diff --git a/_maps/map_files/RandomRuins/SpaceRuins/abandoned_engi_sat.dmm b/_maps/map_files/RandomRuins/SpaceRuins/abandoned_engi_sat.dmm index 4f68f3035fe6..9fcd2da8a0cc 100644 --- a/_maps/map_files/RandomRuins/SpaceRuins/abandoned_engi_sat.dmm +++ b/_maps/map_files/RandomRuins/SpaceRuins/abandoned_engi_sat.dmm @@ -194,6 +194,10 @@ /obj/effect/mapping_helpers/turfs/burn, /turf/simulated/floor/plating, /area/ruin/space/abandoned_engi_sat) +"fs" = ( +/mob/living/simple_animal/hostile/asteroid/hivelord, +/turf/simulated/floor/wood/airless, +/area/ruin/space/abandoned_engi_sat) "fA" = ( /turf/simulated/floor/plasteel, /area/ruin/space/abandoned_engi_sat) @@ -364,6 +368,7 @@ name = "torn sign"; pixel_x = -1 }, +/obj/effect/spawner/random/pool/spaceloot/syndicate/mixed, /turf/simulated/floor/plating, /area/ruin/space/abandoned_engi_sat) "kT" = ( @@ -503,6 +508,7 @@ pixel_y = -24; name = "south bump" }, +/obj/effect/spawner/random/pool/spaceloot/syndicate/mixed, /turf/simulated/floor/plasteel, /area/ruin/space/abandoned_engi_sat) "oL" = ( @@ -546,6 +552,7 @@ /area/ruin/space/abandoned_engi_sat) "pX" = ( /obj/structure/closet/secure_closet/engineering_personal/empty, +/obj/effect/spawner/random/pool/spaceloot/syndicate/mixed, /turf/simulated/floor/wood/airless, /area/ruin/space/abandoned_engi_sat) "qu" = ( @@ -711,6 +718,7 @@ pixel_y = 32 }, /obj/structure/closet/crate/internals, +/obj/effect/spawner/random/pool/spaceloot/syndicate/mixed, /turf/simulated/floor/plasteel{ icon_state = "bot"; dir = 1 @@ -931,6 +939,7 @@ /obj/machinery/light{ dir = 1 }, +/obj/effect/spawner/random/pool/spaceloot/syndicate/mixed, /turf/simulated/floor/plasteel{ icon_state = "vault"; dir = 5 @@ -950,6 +959,10 @@ name = "floor" }, /area/ruin/space/abandoned_engi_sat) +"FN" = ( +/mob/living/simple_animal/hostile/asteroid/hivelord, +/turf/simulated/floor/carpet/airless, +/area/ruin/space/abandoned_engi_sat) "FQ" = ( /obj/machinery/door/airlock/engineering{ name = "Construction Area" @@ -1259,6 +1272,11 @@ dir = 5 }, /area/ruin/space/abandoned_engi_sat) +"RV" = ( +/obj/effect/mapping_helpers/turfs/damage, +/mob/living/simple_animal/hostile/asteroid/hivelord, +/turf/simulated/floor/plasteel, +/area/ruin/space/abandoned_engi_sat) "Sa" = ( /obj/structure/table, /turf/simulated/floor/plasteel{ @@ -1340,6 +1358,10 @@ /obj/effect/decal/cleanable/dirt, /turf/simulated/floor/plating, /area/ruin/space/abandoned_engi_sat) +"Ye" = ( +/mob/living/simple_animal/hostile/asteroid/hivelord, +/turf/simulated/floor/plasteel, +/area/ruin/space/abandoned_engi_sat) "Yz" = ( /obj/structure/closet/emcloset, /turf/simulated/floor/plasteel{ @@ -2089,7 +2111,7 @@ Ux Vx mQ DO -DO +fs DO DO bi @@ -2159,7 +2181,7 @@ kI mG pX hB -nH +FN pX EU EU @@ -2286,9 +2308,9 @@ oL xp gL fA -kd -fA +RV fA +Ye fA eG iV diff --git a/_maps/map_files/RandomRuins/SpaceRuins/abandoned_sec_shuttle.dmm b/_maps/map_files/RandomRuins/SpaceRuins/abandoned_sec_shuttle.dmm index 7012a0b2be79..d972e10bdc6f 100644 --- a/_maps/map_files/RandomRuins/SpaceRuins/abandoned_sec_shuttle.dmm +++ b/_maps/map_files/RandomRuins/SpaceRuins/abandoned_sec_shuttle.dmm @@ -115,6 +115,7 @@ /obj/item/gun/projectile/automatic/pistol/enforcer, /obj/item/grenade/flashbang, /obj/item/storage/firstaid/regular, +/obj/effect/spawner/random/pool/spaceloot/syndicate/mixed, /turf/simulated/floor/plating/airless, /area/ruin/space/sec_shuttle) "F" = ( diff --git a/_maps/map_files/RandomRuins/SpaceRuins/abandonedtele.dmm b/_maps/map_files/RandomRuins/SpaceRuins/abandonedtele.dmm index f7a004b86b90..316003f265a5 100644 --- a/_maps/map_files/RandomRuins/SpaceRuins/abandonedtele.dmm +++ b/_maps/map_files/RandomRuins/SpaceRuins/abandonedtele.dmm @@ -90,6 +90,7 @@ /area/ruin/space/abandtele) "w" = ( /obj/structure/closet, +/obj/effect/spawner/random/pool/spaceloot/syndicate/mixed, /turf/simulated/floor/plating/airless, /area/ruin/space/abandtele) "x" = ( @@ -106,6 +107,7 @@ /obj/item/weldingtool, /obj/item/wrench, /obj/item/circuitboard/teleporter, +/obj/effect/spawner/random/pool/spaceloot/syndicate/mixed, /turf/simulated/floor/plating/airless, /area/ruin/space/abandtele) "z" = ( diff --git a/_maps/map_files/RandomRuins/SpaceRuins/abandonedzoo.dmm b/_maps/map_files/RandomRuins/SpaceRuins/abandonedzoo.dmm index 95312902c673..d6bb7eeb8078 100644 --- a/_maps/map_files/RandomRuins/SpaceRuins/abandonedzoo.dmm +++ b/_maps/map_files/RandomRuins/SpaceRuins/abandonedzoo.dmm @@ -216,7 +216,7 @@ /obj/structure/cable{ icon_state = "4-8" }, -/obj/item/gun/energy/floragun, +/obj/effect/spawner/random/pool/spaceloot/zoo, /turf/simulated/floor/plasteel{ icon_state = "dark" }, @@ -376,7 +376,7 @@ /area/ruin/space/unpowered) "aY" = ( /obj/structure/table/reinforced, -/obj/item/gun/energy/temperature, +/obj/effect/spawner/random/pool/spaceloot/zoo, /turf/simulated/floor/plasteel{ icon_state = "dark" }, diff --git a/_maps/map_files/RandomRuins/SpaceRuins/asteroid1.dmm b/_maps/map_files/RandomRuins/SpaceRuins/asteroid1.dmm index 5ff86b1f4066..9ecd90646cbd 100644 --- a/_maps/map_files/RandomRuins/SpaceRuins/asteroid1.dmm +++ b/_maps/map_files/RandomRuins/SpaceRuins/asteroid1.dmm @@ -9,6 +9,10 @@ "c" = ( /turf/simulated/mineral/random/high_chance, /area/ruin/space/unpowered) +"l" = ( +/obj/effect/spawner/random/pool/spaceloot/syndicate/mixed, +/turf/simulated/floor/plating/asteroid/airless, +/area/ruin/space/unpowered) "V" = ( /turf/template_noop, /area/template_noop) @@ -149,7 +153,7 @@ V V V b -b +l V V V diff --git a/_maps/map_files/RandomRuins/SpaceRuins/asteroid2.dmm b/_maps/map_files/RandomRuins/SpaceRuins/asteroid2.dmm index 521e6b492c4e..5f438bb56c40 100644 --- a/_maps/map_files/RandomRuins/SpaceRuins/asteroid2.dmm +++ b/_maps/map_files/RandomRuins/SpaceRuins/asteroid2.dmm @@ -15,6 +15,10 @@ /obj/structure/spawner/mining/basilisk, /turf/simulated/floor/plating/asteroid/airless, /area/ruin/space/unpowered) +"C" = ( +/obj/effect/spawner/random/pool/spaceloot/syndicate/mixed, +/turf/simulated/floor/plating/asteroid/airless, +/area/ruin/space/unpowered) "R" = ( /obj/structure/spawner/mining/goliath, /turf/simulated/floor/plating/asteroid/airless, @@ -220,7 +224,7 @@ c d c c -c +C c c c @@ -337,7 +341,7 @@ c c c c -c +C c c c diff --git a/_maps/map_files/RandomRuins/SpaceRuins/asteroid3.dmm b/_maps/map_files/RandomRuins/SpaceRuins/asteroid3.dmm index e48592dc2358..3b700b3b0ff5 100644 --- a/_maps/map_files/RandomRuins/SpaceRuins/asteroid3.dmm +++ b/_maps/map_files/RandomRuins/SpaceRuins/asteroid3.dmm @@ -22,6 +22,10 @@ "q" = ( /turf/simulated/mineral/random/low_chance, /area/ruin/space/unpowered) +"r" = ( +/obj/effect/spawner/random/pool/spaceloot/syndicate/mixed, +/turf/simulated/floor/plating/asteroid/airless, +/area/ruin/space/unpowered) "v" = ( /obj/structure/spawner/mining/basilisk, /turf/simulated/floor/plating/asteroid/airless, @@ -175,7 +179,7 @@ q c c c -b +r c c q diff --git a/_maps/map_files/RandomRuins/SpaceRuins/asteroid4.dmm b/_maps/map_files/RandomRuins/SpaceRuins/asteroid4.dmm index 2ac460ad24c3..13a16bcd6425 100644 --- a/_maps/map_files/RandomRuins/SpaceRuins/asteroid4.dmm +++ b/_maps/map_files/RandomRuins/SpaceRuins/asteroid4.dmm @@ -50,6 +50,10 @@ }, /turf/simulated/floor/mineral/titanium/blue, /area/ruin/space/unpowered) +"p" = ( +/obj/effect/spawner/random/pool/spaceloot/syndicate/mixed, +/turf/simulated/floor/plating, +/area/ruin/space/unpowered) "Q" = ( /turf/simulated/mineral/random/low_chance, /area/ruin/space/unpowered) @@ -354,7 +358,7 @@ a c c b -f +p f i i diff --git a/_maps/map_files/RandomRuins/SpaceRuins/asteroid5.dmm b/_maps/map_files/RandomRuins/SpaceRuins/asteroid5.dmm index 313a25539d57..32bbba92f3e4 100644 --- a/_maps/map_files/RandomRuins/SpaceRuins/asteroid5.dmm +++ b/_maps/map_files/RandomRuins/SpaceRuins/asteroid5.dmm @@ -15,6 +15,10 @@ /obj/structure/spawner/mining/goliath, /turf/simulated/floor/plating/asteroid/airless, /area/ruin/space/unpowered) +"o" = ( +/obj/effect/spawner/random/pool/spaceloot/syndicate/mixed, +/turf/simulated/floor/plating/asteroid/airless, +/area/ruin/space/unpowered) "A" = ( /turf/simulated/mineral/random/low_chance, /area/ruin/space/unpowered) @@ -606,7 +610,7 @@ d c c b -d +o d c d diff --git a/_maps/map_files/RandomRuins/SpaceRuins/blowntcommsat.dmm b/_maps/map_files/RandomRuins/SpaceRuins/blowntcommsat.dmm index b7c699afbf25..57bae163401e 100644 --- a/_maps/map_files/RandomRuins/SpaceRuins/blowntcommsat.dmm +++ b/_maps/map_files/RandomRuins/SpaceRuins/blowntcommsat.dmm @@ -51,6 +51,13 @@ }, /turf/simulated/floor/plating/airless, /area/ruin/space/tcommsat) +"cl" = ( +/obj/structure/rack, +/obj/effect/spawner/random/pool/spaceloot/syndicate/mixed, +/turf/simulated/floor/plasteel/airless{ + icon_state = "dark" + }, +/area/ruin/space/tcommsat) "cM" = ( /obj/effect/decal/cleanable/blood/writing{ dir = 8 @@ -207,7 +214,7 @@ }, /area/ruin/space/tcommsat) "lq" = ( -/mob/living/simple_animal/hostile/syndicate/ranged/space/autogib, +/obj/effect/spawner/random/pool/spaceloot/modsuit_syndie, /turf/simulated/floor/plating/airless, /area/ruin/space/tcommsat) "my" = ( @@ -481,6 +488,7 @@ /area/ruin/space/tcommsat) "Go" = ( /obj/structure/table, +/obj/effect/spawner/random/pool/spaceloot/syndicate/mixed, /turf/simulated/floor/plating/airless, /area/ruin/space/tcommsat) "GG" = ( @@ -590,6 +598,10 @@ }, /turf/simulated/floor/plating/airless, /area/ruin/space/tcommsat) +"NC" = ( +/obj/effect/spawner/random/pool/spaceloot/syndicate/mixed, +/turf/simulated/floor/plating/airless, +/area/ruin/space/tcommsat) "NJ" = ( /obj/structure/disposaloutlet{ dir = 4 @@ -632,6 +644,7 @@ dir = 8 }, /obj/structure/closet/firecloset, +/obj/effect/spawner/random/pool/spaceloot/syndicate/mixed, /turf/simulated/floor/plasteel, /area/ruin/space/tcommsat) "PZ" = ( @@ -1241,7 +1254,7 @@ Wc Is ot UK -fS +cl Wr kx Jr @@ -2082,7 +2095,7 @@ Wc Wc Wc Is -Wc +NC Wr kx Jr @@ -2862,7 +2875,7 @@ au Wc ot bc -Wc +NC Wr bc Wc diff --git a/_maps/map_files/RandomRuins/SpaceRuins/casino.dmm b/_maps/map_files/RandomRuins/SpaceRuins/casino.dmm index edea8014ad6b..33b1f8830e20 100644 --- a/_maps/map_files/RandomRuins/SpaceRuins/casino.dmm +++ b/_maps/map_files/RandomRuins/SpaceRuins/casino.dmm @@ -293,6 +293,7 @@ /area/ruin/space/powered/casino/security) "hv" = ( /obj/structure/table/reinforced, +/obj/effect/spawner/random/pool/spaceloot/syndicate/mixed, /turf/simulated/floor/carpet/black, /area/ruin/space/powered/casino/floor) "hJ" = ( @@ -323,6 +324,8 @@ /obj/structure/cable{ icon_state = "4-8" }, +/obj/effect/spawner/random/pool/spaceloot/syndicate/mixed, +/obj/effect/spawner/random/pool/spaceloot/syndicate/mixed, /turf/simulated/floor/mineral/plastitanium, /area/ruin/space/powered/casino/security) "in" = ( @@ -382,6 +385,7 @@ /area/ruin/space/powered/casino/arrivals) "jz" = ( /obj/structure/closet/cabinet, +/obj/effect/spawner/random/pool/spaceloot/syndicate/mixed, /turf/simulated/floor/plating, /area/ruin/space/powered/casino/floor) "jJ" = ( @@ -660,6 +664,7 @@ "rh" = ( /obj/structure/grille/broken, /obj/structure/closet/crate/trashcart, +/obj/effect/spawner/random/pool/spaceloot/syndicate/mixed, /turf/simulated/floor/plating, /area/ruin/space/powered/casino/maints) "rp" = ( @@ -802,6 +807,7 @@ dir = 8 }, /obj/effect/mob_spawn/human/corpse/random_species/gambler, +/obj/effect/spawner/random/pool/spaceloot/syndicate/mixed, /turf/simulated/floor/plasteel/freezer, /area/ruin/space/powered/casino/hall) "wo" = ( @@ -1111,6 +1117,13 @@ }, /turf/simulated/floor/plasteel/dark, /area/ruin/space/powered/casino/arrivals) +"EK" = ( +/obj/structure/table, +/obj/effect/spawner/random/pool/spaceloot/syndicate/mixed, +/turf/simulated/floor/plasteel{ + icon_state = "cafeteria" + }, +/area/ruin/space/powered/casino/kitchen) "EZ" = ( /obj/machinery/door/airlock/maintenance, /obj/effect/spawner/random/dirt/maybe, @@ -1310,6 +1323,7 @@ "Nh" = ( /obj/structure/table/reinforced, /obj/item/tank/internals/oxygen, +/obj/effect/spawner/random/pool/spaceloot/syndicate/mixed, /turf/simulated/floor/mineral/plastitanium/red, /area/ruin/space/powered/casino/docked_ships) "Nj" = ( @@ -1368,6 +1382,13 @@ }, /turf/simulated/floor/plating, /area/ruin/space/powered/casino/security) +"OZ" = ( +/obj/structure/closet/secure_closet/freezer/fridge, +/obj/effect/spawner/random/pool/spaceloot/syndicate/mixed, +/turf/simulated/floor/plasteel{ + icon_state = "showroomfloor" + }, +/area/ruin/space/powered/casino/kitchen) "Pz" = ( /obj/structure/chair/wood{ dir = 8 @@ -2222,7 +2243,7 @@ cc cc fT sO -UO +OZ RS Is Is @@ -2454,7 +2475,7 @@ An IS sO UW -DM +EK ql DM sO diff --git a/_maps/map_files/RandomRuins/SpaceRuins/clownmime.dmm b/_maps/map_files/RandomRuins/SpaceRuins/clownmime.dmm index c353cfd9ef06..65170fd4d134 100644 --- a/_maps/map_files/RandomRuins/SpaceRuins/clownmime.dmm +++ b/_maps/map_files/RandomRuins/SpaceRuins/clownmime.dmm @@ -73,6 +73,7 @@ /obj/structure/window/reinforced{ dir = 1 }, +/obj/effect/spawner/random/pool/spaceloot/syndicate/mixed, /turf/simulated/floor/mineral/tranquillite, /area/ruin/space/powered) "fS" = ( @@ -732,6 +733,13 @@ /obj/effect/mapping_helpers/turfs/burn, /turf/simulated/floor/mineral/titanium, /area/ruin/space/clown_mime_ruin) +"OZ" = ( +/obj/effect/mapping_helpers/turfs/damage, +/obj/effect/mapping_helpers/turfs/burn, +/obj/item/stack/sheet/wood, +/obj/effect/spawner/random/pool/spaceloot/syndicate/mixed, +/turf/simulated/floor/mineral/plastitanium, +/area/ruin/space/clown_mime_ruin) "Pt" = ( /obj/structure/table/reinforced, /obj/effect/spawner/random/maintenance, @@ -1079,7 +1087,7 @@ OK nX wP Bb -TC +OZ nX tN tN diff --git a/_maps/map_files/RandomRuins/SpaceRuins/debris1.dmm b/_maps/map_files/RandomRuins/SpaceRuins/debris1.dmm index 354deb775f47..fb4e77a195c7 100644 --- a/_maps/map_files/RandomRuins/SpaceRuins/debris1.dmm +++ b/_maps/map_files/RandomRuins/SpaceRuins/debris1.dmm @@ -149,6 +149,10 @@ }, /turf/simulated/floor/plating/burnt/airless, /area/template_noop) +"QL" = ( +/obj/effect/spawner/random/pool/spaceloot/syndicate/mixed, +/turf/simulated/floor/plating/burnt/airless, +/area/template_noop) (1,1,1) = {" aa @@ -359,7 +363,7 @@ aa ay ad ml -ay +QL aU aa aa diff --git a/_maps/map_files/RandomRuins/SpaceRuins/debris2.dmm b/_maps/map_files/RandomRuins/SpaceRuins/debris2.dmm index ff51a70a0aa7..586ce7c912ac 100644 --- a/_maps/map_files/RandomRuins/SpaceRuins/debris2.dmm +++ b/_maps/map_files/RandomRuins/SpaceRuins/debris2.dmm @@ -129,6 +129,11 @@ /obj/machinery/computer/pandemic, /turf/simulated/floor/plasteel/airless, /area/template_noop) +"Di" = ( +/obj/effect/mapping_helpers/turfs/burn, +/obj/effect/spawner/random/pool/spaceloot/syndicate/mixed, +/turf/simulated/floor/plasteel/airless, +/area/template_noop) (1,1,1) = {" aa @@ -179,7 +184,7 @@ aa ad aG aA -aM +Di aF ad as diff --git a/_maps/map_files/RandomRuins/SpaceRuins/debris3.dmm b/_maps/map_files/RandomRuins/SpaceRuins/debris3.dmm index 419dbd23ad01..e8f94ba21d85 100644 --- a/_maps/map_files/RandomRuins/SpaceRuins/debris3.dmm +++ b/_maps/map_files/RandomRuins/SpaceRuins/debris3.dmm @@ -128,6 +128,10 @@ /obj/item/stack/sheet/metal, /turf/template_noop, /area/template_noop) +"P" = ( +/obj/effect/spawner/random/pool/spaceloot/syndicate/mixed, +/turf/simulated/floor/plating/damaged/airless, +/area/template_noop) "Q" = ( /obj/structure/girder, /turf/template_noop, @@ -529,7 +533,7 @@ U v a O -z +P z a a diff --git a/_maps/map_files/RandomRuins/SpaceRuins/deepstorage.dmm b/_maps/map_files/RandomRuins/SpaceRuins/deepstorage.dmm index b90406f23bdc..e062d4b683c5 100644 --- a/_maps/map_files/RandomRuins/SpaceRuins/deepstorage.dmm +++ b/_maps/map_files/RandomRuins/SpaceRuins/deepstorage.dmm @@ -5997,9 +5997,9 @@ /area/ruin/space/deepstorage) "MR" = ( /obj/structure/rack, -/obj/item/paper/researchnotes, /obj/effect/turf_decal/delivery/hollow, -/obj/effect/spawner/random/deepstorage_reward/main, +/obj/effect/spawner/random/pool/spaceloot/deepstorage/main, +/obj/item/paper/researchnotes, /turf/simulated/floor/plasteel{ dir = 6; icon_state = "vault" diff --git a/_maps/map_files/RandomRuins/SpaceRuins/derelict1.dmm b/_maps/map_files/RandomRuins/SpaceRuins/derelict1.dmm index 69e8353e31ac..97cf1402ced1 100644 --- a/_maps/map_files/RandomRuins/SpaceRuins/derelict1.dmm +++ b/_maps/map_files/RandomRuins/SpaceRuins/derelict1.dmm @@ -94,6 +94,12 @@ /mob/living/simple_animal/hostile/alien, /turf/simulated/floor/plating/airless, /area/ruin/space/unpowered) +"I" = ( +/obj/structure/alien/weeds, +/obj/structure/table, +/obj/effect/spawner/random/pool/spaceloot/syndicate/mixed, +/turf/simulated/floor/plating/airless, +/area/ruin/space/unpowered) "S" = ( /obj/structure/alien/weeds, /obj/structure/bed/nest, @@ -609,8 +615,8 @@ f G f c -m -m +I +I f c b diff --git a/_maps/map_files/RandomRuins/SpaceRuins/derelict3.dmm b/_maps/map_files/RandomRuins/SpaceRuins/derelict3.dmm index 20fe6a14d08c..21868b544b64 100644 --- a/_maps/map_files/RandomRuins/SpaceRuins/derelict3.dmm +++ b/_maps/map_files/RandomRuins/SpaceRuins/derelict3.dmm @@ -47,6 +47,10 @@ /obj/effect/decal/remains/human, /turf/simulated/floor/plating/airless, /area/ruin/space/unpowered) +"H" = ( +/obj/effect/spawner/random/pool/spaceloot/syndicate/mixed, +/turf/simulated/floor/plating/airless, +/area/ruin/space/unpowered) "O" = ( /mob/living/simple_animal/hostile/carp, /turf/simulated/floor/plating/airless, @@ -852,7 +856,7 @@ d d b c -b +H b b b @@ -1090,7 +1094,7 @@ b b b c -b +H b b b diff --git a/_maps/map_files/RandomRuins/SpaceRuins/derelict4.dmm b/_maps/map_files/RandomRuins/SpaceRuins/derelict4.dmm index 9d3a9e8bf61e..48208579bf65 100644 --- a/_maps/map_files/RandomRuins/SpaceRuins/derelict4.dmm +++ b/_maps/map_files/RandomRuins/SpaceRuins/derelict4.dmm @@ -61,6 +61,7 @@ /area/ruin/space/unpowered) "p" = ( /obj/structure/table, +/obj/effect/spawner/random/pool/spaceloot/syndicate/mixed, /turf/simulated/floor/mineral/titanium/blue/airless, /area/ruin/space/unpowered) "q" = ( diff --git a/_maps/map_files/RandomRuins/SpaceRuins/derelict5.dmm b/_maps/map_files/RandomRuins/SpaceRuins/derelict5.dmm index a57154509b6a..400c52a36c72 100644 --- a/_maps/map_files/RandomRuins/SpaceRuins/derelict5.dmm +++ b/_maps/map_files/RandomRuins/SpaceRuins/derelict5.dmm @@ -83,6 +83,10 @@ /obj/machinery/kitchen_machine/microwave, /turf/simulated/floor/plasteel, /area/ruin/space/unpowered) +"lE" = ( +/obj/effect/spawner/random/pool/spaceloot/syndicate/mixed, +/turf/simulated/floor/plasteel, +/area/ruin/space/unpowered) "mn" = ( /obj/structure/closet/crate, /obj/item/toy/plushie/nianplushie, @@ -241,6 +245,7 @@ /area/ruin/space/unpowered) "LA" = ( /obj/structure/table, +/obj/effect/spawner/random/pool/spaceloot/syndicate/mixed, /turf/simulated/floor/plasteel, /area/ruin/space/unpowered) "LD" = ( @@ -1324,7 +1329,7 @@ Qx Qx Qx Qx -zN +lE vE hG bO diff --git a/_maps/map_files/RandomRuins/SpaceRuins/dj.dmm b/_maps/map_files/RandomRuins/SpaceRuins/dj.dmm index 6894f69abde8..591be2b910a3 100644 --- a/_maps/map_files/RandomRuins/SpaceRuins/dj.dmm +++ b/_maps/map_files/RandomRuins/SpaceRuins/dj.dmm @@ -525,6 +525,7 @@ "bt" = ( /obj/effect/decal/cleanable/dirt, /obj/structure/closet/crate/can, +/obj/effect/spawner/random/pool/spaceloot/syndicate/mixed, /turf/simulated/floor/plasteel{ icon_state = "bar" }, @@ -694,6 +695,7 @@ pixel_y = 2 }, /obj/effect/decal/cleanable/dirt, +/obj/effect/spawner/random/pool/spaceloot/syndicate/mixed, /turf/simulated/floor/plasteel{ icon_state = "freezerfloor" }, diff --git a/_maps/map_files/RandomRuins/SpaceRuins/druglab.dmm b/_maps/map_files/RandomRuins/SpaceRuins/druglab.dmm index eacc7acf7711..a349099a7768 100644 --- a/_maps/map_files/RandomRuins/SpaceRuins/druglab.dmm +++ b/_maps/map_files/RandomRuins/SpaceRuins/druglab.dmm @@ -13,6 +13,7 @@ /area/ruin/space/methlab) "d" = ( /obj/structure/closet/crate, +/obj/effect/spawner/random/pool/spaceloot/syndicate/mixed, /turf/simulated/floor/plating, /area/ruin/space/methlab) "e" = ( diff --git a/_maps/map_files/RandomRuins/SpaceRuins/emptyshell.dmm b/_maps/map_files/RandomRuins/SpaceRuins/emptyshell.dmm index 3a6699cffbc3..324ba02d8fc6 100644 --- a/_maps/map_files/RandomRuins/SpaceRuins/emptyshell.dmm +++ b/_maps/map_files/RandomRuins/SpaceRuins/emptyshell.dmm @@ -40,6 +40,10 @@ /mob/living/simple_animal/hostile/asteroid/hivelord, /turf/simulated/floor/plating, /area/ruin/space/unpowered) +"t" = ( +/obj/effect/spawner/random/pool/spaceloot/syndicate/mixed, +/turf/simulated/floor/plating, +/area/ruin/space/unpowered) "T" = ( /obj/item/salvage/ruin/tablet, /turf/simulated/floor/plating, @@ -301,7 +305,7 @@ c c d d -d +t d d d diff --git a/_maps/map_files/RandomRuins/SpaceRuins/freighter.dmm b/_maps/map_files/RandomRuins/SpaceRuins/freighter.dmm index 4f1796e639a3..baf8278e10d0 100644 --- a/_maps/map_files/RandomRuins/SpaceRuins/freighter.dmm +++ b/_maps/map_files/RandomRuins/SpaceRuins/freighter.dmm @@ -153,7 +153,7 @@ /area/ruin/space/powered) "nq" = ( /obj/structure/closet/crate, -/obj/item/banhammer, +/obj/effect/spawner/random/pool/spaceloot/syndicate/mixed, /turf/simulated/floor/mineral/plastitanium, /area/ruin/space/powered) "nD" = ( @@ -184,6 +184,7 @@ /area/ruin/space/powered) "rV" = ( /obj/structure/closet/crate/secure/loot, +/obj/effect/spawner/random/pool/spaceloot/syndicate/mixed, /turf/simulated/floor/mineral/plastitanium, /area/ruin/space/powered) "st" = ( @@ -254,6 +255,7 @@ /obj/structure/safe, /obj/item/id_decal/gold, /obj/item/stack/spacecash/c200, +/obj/effect/spawner/random/pool/spaceloot/syndicate/mixed, /turf/simulated/floor/plasteel{ dir = 5; icon_state = "caution" diff --git a/_maps/map_files/RandomRuins/SpaceRuins/intactemptyship.dmm b/_maps/map_files/RandomRuins/SpaceRuins/intactemptyship.dmm index f13694d1e1d2..60ebb6538381 100644 --- a/_maps/map_files/RandomRuins/SpaceRuins/intactemptyship.dmm +++ b/_maps/map_files/RandomRuins/SpaceRuins/intactemptyship.dmm @@ -136,6 +136,11 @@ /obj/item/salvage/ruin/tablet, /turf/simulated/floor/mineral/titanium/purple, /area/ruin/space/powered) +"U" = ( +/obj/structure/closet, +/obj/effect/spawner/random/pool/spaceloot/syndicate/mixed, +/turf/simulated/floor/mineral/titanium/purple, +/area/ruin/space/powered) (1,1,1) = {" a @@ -322,7 +327,7 @@ a a a b -j +U r w Q diff --git a/_maps/map_files/RandomRuins/SpaceRuins/listeningpost.dmm b/_maps/map_files/RandomRuins/SpaceRuins/listeningpost.dmm index d068c1d38ffe..7d2518499e27 100644 --- a/_maps/map_files/RandomRuins/SpaceRuins/listeningpost.dmm +++ b/_maps/map_files/RandomRuins/SpaceRuins/listeningpost.dmm @@ -136,6 +136,10 @@ icon_state = "solarpanel" }, /area/ruin/space/syndicate_listening_station/asteroid) +"nk" = ( +/obj/effect/spawner/random/pool/spaceloot/syndicate/mixed, +/turf/simulated/floor/mineral/silver, +/area/ruin/space/syndicate_listening_station) "oE" = ( /obj/effect/decal/cleanable/dirt, /obj/machinery/floodlight, @@ -323,6 +327,7 @@ /obj/item/storage/box/tapes, /obj/item/taperecorder, /obj/item/clothing/glasses/regular, +/obj/effect/spawner/random/pool/spaceloot/syndicate/mixed, /turf/simulated/floor/plasteel/dark, /area/ruin/space/syndicate_listening_station) "AT" = ( @@ -550,6 +555,7 @@ /obj/item/clothing/shoes/slippers, /obj/item/clothing/under/misc/pj/red, /obj/item/clothing/suit/jacket/bomber/syndicate, +/obj/effect/spawner/random/pool/spaceloot/syndicate/mixed, /turf/simulated/floor/wood, /area/ruin/space/syndicate_listening_station) "RN" = ( @@ -1541,7 +1547,7 @@ yn yn kJ KM -Nd +nk kJ PH le diff --git a/_maps/map_files/RandomRuins/SpaceRuins/meatpackers.dmm b/_maps/map_files/RandomRuins/SpaceRuins/meatpackers.dmm index f63dd9362487..7b21d55fd076 100644 --- a/_maps/map_files/RandomRuins/SpaceRuins/meatpackers.dmm +++ b/_maps/map_files/RandomRuins/SpaceRuins/meatpackers.dmm @@ -63,6 +63,7 @@ "ap" = ( /obj/item/restraints/handcuffs, /obj/structure/closet/crate, +/obj/effect/spawner/random/pool/spaceloot/syndicate/mixed, /turf/simulated/floor/plating/airless, /area/ruin/unpowered/bmp_ship/delta) "aq" = ( @@ -193,6 +194,7 @@ "aP" = ( /obj/item/stack/spacecash/c50, /obj/item/stack/spacecash/c100, +/obj/effect/spawner/random/pool/spaceloot/syndicate/mixed, /turf/simulated/floor/wood, /area/ruin/unpowered/bmp_ship/fore) "aQ" = ( @@ -211,6 +213,7 @@ /obj/effect/turf_decal/stripes/line{ dir = 1 }, +/obj/effect/spawner/random/pool/spaceloot/syndicate/mixed, /turf/simulated/floor/plating, /area/ruin/unpowered/bmp_ship/fore) "aT" = ( @@ -713,6 +716,7 @@ /obj/structure/closet/secure_closet/freezer/meat{ opened = 1 }, +/obj/effect/spawner/random/pool/spaceloot/syndicate/mixed, /turf/simulated/floor/plasteel{ icon_state = "white" }, @@ -2198,11 +2202,13 @@ /obj/structure/closet/crate/freezer, /obj/item/food/meat, /obj/item/food/hugemushroomslice, -/obj/effect/turf_decal/stripes/line{ - dir = 2 - }, +/obj/effect/turf_decal/stripes/line, /turf/simulated/floor/plating, /area/ruin/unpowered/bmp_ship/delta) +"PE" = ( +/obj/effect/spawner/random/pool/spaceloot/syndicate/mixed, +/turf/simulated/floor/plating, +/area/ruin/unpowered/bmp_ship/aft) "PP" = ( /obj/structure/computerframe{ dir = 4 @@ -4671,7 +4677,7 @@ cl cv eb ex -dG +PE dG dG fu diff --git a/_maps/map_files/RandomRuins/SpaceRuins/mechtransport.dmm b/_maps/map_files/RandomRuins/SpaceRuins/mechtransport.dmm index 393125e60ced..8ecdc1fa8d32 100644 --- a/_maps/map_files/RandomRuins/SpaceRuins/mechtransport.dmm +++ b/_maps/map_files/RandomRuins/SpaceRuins/mechtransport.dmm @@ -21,6 +21,7 @@ /area/ruin/space/mech_transport) "aZ" = ( /obj/structure/closet/crate/secure/loot, +/obj/effect/spawner/random/pool/spaceloot/syndicate/mixed, /turf/simulated/floor/plasteel/dark, /area/ruin/space/mech_transport) "bk" = ( @@ -101,10 +102,10 @@ /area/ruin/space/mech_transport) "hm" = ( /obj/structure/table, -/obj/item/mecha_parts/core, /obj/structure/sign/poster/contraband/tools{ pixel_y = 32 }, +/obj/effect/spawner/random/pool/spaceloot/mechtransport/storage4, /turf/simulated/floor/plasteel/dark, /area/ruin/space/mech_transport) "hu" = ( @@ -121,12 +122,7 @@ /area/ruin/space/mech_transport) "hW" = ( /obj/structure/table, -/obj/item/mecha_parts/mecha_equipment/repair_droid, -/obj/item/mecha_parts/mecha_equipment/extinguisher, -/obj/item/mecha_modkit/voice/honk{ - pixel_y = 10; - pixel_x = 3 - }, +/obj/effect/spawner/random/pool/spaceloot/mechtransport/storage1, /turf/simulated/floor/plasteel/dark, /area/ruin/space/mech_transport) "iG" = ( @@ -164,6 +160,7 @@ }, /obj/machinery/door/window, /obj/effect/decal/cleanable/cobweb, +/obj/effect/spawner/random/pool/spaceloot/syndicate/mixed, /turf/simulated/floor/plasteel/dark, /area/ruin/space/mech_transport) "od" = ( @@ -201,6 +198,7 @@ /area/ruin/space/mech_transport) "pJ" = ( /obj/structure/closet/firecloset, +/obj/effect/spawner/random/pool/spaceloot/syndicate/mixed, /turf/simulated/floor/mineral/plastitanium/red/airless, /area/ruin/space/mech_transport) "qs" = ( @@ -212,7 +210,6 @@ "qE" = ( /obj/effect/turf_decal/delivery/hollow, /obj/structure/sign/nosmoking_1{ - pixel_y = 0; pixel_x = 32 }, /obj/effect/mapping_helpers/turfs/burn, @@ -248,7 +245,6 @@ "sr" = ( /obj/structure/rack, /obj/item/stack/sheet/glass/fifty{ - pixel_y = 0; pixel_x = -2 }, /obj/item/stack/sheet/metal/fifty{ @@ -263,6 +259,7 @@ /area/ruin/space/mech_transport) "sY" = ( /obj/structure/closet, +/obj/effect/spawner/random/pool/spaceloot/syndicate/mixed, /turf/simulated/floor/plating, /area/ruin/space/mech_transport) "ta" = ( @@ -313,13 +310,7 @@ /area/ruin/space/mech_transport) "wo" = ( /obj/structure/table, -/obj/item/mecha_parts/mecha_equipment/drill, -/obj/item/mecha_parts/mecha_equipment/drill{ - pixel_y = 10 - }, -/obj/item/mecha_parts/mecha_equipment/drill/diamonddrill{ - pixel_y = 4 - }, +/obj/effect/spawner/random/pool/spaceloot/mechtransport/storage2, /turf/simulated/floor/plasteel/dark, /area/ruin/space/mech_transport) "wz" = ( @@ -542,7 +533,7 @@ /area/ruin/space/mech_transport) "MK" = ( /obj/structure/table, -/obj/item/mecha_parts/mecha_equipment/medical/sleeper, +/obj/effect/spawner/random/pool/spaceloot/mechtransport/storage3, /turf/simulated/floor/plasteel/dark, /area/ruin/space/mech_transport) "Nc" = ( diff --git a/_maps/map_files/RandomRuins/SpaceRuins/moonoutpost19.dmm b/_maps/map_files/RandomRuins/SpaceRuins/moonoutpost19.dmm index 525d34dae908..6dd7ac7ae041 100644 --- a/_maps/map_files/RandomRuins/SpaceRuins/moonoutpost19.dmm +++ b/_maps/map_files/RandomRuins/SpaceRuins/moonoutpost19.dmm @@ -4992,7 +4992,7 @@ /obj/effect/decal/cleanable/cobweb2, /obj/effect/turf_decal/delivery/hollow, /obj/structure/rack, -/obj/item/paper/researchnotes, +/obj/effect/spawner/random/pool/spaceloot/moonoutpost19/vault1, /turf/simulated/floor/plasteel{ icon_state = "dark" }, @@ -5921,9 +5921,8 @@ /area/ruin/space/moonbase19) "vh" = ( /obj/structure/rack, -/obj/item/mecha_parts/core, /obj/effect/turf_decal/delivery/hollow, -/obj/item/stock_parts/cell/infinite/abductor, +/obj/effect/spawner/random/pool/spaceloot/moonoutpost19/vault3, /turf/simulated/floor/plasteel{ icon_state = "dark" }, @@ -8137,8 +8136,7 @@ }, /obj/effect/decal/cleanable/dirt, /obj/effect/turf_decal/delivery/hollow, -/obj/item/assembly/signaler/anomaly/random, -/obj/item/storage/lockbox/experimental_weapon, +/obj/effect/spawner/random/pool/spaceloot/moonoutpost19/vault2, /turf/simulated/floor/plasteel{ icon_state = "dark" }, diff --git a/_maps/map_files/RandomRuins/SpaceRuins/onehalf.dmm b/_maps/map_files/RandomRuins/SpaceRuins/onehalf.dmm index af97fb7f18aa..0ffd2a49d583 100644 --- a/_maps/map_files/RandomRuins/SpaceRuins/onehalf.dmm +++ b/_maps/map_files/RandomRuins/SpaceRuins/onehalf.dmm @@ -1030,6 +1030,7 @@ /area/ruin/space/onehalf/abandonedbridge) "dd" = ( /obj/structure/closet/firecloset/full, +/obj/effect/spawner/random/pool/spaceloot/syndicate/mixed, /turf/simulated/floor/plasteel, /area/ruin/space/onehalf/abandonedbridge) "de" = ( @@ -1122,6 +1123,11 @@ /mob/living/simple_animal/hostile/carp, /turf/template_noop, /area/template_noop) +"jI" = ( +/obj/structure/disposalpipe/trunk, +/obj/effect/spawner/random/pool/spaceloot/syndicate/mixed, +/turf/simulated/floor/plating/airless, +/area/ruin/space/onehalf/drone_bay) "jQ" = ( /obj/structure/cable{ icon_state = "0-8" @@ -1548,7 +1554,7 @@ aa aa aa as -aE +jI aM ba bo @@ -1680,7 +1686,7 @@ aa aa aa av -aE +jI aR by bo diff --git a/_maps/map_files/RandomRuins/SpaceRuins/rocky_motel.dmm b/_maps/map_files/RandomRuins/SpaceRuins/rocky_motel.dmm index 08a28a4cfd0d..141a1e5e9276 100644 --- a/_maps/map_files/RandomRuins/SpaceRuins/rocky_motel.dmm +++ b/_maps/map_files/RandomRuins/SpaceRuins/rocky_motel.dmm @@ -38,6 +38,7 @@ /obj/structure/toilet{ dir = 4 }, +/obj/effect/spawner/random/pool/spaceloot/syndicate/mixed, /turf/simulated/floor/plasteel{ icon_state = "freezerfloor" }, @@ -46,6 +47,7 @@ /obj/structure/closet/cabinet, /obj/item/clothing/under/color/random, /obj/item/clothing/under/dress/sundress, +/obj/effect/spawner/random/pool/spaceloot/syndicate/mixed, /turf/simulated/floor/carpet/black, /area/ruin/space/powered) "fH" = ( @@ -74,6 +76,7 @@ "gP" = ( /obj/structure/table/wood, /obj/effect/mapping_helpers/turfs/damage, +/obj/effect/spawner/random/pool/spaceloot/syndicate/mixed, /turf/simulated/floor/wood, /area/ruin/space/powered) "gY" = ( diff --git a/_maps/map_files/RandomRuins/SpaceRuins/spacebar.dmm b/_maps/map_files/RandomRuins/SpaceRuins/spacebar.dmm index e72adf279475..e67ddd0b3b2b 100644 --- a/_maps/map_files/RandomRuins/SpaceRuins/spacebar.dmm +++ b/_maps/map_files/RandomRuins/SpaceRuins/spacebar.dmm @@ -127,6 +127,7 @@ /area/ruin/space/powered/bar) "aF" = ( /obj/structure/closet/secure_closet/freezer/kitchen, +/obj/effect/spawner/random/pool/spaceloot/syndicate/mixed, /turf/simulated/floor/wood, /area/ruin/space/powered/bar) "aG" = ( @@ -134,6 +135,7 @@ /area/ruin/space/powered) "aH" = ( /obj/structure/closet/secure_closet/freezer/fridge, +/obj/effect/spawner/random/pool/spaceloot/syndicate/mixed, /turf/simulated/floor/wood, /area/ruin/space/powered/bar) "aI" = ( @@ -456,6 +458,7 @@ /obj/machinery/light{ dir = 8 }, +/obj/effect/spawner/random/pool/spaceloot/syndicate/mixed, /turf/simulated/floor/plasteel{ icon_state = "dark" }, diff --git a/_maps/map_files/RandomRuins/SpaceRuins/syndicatedruglab.dmm b/_maps/map_files/RandomRuins/SpaceRuins/syndicatedruglab.dmm index 096d63d14423..7cca9d8aac26 100644 --- a/_maps/map_files/RandomRuins/SpaceRuins/syndicatedruglab.dmm +++ b/_maps/map_files/RandomRuins/SpaceRuins/syndicatedruglab.dmm @@ -1,6 +1,7 @@ //MAP CONVERTED BY dmm2tgm.py THIS HEADER COMMENT PREVENTS RECONVERSION, DO NOT REMOVE "cq" = ( /obj/structure/table, +/obj/effect/spawner/random/pool/spaceloot/syndicate/mixed, /turf/simulated/floor/pod/dark, /area/ruin/space/syndicate_druglab) "dL" = ( @@ -267,7 +268,7 @@ /area/ruin/space/syndicate_druglab) "Fq" = ( /obj/structure/closet/cabinet, -/obj/item/soap/syndie, +/obj/effect/spawner/random/pool/spaceloot/syndicate/mixed, /turf/simulated/floor/carpet/black, /area/ruin/space/syndicate_druglab) "Fx" = ( diff --git a/_maps/map_files/RandomRuins/SpaceRuins/syndie_space_base.dmm b/_maps/map_files/RandomRuins/SpaceRuins/syndie_space_base.dmm index 46ce3149055e..d1b78f2c22c4 100644 --- a/_maps/map_files/RandomRuins/SpaceRuins/syndie_space_base.dmm +++ b/_maps/map_files/RandomRuins/SpaceRuins/syndie_space_base.dmm @@ -1955,6 +1955,9 @@ /obj/structure/cable/green{ icon_state = "1-2" }, +/obj/structure/cable/green{ + icon_state = "1-4" + }, /turf/simulated/floor/plasteel{ icon_state = "dark" }, @@ -2419,6 +2422,9 @@ }, /turf/simulated/floor/engine, /area/ruin/unpowered/syndicate_space_base/toxtest) +"nV" = ( +/turf/simulated/wall/mineral/plastitanium/nodiagonal, +/area/ruin/unpowered/syndicate_space_base/inner) "nW" = ( /obj/machinery/atmospherics/pipe/simple/hidden/scrubbers{ dir = 4 @@ -2813,11 +2819,18 @@ }, /area/ruin/unpowered/syndicate_space_base/genetics) "qf" = ( -/obj/machinery/economy/arcade/claw, -/turf/simulated/floor/plasteel{ - icon_state = "dark" +/obj/structure/cable/green, +/obj/machinery/power/apc/syndicate/directional/east, +/obj/machinery/light/small{ + dir = 8 }, -/area/ruin/unpowered/syndicate_space_base/arrivals) +/obj/item/toy/plushie/lizardplushie{ + name = "Forks-the-Outlet" + }, +/turf/simulated/floor/plating{ + icon_state = "asteroidplating" + }, +/area/ruin/unpowered/syndicate_space_base/cave) "qj" = ( /obj/machinery/light, /obj/machinery/camera{ @@ -2946,6 +2959,10 @@ icon_state = "yellow" }, /area/ruin/unpowered/syndicate_space_base/atmos) +"rd" = ( +/obj/structure/sign/electricshock, +/turf/simulated/wall/mineral/plastitanium/nodiagonal, +/area/ruin/unpowered/syndicate_space_base/main) "rg" = ( /obj/machinery/atmospherics/pipe/simple/hidden/scrubbers, /obj/machinery/atmospherics/pipe/manifold/hidden/supply{ @@ -3198,6 +3215,9 @@ /obj/machinery/atmospherics/pipe/simple/hidden/scrubbers{ dir = 10 }, +/obj/structure/cable/green{ + icon_state = "2-8" + }, /turf/simulated/floor/plasteel{ icon_state = "dark" }, @@ -3442,6 +3462,9 @@ codes_txt = "patrol;next_patrol=SBW6"; location = "SBW5" }, +/obj/structure/cable/green{ + icon_state = "4-8" + }, /turf/simulated/floor/plasteel{ icon_state = "dark" }, @@ -4042,6 +4065,12 @@ icon_state = "dark" }, /area/ruin/unpowered/syndicate_space_base/toxlaunch) +"xM" = ( +/obj/machinery/economy/arcade/claw/syndi, +/turf/simulated/floor/plasteel{ + icon_state = "dark" + }, +/area/ruin/unpowered/syndicate_space_base/arrivals) "xO" = ( /obj/machinery/alarm/syndicate/directional/north, /turf/simulated/floor/plasteel{ @@ -4102,6 +4131,20 @@ icon_state = "dark" }, /area/ruin/unpowered/syndicate_space_base/arrivals) +"ye" = ( +/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers{ + dir = 4 + }, +/obj/machinery/atmospherics/pipe/simple/hidden/supply{ + dir = 4 + }, +/obj/machinery/light{ + dir = 1 + }, +/turf/simulated/floor/plasteel{ + icon_state = "dark" + }, +/area/ruin/unpowered/syndicate_space_base/arrivals) "yf" = ( /obj/effect/turf_decal/caution{ dir = 8 @@ -5295,6 +5338,9 @@ /obj/machinery/atmospherics/pipe/simple/hidden/supply{ dir = 10 }, +/obj/structure/cable/green{ + icon_state = "4-8" + }, /turf/simulated/floor/plasteel{ icon_state = "dark" }, @@ -7163,6 +7209,18 @@ icon_state = "darkpurple" }, /area/ruin/unpowered/syndicate_space_base/chemistry) +"RM" = ( +/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers{ + dir = 4 + }, +/obj/machinery/atmospherics/pipe/simple/hidden/supply{ + dir = 4 + }, +/obj/machinery/light, +/turf/simulated/floor/plasteel{ + icon_state = "dark" + }, +/area/ruin/unpowered/syndicate_space_base/arrivals) "RN" = ( /obj/machinery/reagentgrinder, /obj/item/stack/sheet/mineral/plasma{ @@ -7214,6 +7272,16 @@ }, /turf/simulated/floor/wood, /area/ruin/unpowered/syndicate_space_base/arrivals) +"RW" = ( +/obj/machinery/door/airlock/hatch/syndicate, +/obj/machinery/door/firedoor, +/obj/structure/cable/green{ + icon_state = "1-2" + }, +/turf/simulated/floor/plasteel{ + icon_state = "dark" + }, +/area/ruin/unpowered/syndicate_space_base/main) "RX" = ( /turf/simulated/wall/mineral/plastitanium/nodiagonal, /area/ruin/unpowered/syndicate_space_base/main) @@ -7593,6 +7661,9 @@ /obj/machinery/atmospherics/unary/vent_scrubber/on{ dir = 1 }, +/obj/structure/cable/green{ + icon_state = "1-2" + }, /turf/simulated/floor/plasteel{ icon_state = "dark" }, @@ -9416,12 +9487,12 @@ xn xn xn xn -My +ye ma nZ kk ZI -My +RM xn xn xn @@ -9996,7 +10067,7 @@ xn xn xn xn -qf +xM xQ xQ My @@ -10069,7 +10140,7 @@ kE kE kE xn -qf +xM xQ vR nW @@ -11995,8 +12066,8 @@ wA PL sV TK -RX -kE +RW +qf kE kE kE @@ -12068,8 +12139,8 @@ hO PL am am -RX -kE +rd +nV kE kE kE diff --git a/_maps/map_files/RandomRuins/SpaceRuins/syndiecakesfactory.dmm b/_maps/map_files/RandomRuins/SpaceRuins/syndiecakesfactory.dmm index 0fef45873213..30e727b81cba 100644 --- a/_maps/map_files/RandomRuins/SpaceRuins/syndiecakesfactory.dmm +++ b/_maps/map_files/RandomRuins/SpaceRuins/syndiecakesfactory.dmm @@ -742,7 +742,7 @@ /area/template_noop) "CR" = ( /obj/structure/chair/office/dark, -/mob/living/simple_animal/hostile/syndicate/ranged/space/autogib, +/obj/effect/spawner/random/pool/spaceloot/modsuit_syndie, /turf/simulated/floor/engine, /area/ruin/space/syndicakefactory) "CW" = ( @@ -908,6 +908,13 @@ /obj/item/stack/sheet/animalhide/corgi, /turf/simulated/floor/grass, /area/ruin/space/syndicakefactory) +"ID" = ( +/obj/structure/table/glass/reinforced/plastitanium, +/obj/effect/spawner/random/pool/spaceloot/syndicate/mixed, +/turf/simulated/floor/plasteel{ + icon_state = "floorgrime" + }, +/area/ruin/space/syndicakefactory) "IE" = ( /obj/item/flag/syndi{ anchored = 1 @@ -2747,7 +2754,7 @@ OK OK OK EJ -Wh +ID xO hq xO diff --git a/_maps/map_files/RandomRuins/SpaceRuins/syndiedepot.dmm b/_maps/map_files/RandomRuins/SpaceRuins/syndiedepot.dmm index d30991749016..8d7650291303 100644 --- a/_maps/map_files/RandomRuins/SpaceRuins/syndiedepot.dmm +++ b/_maps/map_files/RandomRuins/SpaceRuins/syndiedepot.dmm @@ -146,13 +146,13 @@ dir = 1; on = 1 }, -/obj/effect/spawner/random/syndicate/loot/common, +/obj/effect/spawner/random/pool/spaceloot/syndicate/common/depot, /turf/simulated/floor/plasteel{ icon_state = "dark" }, /area/syndicate_depot/core) "aB" = ( -/obj/effect/spawner/random/syndicate/loot/common, +/obj/effect/spawner/random/pool/spaceloot/syndicate/common/depot, /turf/simulated/floor/plasteel{ icon_state = "dark" }, @@ -342,7 +342,7 @@ }, /area/syndicate_depot/core) "bc" = ( -/obj/effect/spawner/random/syndicate/loot/rare, +/obj/effect/spawner/random/pool/spaceloot/syndicate/rare/depot, /turf/simulated/floor/plasteel{ icon_state = "dark" }, @@ -350,7 +350,7 @@ "bd" = ( /obj/item/lighter/zippo/black, /obj/structure/table, -/obj/effect/spawner/random/syndicate/loot/stetchkin, +/obj/effect/spawner/random/syndicate/stetchkin, /turf/simulated/floor/plasteel{ icon_state = "dark" }, @@ -367,7 +367,7 @@ dir = 1; on = 1 }, -/obj/effect/spawner/random/syndicate/loot/rare, +/obj/effect/spawner/random/pool/spaceloot/syndicate/rare/depot, /turf/simulated/floor/plasteel{ icon_state = "dark" }, @@ -394,7 +394,7 @@ /area/syndicate_depot/outer) "bl" = ( /obj/structure/table, -/obj/effect/spawner/random/syndicate/loot/stetchkin, +/obj/effect/spawner/random/syndicate/stetchkin, /turf/simulated/floor/plasteel{ icon_state = "dark" }, @@ -409,20 +409,11 @@ icon_state = "dark" }, /area/syndicate_depot/outer) -"bn" = ( -/obj/machinery/light{ - dir = 8 - }, -/obj/effect/spawner/random/syndicate/loot/common, -/turf/simulated/floor/plasteel{ - icon_state = "dark" - }, -/area/syndicate_depot/core) "bo" = ( /obj/machinery/light{ dir = 4 }, -/obj/effect/spawner/random/syndicate/loot/common, +/obj/effect/spawner/random/pool/spaceloot/syndicate/common/depot, /turf/simulated/floor/plasteel{ icon_state = "dark" }, @@ -532,7 +523,7 @@ }, /area/syndicate_depot/core) "bE" = ( -/obj/effect/spawner/random/syndicate/loot/officer, +/obj/effect/spawner/random/pool/spaceloot/syndicate/officer/depot, /turf/simulated/floor/plasteel{ icon_state = "dark" }, @@ -652,7 +643,7 @@ /area/syndicate_depot/outer) "bU" = ( /obj/structure/table, -/obj/effect/spawner/random/syndicate/loot/stetchkin, +/obj/effect/spawner/random/syndicate/stetchkin, /turf/simulated/floor/plasteel{ icon_state = "dark" }, @@ -786,8 +777,8 @@ }, /area/syndicate_depot/core) "cm" = ( -/obj/effect/spawner/random/syndicate/loot/armory, /obj/machinery/atmospherics/pipe/simple/hidden, +/obj/effect/spawner/random/pool/spaceloot/syndicate/armory/depot, /turf/simulated/floor/plasteel{ icon_state = "dark" }, @@ -797,13 +788,13 @@ dir = 1; on = 1 }, -/obj/effect/spawner/random/syndicate/loot/armory, +/obj/effect/spawner/random/pool/spaceloot/syndicate/armory/depot, /turf/simulated/floor/plasteel{ icon_state = "dark" }, /area/syndicate_depot/core) "co" = ( -/obj/effect/spawner/random/syndicate/loot/armory, +/obj/effect/spawner/random/pool/spaceloot/syndicate/armory/depot, /turf/simulated/floor/plasteel{ icon_state = "dark" }, @@ -1100,7 +1091,7 @@ /obj/machinery/light/small{ dir = 8 }, -/obj/effect/spawner/random/syndicate/loot/rare, +/obj/effect/spawner/random/pool/spaceloot/syndicate/rare/depot, /turf/simulated/floor/plasteel{ icon_state = "dark" }, @@ -1142,6 +1133,14 @@ }, /turf/simulated/floor/plating/asteroid/airless, /area/syndicate_depot/outer) +"Nh" = ( +/obj/machinery/light{ + dir = 4 + }, +/turf/simulated/floor/plasteel{ + icon_state = "dark" + }, +/area/syndicate_depot/core) "Te" = ( /turf/simulated/mineral/random/high_chance, /area/syndicate_depot/outer) @@ -1729,7 +1728,7 @@ aM at aD aD -bn +cW bu bz at @@ -1933,7 +1932,7 @@ aD aD aD aD -bo +Nh aD bv at @@ -2093,7 +2092,7 @@ aD aD aD aD -bE +aB at aD aD @@ -2452,7 +2451,7 @@ cl cz aD cQ -bE +aD aD aD at @@ -2488,11 +2487,11 @@ af at aw aD -aB +aD at aD aD -bc +aD bi aD aD @@ -2547,7 +2546,7 @@ aD at aD aD -bE +aD bE cb cn @@ -2558,7 +2557,7 @@ aD bC aD at -bh +aL aD at af @@ -2609,7 +2608,7 @@ cV aD aD at -bc +aD aD at at @@ -2746,7 +2745,7 @@ aD aD aE aD -bc +aD bc at aD @@ -2757,12 +2756,12 @@ at aD cD aD -bE +aD at aL aD bc -bc +aD aD aD at @@ -2894,7 +2893,7 @@ af af af at -aB +aD aD aK aR @@ -2965,7 +2964,7 @@ aD cW aD aD -aB +aD at af af diff --git a/_maps/map_files/RandomRuins/SpaceRuins/telecomns_returns.dmm b/_maps/map_files/RandomRuins/SpaceRuins/telecomns_returns.dmm index 9263dfe5d4c7..a55559ca85b8 100644 --- a/_maps/map_files/RandomRuins/SpaceRuins/telecomns_returns.dmm +++ b/_maps/map_files/RandomRuins/SpaceRuins/telecomns_returns.dmm @@ -84,9 +84,9 @@ }, /area/ruin/space/telecomms/chamber) "bP" = ( -/obj/effect/spawner/random/telecomms_core_table, /obj/machinery/ai_slipper, /obj/structure/table/glass/reinforced/plastitanium, +/obj/effect/spawner/random/pool/spaceloot/dvorak_core_table, /turf/simulated/floor/plasteel{ dir = 1; icon_state = "vault"; @@ -388,7 +388,7 @@ /turf/simulated/floor/plasteel, /area/ruin/space/telecomms/tele) "ia" = ( -/obj/effect/spawner/random/telecomms_emp_loot, +/obj/effect/spawner/random/pool/spaceloot/dvorak_emp_loot, /turf/simulated/floor/engine, /area/ruin/space/telecomms/computer) "ik" = ( @@ -1667,7 +1667,7 @@ }, /area/ruin/space/telecomms/chamber) "CI" = ( -/obj/structure/displaycase/dvoraks_treat, +/obj/effect/spawner/random/pool/spaceloot/dvorak_displaycase, /turf/simulated/floor/plasteel{ dir = 4; icon_state = "vault"; diff --git a/_maps/map_files/RandomRuins/SpaceRuins/turretedoutpost.dmm b/_maps/map_files/RandomRuins/SpaceRuins/turretedoutpost.dmm index 5e607e129113..833af7b41907 100644 --- a/_maps/map_files/RandomRuins/SpaceRuins/turretedoutpost.dmm +++ b/_maps/map_files/RandomRuins/SpaceRuins/turretedoutpost.dmm @@ -70,6 +70,7 @@ /area/ruin/space/unpowered) "q" = ( /obj/machinery/light, +/mob/living/simple_animal/hostile/syndicate/melee/autogib, /turf/simulated/floor/plasteel, /area/ruin/space/unpowered) "r" = ( @@ -183,6 +184,7 @@ /area/ruin/space/unpowered) "H" = ( /obj/structure/chair, +/mob/living/simple_animal/hostile/syndicate/melee/autogib, /turf/simulated/floor/plasteel, /area/ruin/space/unpowered) "I" = ( @@ -263,6 +265,22 @@ }, /turf/simulated/floor/plasteel, /area/ruin/space/unpowered) +"T" = ( +/obj/item/rack_parts, +/obj/effect/spawner/random/pool/spaceloot/syndicate/mixed, +/turf/simulated/floor/plasteel{ + dir = 8; + icon_state = "vault" + }, +/area/ruin/space/unpowered) +"Z" = ( +/obj/structure/rack, +/obj/effect/spawner/random/pool/spaceloot/syndicate/mixed, +/turf/simulated/floor/plasteel{ + dir = 8; + icon_state = "vault" + }, +/area/ruin/space/unpowered) (1,1,1) = {" a @@ -384,10 +402,10 @@ a l d d -s -r +T +Z F -r +Z d d l @@ -429,8 +447,8 @@ l d s x -r -r +Z +Z x s d diff --git a/_maps/map_files/RandomRuins/SpaceRuins/unathi_skiff.dmm b/_maps/map_files/RandomRuins/SpaceRuins/unathi_skiff.dmm index c9fb4b3c1206..b60a14413482 100644 --- a/_maps/map_files/RandomRuins/SpaceRuins/unathi_skiff.dmm +++ b/_maps/map_files/RandomRuins/SpaceRuins/unathi_skiff.dmm @@ -129,9 +129,7 @@ /area/ruin/space/unathi_breacher/hold) "kb" = ( /obj/structure/rack, -/obj/item/stack/sheet/mineral/gold, -/obj/item/stack/sheet/mineral/gold, -/obj/item/stack/sheet/mineral/gold, +/obj/effect/spawner/random/pool/spaceloot/syndicate/mixed, /turf/simulated/floor/pod/dark, /area/ruin/space/unathi_breacher/hold) "kf" = ( @@ -146,6 +144,7 @@ "kt" = ( /obj/structure/table, /obj/item/screwdriver, +/obj/effect/spawner/random/pool/spaceloot/syndicate/mixed, /turf/simulated/floor/plasteel/airless, /area/ruin/space/unathi_breacher/engineering) "li" = ( diff --git a/_maps/map_files/RandomRuins/SpaceRuins/ussp.dmm b/_maps/map_files/RandomRuins/SpaceRuins/ussp.dmm index bcddd30bcfd6..580fe6558302 100644 --- a/_maps/map_files/RandomRuins/SpaceRuins/ussp.dmm +++ b/_maps/map_files/RandomRuins/SpaceRuins/ussp.dmm @@ -1284,6 +1284,7 @@ dir = 4 }, /obj/effect/decal/cleanable/dirt, +/obj/effect/spawner/random/pool/spaceloot/syndicate/mixed, /turf/simulated/floor/plasteel{ dir = 6; icon_state = "darkred" @@ -3271,6 +3272,7 @@ /area/ruin/space/derelict/hallway/primary) "iI" = ( /obj/structure/closet/firecloset, +/obj/effect/spawner/random/pool/spaceloot/syndicate/mixed, /turf/simulated/floor/plasteel{ dir = 6; icon_state = "caution" @@ -4893,6 +4895,7 @@ /obj/structure/window/reinforced{ dir = 1 }, +/obj/effect/spawner/random/pool/spaceloot/syndicate/mixed, /turf/simulated/floor/plasteel{ dir = 1; icon_state = "whitered" @@ -4939,6 +4942,7 @@ /area/ruin/space/derelict/crew_quarters) "nh" = ( /obj/structure/closet/athletic_mixed, +/obj/effect/spawner/random/pool/spaceloot/syndicate/mixed, /turf/simulated/floor/plasteel{ icon_state = "hydrofloor" }, @@ -5716,6 +5720,7 @@ /area/ruin/space/derelict/hallway/primary) "pt" = ( /obj/structure/closet/jcloset, +/obj/effect/spawner/random/pool/spaceloot/syndicate/mixed, /turf/simulated/floor/plasteel/dark, /area/ruin/space/derelict/crew_quarters) "pu" = ( @@ -6950,6 +6955,10 @@ /obj/effect/spawner/random/fungus/frequent, /turf/simulated/wall/indestructible/titanium/soviet/nodiagonal, /area/ruin/space/derelict/arrival) +"Ae" = ( +/mob/living/simple_animal/hostile/poison/giant_spider/hunter, +/turf/simulated/floor/plasteel/dark, +/area/ruin/space/derelict/crew_quarters) "Bx" = ( /obj/machinery/door_control{ id = "ruslock"; @@ -7029,6 +7038,13 @@ icon_state = "white" }, /area/ruin/space/derelict/arrival) +"Za" = ( +/obj/structure/chair/comfy/shuttle{ + dir = 4 + }, +/obj/effect/spawner/random/pool/spaceloot/syndicate/mixed, +/turf/simulated/floor/mineral/plastitanium/red, +/area/ruin/space/derelict/arrival) (1,1,1) = {" ac @@ -7264,7 +7280,7 @@ ac ir iP ji -jQ +Za jQ lt lI @@ -12452,7 +12468,7 @@ ac aV pm pt -hU +Ae pM pY db @@ -12736,7 +12752,7 @@ pn pw pw db -db +qA db Mi aV diff --git a/_maps/map_files/RandomRuins/SpaceRuins/ussp_tele.dmm b/_maps/map_files/RandomRuins/SpaceRuins/ussp_tele.dmm index 70f2dca4ac04..0d5ebb8c4f2a 100644 --- a/_maps/map_files/RandomRuins/SpaceRuins/ussp_tele.dmm +++ b/_maps/map_files/RandomRuins/SpaceRuins/ussp_tele.dmm @@ -230,6 +230,7 @@ /area/ruin/space/derelict/teleporter) "vr" = ( /obj/effect/decal/cleanable/dirt, +/obj/effect/spawner/random/pool/spaceloot/syndicate/mixed, /turf/simulated/floor/plasteel{ dir = 10; icon_state = "darkblue" diff --git a/_maps/map_files/RandomRuins/SpaceRuins/wizardcrash.dmm b/_maps/map_files/RandomRuins/SpaceRuins/wizardcrash.dmm index fe9aa407df24..eda3acc04835 100644 --- a/_maps/map_files/RandomRuins/SpaceRuins/wizardcrash.dmm +++ b/_maps/map_files/RandomRuins/SpaceRuins/wizardcrash.dmm @@ -315,6 +315,7 @@ /area/ruin/space/powered) "bk" = ( /obj/structure/rack, +/obj/effect/spawner/random/pool/spaceloot/syndicate/mixed, /turf/simulated/floor/plasteel{ icon_state = "chapel" }, @@ -396,6 +397,7 @@ /area/ruin/space/powered) "bz" = ( /mob/living/simple_animal/hostile/mimic/crate, +/obj/effect/spawner/random/pool/spaceloot/syndicate/mixed, /turf/simulated/floor/plating, /area/ruin/space/powered) "bA" = ( @@ -488,6 +490,10 @@ /obj/structure/table, /turf/simulated/floor/plating, /area/ruin/space/powered) +"EZ" = ( +/obj/effect/spawner/random/pool/spaceloot/syndicate/mixed, +/turf/simulated/floor/plating, +/area/ruin/space/powered) "YM" = ( /obj/structure/table/wood, /obj/item/blank_tarot_card, @@ -577,7 +583,7 @@ aa bH ae aY -aS +EZ bl bq ae diff --git a/_maps/map_files/RandomRuins/SpaceRuins/wreckedcargoship.dmm b/_maps/map_files/RandomRuins/SpaceRuins/wreckedcargoship.dmm index 0f6d16eea8e9..5f8a7b0b8732 100644 --- a/_maps/map_files/RandomRuins/SpaceRuins/wreckedcargoship.dmm +++ b/_maps/map_files/RandomRuins/SpaceRuins/wreckedcargoship.dmm @@ -274,6 +274,7 @@ /obj/effect/decal/cleanable/cobweb, /obj/structure/rack, /obj/item/stack/rods/fifty, +/obj/effect/spawner/random/pool/spaceloot/syndicate/mixed, /turf/simulated/floor/plasteel{ icon_state = "titanium"; dir = 4 @@ -666,6 +667,7 @@ dir = 1 }, /obj/structure/closet/crate/secure/loot, +/obj/effect/spawner/random/pool/spaceloot/syndicate/mixed, /turf/simulated/floor/pod/light, /area/ruin/space/wreck_cargoship) "AN" = ( @@ -783,6 +785,7 @@ "Fk" = ( /obj/structure/closet/crate, /obj/effect/decal/cleanable/dirt, +/obj/effect/spawner/random/pool/spaceloot/syndicate/mixed, /turf/simulated/floor/plasteel{ icon_state = "yellowsiding"; dir = 1 @@ -1084,6 +1087,7 @@ pixel_y = -32 }, /obj/structure/closet/crate/secure/loot, +/obj/effect/spawner/random/pool/spaceloot/syndicate/mixed, /turf/simulated/floor/plasteel{ dir = 1; icon_state = "blackcorner" @@ -1193,6 +1197,7 @@ "Vc" = ( /obj/effect/decal/cleanable/cobweb, /obj/effect/decal/cleanable/dirt, +/obj/effect/spawner/random/pool/spaceloot/syndicate/mixed, /turf/simulated/floor/plasteel{ dir = 9; icon_state = "caution" @@ -1307,6 +1312,7 @@ /obj/machinery/light/small{ dir = 1 }, +/obj/effect/spawner/random/pool/spaceloot/syndicate/mixed, /turf/simulated/floor/plating, /area/ruin/space/wreck_cargoship) "XX" = ( diff --git a/_maps/map_files/stations/cerestation.dmm b/_maps/map_files/stations/cerestation.dmm index 4e2c464e12be..bb9c3e185534 100644 --- a/_maps/map_files/stations/cerestation.dmm +++ b/_maps/map_files/stations/cerestation.dmm @@ -14324,6 +14324,25 @@ /turf/simulated/floor/plating, /area/station/engineering/smes) "bTk" = ( +/obj/structure/closet/crate{ + name = "solar pack crate" + }, +/obj/item/solar_assembly, +/obj/item/solar_assembly, +/obj/item/solar_assembly, +/obj/item/solar_assembly, +/obj/item/solar_assembly, +/obj/item/solar_assembly, +/obj/item/solar_assembly, +/obj/item/solar_assembly, +/obj/item/solar_assembly, +/obj/item/solar_assembly, +/obj/item/solar_assembly, +/obj/item/solar_assembly, +/obj/item/solar_assembly, +/obj/item/circuitboard/solar_control, +/obj/item/tracker_electronics, +/obj/item/paper/solar, /turf/simulated/floor/plating, /area/station/engineering/smes) "bTl" = ( diff --git a/_maps/map_files/stations/deltastation.dmm b/_maps/map_files/stations/deltastation.dmm index 8ba30d96109a..7128040b4864 100644 --- a/_maps/map_files/stations/deltastation.dmm +++ b/_maps/map_files/stations/deltastation.dmm @@ -36171,8 +36171,24 @@ /obj/structure/closet/crate{ name = "solar pack crate" }, -/obj/effect/turf_decal/delivery/hollow, +/obj/item/solar_assembly, +/obj/item/solar_assembly, +/obj/item/solar_assembly, +/obj/item/solar_assembly, +/obj/item/solar_assembly, +/obj/item/solar_assembly, +/obj/item/solar_assembly, +/obj/item/solar_assembly, +/obj/item/solar_assembly, +/obj/item/solar_assembly, +/obj/item/solar_assembly, +/obj/item/solar_assembly, +/obj/item/solar_assembly, +/obj/item/circuitboard/solar_control, +/obj/item/tracker_electronics, +/obj/item/paper/solar, /obj/machinery/alarm/directional/south, +/obj/effect/turf_decal/delivery/hollow, /turf/simulated/floor/plasteel, /area/station/engineering/equipmentstorage) "csA" = ( @@ -67358,10 +67374,6 @@ }, /turf/simulated/floor/plasteel, /area/station/science/testrange) -"kol" = ( -/obj/effect/decal/cleanable/dirt, -/turf/simulated/floor/plasteel, -/area/station/maintenance/port) "kot" = ( /obj/machinery/atmospherics/pipe/simple/hidden/supply{ dir = 5 @@ -76483,6 +76495,10 @@ }, /turf/simulated/floor/plating, /area/station/security/armory/secure) +"pvo" = ( +/obj/effect/decal/cleanable/dirt, +/turf/simulated/floor/plasteel, +/area/station/maintenance/port) "pvv" = ( /obj/structure/table/reinforced, /obj/machinery/door/window/reinforced/normal, @@ -127280,7 +127296,7 @@ tik xjh mQi rLQ -kol +pvo drn dhG fBk diff --git a/_maps/map_files220/RandomRuins/SpaceRuins/convoy_ambush.dmm b/_maps/map_files220/RandomRuins/SpaceRuins/convoy_ambush.dmm index e0b4e49a0175..a1f3f1fd3daa 100644 --- a/_maps/map_files220/RandomRuins/SpaceRuins/convoy_ambush.dmm +++ b/_maps/map_files220/RandomRuins/SpaceRuins/convoy_ambush.dmm @@ -54,9 +54,7 @@ }, /area/ruin/space/unpowered/unpowered_structures) "cj" = ( -/mob/living/simple_animal/hostile/syndicate/ranged/space/autogib{ - wander = 0 - }, +/obj/effect/spawner/random/pool/spaceloot/modsuit_syndie, /obj/effect/decal/cleanable/blood, /turf/simulated/floor/plasteel/airless{ icon_state = "dark" @@ -1074,9 +1072,7 @@ "Sn" = ( /obj/structure/closet/walllocker/emerglocker/west, /obj/effect/mob_spawn/human/corpse/damaged, -/mob/living/simple_animal/hostile/syndicate/ranged/space/autogib{ - wander = 0 - }, +/obj/effect/spawner/random/pool/spaceloot/modsuit_syndie, /turf/simulated/floor/plasteel/airless{ icon_state = "dark" }, diff --git a/_maps/map_files220/RandomZLevels/spacebattle.dmm b/_maps/map_files220/RandomZLevels/spacebattle.dmm index 7eaee75bdba2..8dd9ae460647 100644 --- a/_maps/map_files220/RandomZLevels/spacebattle.dmm +++ b/_maps/map_files220/RandomZLevels/spacebattle.dmm @@ -1141,7 +1141,7 @@ /turf/simulated/floor/fakespace, /area/awaymission/space_battle/sec_storage) "dL" = ( -/mob/living/simple_animal/hostile/syndicate/ranged/space/autogib/spacebattle, +/obj/effect/spawner/random/pool/spaceloot/modsuit_syndie/spacebattle, /turf/simulated/floor/plating/airless, /area/awaymission/space_battle/syndicate/syndicate2) "dM" = ( @@ -1234,7 +1234,7 @@ /turf/simulated/floor/plating/airless, /area/awaymission/space_battle/syndicate/syndicate3) "eh" = ( -/mob/living/simple_animal/hostile/syndicate/ranged/space/autogib/spacebattle, +/obj/effect/spawner/random/pool/spaceloot/modsuit_syndie/spacebattle, /turf/simulated/floor/plasteel/airless, /area/awaymission/space_battle/engineering) "ei" = ( @@ -1408,7 +1408,7 @@ /turf/simulated/floor/engine/airless, /area/awaymission/space_battle/cruiser) "eN" = ( -/mob/living/simple_animal/hostile/syndicate/ranged/space/autogib/spacebattle, +/obj/effect/spawner/random/pool/spaceloot/modsuit_syndie/spacebattle, /turf/simulated/floor/mineral/plastitanium/red, /area/awaymission/space_battle/syndicate/syndicate5) "eO" = ( @@ -1442,7 +1442,7 @@ /obj/structure/cable{ icon_state = "2-4" }, -/mob/living/simple_animal/hostile/syndicate/ranged/space/autogib, +/obj/effect/spawner/random/pool/spaceloot/modsuit_syndie, /turf/simulated/floor/plasteel/airless, /area/awaymission/space_battle/hallway2) "eT" = ( @@ -1627,7 +1627,7 @@ /obj/structure/cable{ icon_state = "2-4" }, -/mob/living/simple_animal/hostile/syndicate/ranged/space/autogib/spacebattle, +/obj/effect/spawner/random/pool/spaceloot/modsuit_syndie/spacebattle, /turf/simulated/floor/plating, /area/awaymission/space_battle/engine) "fx" = ( @@ -2104,7 +2104,7 @@ /obj/effect/turf_decal/stripes/line{ dir = 1 }, -/mob/living/simple_animal/hostile/syndicate/ranged/space/autogib/spacebattle, +/obj/effect/spawner/random/pool/spaceloot/modsuit_syndie/spacebattle, /turf/simulated/floor/mineral/plastitanium/red/airless, /area/awaymission/space_battle/syndicate) "gQ" = ( @@ -4518,7 +4518,7 @@ /obj/effect/decal/cleanable/shreds, /obj/effect/mapping_helpers/turfs/damage, /obj/machinery/light_construct/directional/south, -/mob/living/simple_animal/hostile/syndicate/ranged/space/autogib, +/obj/effect/spawner/random/pool/spaceloot/modsuit_syndie, /turf/simulated/floor/plating/airless, /area/awaymission/space_battle/living) "oz" = ( @@ -4812,7 +4812,7 @@ /obj/structure/chair/comfy/shuttle/dark{ dir = 8 }, -/mob/living/simple_animal/hostile/syndicate/ranged/space/autogib/spacebattle, +/obj/effect/spawner/random/pool/spaceloot/modsuit_syndie/spacebattle, /turf/simulated/floor/mineral/plastitanium/red, /area/awaymission/space_battle/syndicate) "pA" = ( @@ -5126,7 +5126,7 @@ dir = 4 }, /obj/machinery/light/small/directional/west, -/mob/living/simple_animal/hostile/syndicate/ranged/space/autogib/spacebattle, +/obj/effect/spawner/random/pool/spaceloot/modsuit_syndie/spacebattle, /turf/simulated/floor/mineral/plastitanium/red, /area/awaymission/space_battle/syndicate) "qL" = ( @@ -5430,7 +5430,7 @@ "rI" = ( /obj/effect/mapping_helpers/turfs/damage, /obj/structure/chair/comfy/shuttle, -/mob/living/simple_animal/hostile/syndicate/ranged/space/autogib/spacebattle, +/obj/effect/spawner/random/pool/spaceloot/modsuit_syndie/spacebattle, /turf/simulated/floor/mineral/titanium/blue/airless, /area/space/nearstation) "rJ" = ( @@ -6281,7 +6281,7 @@ icon_state = "1-2" }, /obj/effect/decal/cleanable/dirt, -/mob/living/simple_animal/hostile/syndicate/ranged/space/autogib/spacebattle, +/obj/effect/spawner/random/pool/spaceloot/modsuit_syndie/spacebattle, /turf/simulated/floor/plasteel, /area/awaymission/space_battle/engine) "uD" = ( @@ -6367,7 +6367,7 @@ /obj/item/shard{ icon_state = "small" }, -/mob/living/simple_animal/hostile/syndicate/ranged/space/autogib, +/obj/effect/spawner/random/pool/spaceloot/modsuit_syndie, /turf/simulated/floor/plating/airless, /area/space/nearstation) "uT" = ( @@ -7400,7 +7400,7 @@ /turf/space, /area/space/nearstation) "yr" = ( -/mob/living/simple_animal/hostile/syndicate/ranged/space/autogib, +/obj/effect/spawner/random/pool/spaceloot/modsuit_syndie, /turf/space, /area/space) "ys" = ( @@ -7965,7 +7965,7 @@ /area/awaymission/space_battle/hallway9) "Am" = ( /obj/effect/mapping_helpers/turfs/damage, -/mob/living/simple_animal/hostile/syndicate/ranged/space/autogib/spacebattle, +/obj/effect/spawner/random/pool/spaceloot/modsuit_syndie/spacebattle, /turf/simulated/floor/plating/airless, /area/awaymission/space_battle/engineering) "An" = ( @@ -8019,7 +8019,7 @@ /turf/simulated/floor/plasteel, /area/awaymission/space_battle/sec_storage) "Ax" = ( -/mob/living/simple_animal/hostile/syndicate/ranged/space/autogib/spacebattle, +/obj/effect/spawner/random/pool/spaceloot/modsuit_syndie/spacebattle, /turf/simulated/floor/plasteel/airless{ icon_state = "podfloor" }, @@ -8439,7 +8439,7 @@ /obj/structure/chair/comfy/shuttle/dark{ dir = 8 }, -/mob/living/simple_animal/hostile/syndicate/ranged/space/autogib, +/obj/effect/spawner/random/pool/spaceloot/modsuit_syndie, /turf/simulated/floor/mineral/plastitanium/red, /area/awaymission/space_battle/syndicate/syndicate6) "BS" = ( @@ -8735,7 +8735,7 @@ /obj/structure/cable{ icon_state = "1-2" }, -/mob/living/simple_animal/hostile/syndicate/ranged/space/autogib/spacebattle, +/obj/effect/spawner/random/pool/spaceloot/modsuit_syndie/spacebattle, /turf/simulated/floor/plasteel/airless{ icon_state = "neutral"; dir = 4 @@ -9478,7 +9478,7 @@ /obj/structure/chair/comfy/shuttle/dark{ dir = 8 }, -/mob/living/simple_animal/hostile/syndicate/ranged/space/autogib/spacebattle, +/obj/effect/spawner/random/pool/spaceloot/modsuit_syndie/spacebattle, /turf/simulated/floor/mineral/plastitanium/red, /area/awaymission/space_battle/syndicate/syndicate5) "Fd" = ( @@ -9625,7 +9625,7 @@ color = "red"; dir = 4 }, -/mob/living/simple_animal/hostile/syndicate/ranged/space/autogib/spacebattle, +/obj/effect/spawner/random/pool/spaceloot/modsuit_syndie/spacebattle, /turf/simulated/floor/mineral/plastitanium/red, /area/awaymission/space_battle/syndicate/syndicate6) "FB" = ( @@ -10219,7 +10219,7 @@ /area/awaymission/space_battle/hallway8) "Ht" = ( /obj/effect/mapping_helpers/turfs/damage, -/mob/living/simple_animal/hostile/syndicate/ranged/space/autogib, +/obj/effect/spawner/random/pool/spaceloot/modsuit_syndie, /turf/simulated/floor/plasteel/airless, /area/awaymission/space_battle/living) "Hu" = ( @@ -10836,7 +10836,7 @@ /obj/structure/chair/comfy/shuttle/dark{ dir = 1 }, -/mob/living/simple_animal/hostile/syndicate/ranged/space/autogib/spacebattle, +/obj/effect/spawner/random/pool/spaceloot/modsuit_syndie/spacebattle, /turf/simulated/floor/mineral/plastitanium/red, /area/awaymission/space_battle/syndicate/syndicate5) "Ju" = ( @@ -12110,7 +12110,7 @@ /turf/simulated/floor/plasteel, /area/awaymission/space_battle/hallway10) "NB" = ( -/mob/living/simple_animal/hostile/syndicate/ranged/space/autogib/spacebattle, +/obj/effect/spawner/random/pool/spaceloot/modsuit_syndie/spacebattle, /turf/space, /area/space) "NC" = ( @@ -12962,7 +12962,7 @@ }, /area/awaymission/space_battle/hallway6) "Qr" = ( -/mob/living/simple_animal/hostile/syndicate/ranged/space/autogib/spacebattle, +/obj/effect/spawner/random/pool/spaceloot/modsuit_syndie/spacebattle, /turf/simulated/floor/plasteel/airless{ icon_state = "podfloor" }, @@ -13460,7 +13460,7 @@ /area/awaymission/space_battle/bridge) "RU" = ( /obj/structure/chair/comfy/shuttle/dark, -/mob/living/simple_animal/hostile/syndicate/ranged/space/autogib/spacebattle, +/obj/effect/spawner/random/pool/spaceloot/modsuit_syndie/spacebattle, /turf/simulated/floor/mineral/plastitanium/red, /area/awaymission/space_battle/syndicate/syndicate5) "RV" = ( @@ -13795,7 +13795,7 @@ /obj/structure/chair/comfy/shuttle/dark{ dir = 4 }, -/mob/living/simple_animal/hostile/syndicate/ranged/space/autogib/spacebattle, +/obj/effect/spawner/random/pool/spaceloot/modsuit_syndie/spacebattle, /turf/simulated/floor/mineral/plastitanium/red, /area/awaymission/space_battle/syndicate) "Tb" = ( @@ -13900,7 +13900,7 @@ icon_state = "1-4" }, /obj/effect/mapping_helpers/turfs/damage, -/mob/living/simple_animal/hostile/syndicate/ranged/space/autogib, +/obj/effect/spawner/random/pool/spaceloot/modsuit_syndie, /turf/simulated/floor/plasteel/airless, /area/awaymission/space_battle/hallway2) "Tu" = ( @@ -14838,7 +14838,7 @@ /obj/structure/chair/comfy/shuttle/dark{ dir = 8 }, -/mob/living/simple_animal/hostile/syndicate/ranged/space/autogib/spacebattle, +/obj/effect/spawner/random/pool/spaceloot/modsuit_syndie/spacebattle, /turf/simulated/floor/mineral/plastitanium/red/airless, /area/awaymission/space_battle/syndicate/syndicate2) "Wx" = ( diff --git a/_maps/map_files220/RandomZLevels/wildwest.dmm b/_maps/map_files220/RandomZLevels/wildwest.dmm index de62efb0c7bb..d5ea015a882a 100644 --- a/_maps/map_files220/RandomZLevels/wildwest.dmm +++ b/_maps/map_files220/RandomZLevels/wildwest.dmm @@ -4336,7 +4336,7 @@ /obj/effect/decal/cleanable/cobweb, /obj/effect/decal/cleanable/dirt, /obj/effect/decal/cleanable/ash, -/mob/living/simple_animal/hostile/syndicate/ranged/space/autogib/spacebattle, +/obj/effect/spawner/random/pool/spaceloot/modsuit_syndie/spacebattle, /turf/simulated/floor/plating/asteroid{ icon_state = "asteroidplating" }, diff --git a/_maps/map_files220/generic/centcomm.dmm b/_maps/map_files220/generic/centcomm.dmm index bc0965ba2aaf..9c9809aad514 100644 --- a/_maps/map_files220/generic/centcomm.dmm +++ b/_maps/map_files220/generic/centcomm.dmm @@ -11818,7 +11818,7 @@ /area/centcom/ss220/supply) "haI" = ( /obj/effect/turf_decal/delivery/red, -/obj/effect/spawner/random/syndicate/loot/common, +/obj/effect/spawner/random/pool/spaceloot/syndicate/common/depot, /obj/structure/closet/secure_closet/depot, /turf/simulated/floor/plasteel{ icon_state = "dark" @@ -17961,7 +17961,7 @@ dir = 4 }, /obj/effect/turf_decal/delivery/white, -/obj/effect/spawner/random/syndicate/loot/common, +/obj/effect/spawner/random/pool/spaceloot/syndicate/common/depot, /obj/structure/closet/secure_closet/depot, /turf/simulated/floor/plasteel{ icon_state = "dark" @@ -19973,7 +19973,7 @@ /area/syndicate_mothership) "lKt" = ( /obj/effect/turf_decal/delivery, -/obj/effect/spawner/random/syndicate/loot/common, +/obj/effect/spawner/random/pool/spaceloot/syndicate/common/depot, /obj/structure/closet/secure_closet/depot, /turf/simulated/floor/plasteel{ dir = 1; @@ -20853,7 +20853,7 @@ /obj/structure/light_fake/spot{ dir = 1 }, -/obj/effect/spawner/random/syndicate/loot/common, +/obj/effect/spawner/random/pool/spaceloot/syndicate/common/depot, /obj/structure/closet/secure_closet/depot, /turf/simulated/floor/plasteel{ icon_state = "darkyellowalt" @@ -22241,7 +22241,7 @@ }, /area/syndicate_mothership/cargo) "neJ" = ( -/obj/effect/spawner/random/syndicate/loot/common, +/obj/effect/spawner/random/pool/spaceloot/syndicate/common/depot, /obj/structure/closet/secure_closet/depot, /turf/simulated/floor/plasteel{ dir = 10; @@ -22456,7 +22456,7 @@ /turf/simulated/floor/wood/oak, /area/syndicate_mothership/control) "nlb" = ( -/obj/effect/spawner/random/syndicate/loot/common, +/obj/effect/spawner/random/pool/spaceloot/syndicate/common/depot, /obj/structure/closet/secure_closet/depot, /turf/simulated/floor/plasteel{ icon_state = "dark" @@ -23153,7 +23153,7 @@ dir = 8 }, /obj/effect/turf_decal/delivery/white, -/obj/effect/spawner/random/syndicate/loot/common, +/obj/effect/spawner/random/pool/spaceloot/syndicate/common/depot, /obj/structure/closet/secure_closet/depot, /turf/simulated/floor/plasteel{ icon_state = "dark" @@ -23578,7 +23578,7 @@ /area/syndicate_mothership/outside) "nRS" = ( /obj/effect/turf_decal/delivery/white, -/obj/effect/spawner/random/syndicate/loot/common, +/obj/effect/spawner/random/pool/spaceloot/syndicate/common/depot, /obj/structure/closet/secure_closet/depot, /turf/simulated/floor/plasteel{ icon_state = "dark" @@ -24730,7 +24730,7 @@ "oEC" = ( /obj/effect/turf_decal/stripes/line, /obj/effect/turf_decal/delivery/red, -/obj/effect/spawner/random/syndicate/loot/common, +/obj/effect/spawner/random/pool/spaceloot/syndicate/common/depot, /obj/structure/closet/secure_closet/depot, /turf/simulated/floor/plasteel{ icon_state = "dark" @@ -25393,7 +25393,7 @@ /turf/simulated/floor/indestructible/grass, /area/syndicate_mothership/outside) "oYr" = ( -/obj/effect/spawner/random/syndicate/loot/common, +/obj/effect/spawner/random/pool/spaceloot/syndicate/common/depot, /obj/structure/closet/secure_closet/depot, /obj/structure/closet/crate, /turf/simulated/floor/plasteel{ @@ -34405,7 +34405,7 @@ /turf/simulated/floor/wood/parquet/tile, /area/centcom/ss220/admin2) "upU" = ( -/obj/effect/spawner/random/syndicate/loot/common, +/obj/effect/spawner/random/pool/spaceloot/syndicate/common/depot, /obj/structure/closet/secure_closet/depot, /obj/structure/closet/crate, /turf/simulated/floor/plasteel{ @@ -38194,7 +38194,7 @@ dir = 5 }, /obj/effect/turf_decal/delivery/white, -/obj/effect/spawner/random/syndicate/loot/common, +/obj/effect/spawner/random/pool/spaceloot/syndicate/common/depot, /obj/structure/closet/secure_closet/depot, /turf/simulated/floor/plasteel{ icon_state = "dark" @@ -38753,7 +38753,7 @@ /area/centcom/ss220/admin1) "wLN" = ( /obj/effect/turf_decal/delivery, -/obj/effect/spawner/random/syndicate/loot/common, +/obj/effect/spawner/random/pool/spaceloot/syndicate/common/depot, /obj/structure/closet/secure_closet/depot, /obj/structure/fans/tiny/invisible, /turf/simulated/floor/plasteel{ diff --git a/code/__DEFINES/MC.dm b/code/__DEFINES/MC.dm index 05d92a11ee1f..641fcc941d38 100644 --- a/code/__DEFINES/MC.dm +++ b/code/__DEFINES/MC.dm @@ -95,3 +95,12 @@ }\ /datum/controller/subsystem/timer/##X/fire() {..() /*just so it shows up on the profiler*/} \ /datum/controller/subsystem/timer/##X + +#define MOVEMENT_SUBSYSTEM_DEF(X) GLOBAL_REAL(SS##X, /datum/controller/subsystem/movement/##X);\ +/datum/controller/subsystem/movement/##X/New(){\ + NEW_SS_GLOBAL(SS##X);\ + PreInit();\ + ss_id="movement_[#X]";\ +}\ +/datum/controller/subsystem/movement/##X/fire() {..() /*just so it shows up on the profiler*/} \ +/datum/controller/subsystem/movement/##X diff --git a/code/__DEFINES/color_defines.dm b/code/__DEFINES/color_defines.dm index 42b513901aa6..a22a6c6cbb13 100644 --- a/code/__DEFINES/color_defines.dm +++ b/code/__DEFINES/color_defines.dm @@ -111,6 +111,7 @@ #define COLOR_BLOOD_BASE "#A10808" #define COLOR_BLOOD_MACHINE "#1F181F" +#define COLOR_BLOOD_XENO "#05EE05" // Pipe colours #define PIPE_COLOR_GREY "#ffffff" //yes white is grey diff --git a/code/__DEFINES/dcs/mob_signals.dm b/code/__DEFINES/dcs/mob_signals.dm index e9b71bdc58b7..bcbdc4fbf73c 100644 --- a/code/__DEFINES/dcs/mob_signals.dm +++ b/code/__DEFINES/dcs/mob_signals.dm @@ -218,3 +218,12 @@ /// from remove_ventcrawler(): (mob/living/crawler) #define COMSIG_LIVING_EXIT_VENTCRAWL "living_exit_ventcrawl" + +/// 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/movable_signals.dm b/code/__DEFINES/dcs/movable_signals.dm index 7aa2beca9330..59152fb06644 100644 --- a/code/__DEFINES/dcs/movable_signals.dm +++ b/code/__DEFINES/dcs/movable_signals.dm @@ -70,3 +70,19 @@ /// Called when blocking a teleport #define COMSIG_ATOM_INTERCEPT_TELEPORTED "intercept_teleported" #define COMPONENT_BLOCK_TELEPORT (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/apply_initial_visuals(): () +#define COMSIG_MOVABLE_DRIFT_VISUAL_ATTEMPT "movable_drift_visual_attempt" + #define DRIFT_VISUAL_FAILED (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) + +///called when the movable's glide size is updated: (new_glide_size) +#define COMSIG_MOVABLE_UPDATE_GLIDE_SIZE "movable_glide_size" + +///signal sent out by an atom when it is no longer pulling something : (atom/pulling) +#define COMSIG_ATOM_NO_LONGER_PULLING "movable_no_longer_pulling" diff --git a/code/__DEFINES/dcs/moveloop_signals.dm b/code/__DEFINES/dcs/moveloop_signals.dm new file mode 100644 index 000000000000..c93d93251836 --- /dev/null +++ b/code/__DEFINES/dcs/moveloop_signals.dm @@ -0,0 +1,15 @@ +///from [/datum/move_loop/start_loop] (): +#define COMSIG_MOVELOOP_START "moveloop_start" +///from [/datum/move_loop/stop_loop] (): +#define COMSIG_MOVELOOP_STOP "moveloop_stop" +///from [/datum/move_loop/process] (): +#define COMSIG_MOVELOOP_PREPROCESS_CHECK "moveloop_preprocess_check" + #define MOVELOOP_SKIP_STEP (1<<0) +///from [/datum/move_loop/process] (succeeded, visual_delay): +#define COMSIG_MOVELOOP_POSTPROCESS "moveloop_postprocess" +//from [/datum/move_loop/has_target/jps/recalculate_path] (): +#define COMSIG_MOVELOOP_JPS_REPATH "moveloop_jps_repath" +///From base of /datum/move_loop/process() after attempting to move a movable: (datum/move_loop/loop, old_dir) +#define COMSIG_MOVABLE_MOVED_FROM_LOOP "movable_moved_from_loop" +///from [/datum/move_loop/has_target/jps/on_finish_pathing] +#define COMSIG_MOVELOOP_JPS_FINISHED_PATHING "moveloop_jps_finished_pathing" diff --git a/code/__DEFINES/dcs/obj_signals.dm b/code/__DEFINES/dcs/obj_signals.dm index 936667d709ff..4b138f7146a3 100644 --- a/code/__DEFINES/dcs/obj_signals.dm +++ b/code/__DEFINES/dcs/obj_signals.dm @@ -22,6 +22,14 @@ #define COMSIG_GLOB_CURSED_SLOT_MACHINE_WON "cursed_slot_machine_won" +// /obj/item/tank/jetpack + +/// from /obj/item/tank/jetpack/proc/turn_on() : () +#define COMSIG_JETPACK_ACTIVATED "jetpack_activated" + #define JETPACK_ACTIVATION_FAILED (1<<0) +/// from /obj/item/tank/jetpack/proc/turn_off() : () +#define COMSIG_JETPACK_DEACTIVATED "jetpack_deactivated" + // other subtypes /// from /datum/component/shelved/UnregisterFromParent(): (parent_uid) diff --git a/code/__DEFINES/directions.dm b/code/__DEFINES/directions.dm index 718ebeedf14f..702a6b9008bc 100644 --- a/code/__DEFINES/directions.dm +++ b/code/__DEFINES/directions.dm @@ -29,6 +29,11 @@ /// returns TRUE if direction is cardinal and false if not #define IS_DIR_CARDINAL(dir) (!IS_DIR_DIAGONAL(dir)) +///True if the dir is north or south, false therwise +#define NSCOMPONENT(d) (d&(NORTH|SOUTH)) +///True if the dir is east/west, false otherwise +#define EWCOMPONENT(d) (d&(EAST|WEST)) + /// Inverse direction, taking into account UP|DOWN if necessary. #define REVERSE_DIR(dir) ( ((dir & 85) << 1) | ((dir & 170) >> 1) ) /// returns TRUE if the direction is EAST or WEST @@ -36,4 +41,13 @@ /// returns TRUE if the direction is NORTH or SOUTH #define DIR_JUST_VERTICAL(dir) ((dir == NORTH) || (dir == SOUTH)) +/// North direction as a string "[1]" +#define TEXT_NORTH "[NORTH]" +/// South direction as a string "[2]" +#define TEXT_SOUTH "[SOUTH]" +/// East direction as a string "[4]" +#define TEXT_EAST "[EAST]" +/// West direction as a string "[8]" +#define TEXT_WEST "[WEST]" + #define EXCLUSIVE_OR(thing_one, thing_two) ((thing_one)^(thing_two)) diff --git a/code/__DEFINES/mob_defines.dm b/code/__DEFINES/mob_defines.dm index d3eb93078ea4..92fa20a22f80 100644 --- a/code/__DEFINES/mob_defines.dm +++ b/code/__DEFINES/mob_defines.dm @@ -383,3 +383,7 @@ #define BRAIN_DAMAGE_RATIO_MODERATE 6 / 12 #define BRAIN_DAMAGE_RATIO_SEVERE 8 / 12 #define BRAIN_DAMAGE_RATIO_CRITICAL 10 / 12 + +#define GRAB_PIXEL_SHIFT_PASSIVE 6 +#define GRAB_PIXEL_SHIFT_AGGRESSIVE 12 +#define GRAB_PIXEL_SHIFT_NECK 16 diff --git a/code/__DEFINES/movement_defines.dm b/code/__DEFINES/movement_defines.dm new file mode 100644 index 000000000000..cb76916dc0e8 --- /dev/null +++ b/code/__DEFINES/movement_defines.dm @@ -0,0 +1,71 @@ +/// The minimum for glide_size to be clamped to. +#define MIN_GLIDE_SIZE 1 +/// The maximum for glide_size to be clamped to. +/// This shouldn't be higher than the icon size, and generally you shouldn't be changing this, but it's here just in case. +#define MAX_GLIDE_SIZE 32 + +//Movement loop priority. Only one loop can run at a time, this dictates that +// Higher numbers beat lower numbers +///Standard, go lower then this if you want to override, higher otherwise +#define MOVEMENT_DEFAULT_PRIORITY 10 +///Very few things should override this +#define MOVEMENT_SPACE_PRIORITY 100 +///Higher then the heavens +#define MOVEMENT_ABOVE_SPACE_PRIORITY (MOVEMENT_SPACE_PRIORITY + 1) + +//Movement loop flags +///Should the loop act immediately following its addition? +#define MOVEMENT_LOOP_START_FAST (1<<0) +///Do we not use the priority system? +#define MOVEMENT_LOOP_IGNORE_PRIORITY (1<<1) +///Should we override the loop's glide? +#define MOVEMENT_LOOP_IGNORE_GLIDE (1<<2) +///Should we not update our movables dir on move? +#define MOVEMENT_LOOP_NO_DIR_UPDATE (1<<3) +///Is the loop moving the movable outside its control, like it's an external force? e.g. footsteps won't play if enabled. +#define MOVEMENT_LOOP_OUTSIDE_CONTROL (1<<4) + +// Movement loop status flags +/// Has the loop been paused, soon to be resumed? +#define MOVELOOP_STATUS_PAUSED (1<<0) +/// Is the loop running? (Is true even when paused) +#define MOVELOOP_STATUS_RUNNING (1<<1) +/// Is the loop queued in a subsystem? +#define MOVELOOP_STATUS_QUEUED (1<<2) + +/** + * Returns a bitfield containing flags both present in `flags` arg and the `processing_move_loop_flags` move_packet variable. + * Has no use outside of procs called within the movement proc chain. + */ +#define CHECK_MOVE_LOOP_FLAGS(movable, flags) (movable.move_packet ? (movable.move_packet.processing_move_loop_flags & (flags)) : NONE) + +//Index defines for movement bucket data packets +#define MOVEMENT_BUCKET_TIME 1 +#define MOVEMENT_BUCKET_LIST 2 + +///Return values for moveloop Move() +#define MOVELOOP_FAILURE 0 +#define MOVELOOP_SUCCESS 1 +#define MOVELOOP_NOT_READY 2 + +#define ACTIVE_MOVEMENT_OLDLOC 1 +#define ACTIVE_MOVEMENT_DIRECTION 2 +#define ACTIVE_MOVEMENT_FORCED 3 +#define ACTIVE_MOVEMENT_OLDLOCS 4 + +/// The arguments of this macro correspond directly to the argument order of /atom/movable/proc/Moved +#define SET_ACTIVE_MOVEMENT(_old_loc, _direction, _forced, _oldlocs) \ + active_movement = list( \ + _old_loc, \ + _direction, \ + _forced, \ + _oldlocs, \ + ) + +/// Finish any active movements +#define RESOLVE_ACTIVE_MOVEMENT \ + if(active_movement) { \ + var/__move_args = active_movement; \ + active_movement = null; \ + Moved(arglist(__move_args)); \ + } diff --git a/code/__DEFINES/movement_info.dm b/code/__DEFINES/movement_info.dm deleted file mode 100644 index 95c90f7a1fba..000000000000 --- a/code/__DEFINES/movement_info.dm +++ /dev/null @@ -1,16 +0,0 @@ -/// The arguments of this macro correspond directly to the argument order of /atom/movable/proc/Moved -#define SET_ACTIVE_MOVEMENT(_old_loc, _direction, _forced, _oldlocs) \ - active_movement = list( \ - _old_loc, \ - _direction, \ - _forced, \ - _oldlocs, \ - ) - -/// Finish any active movements -#define RESOLVE_ACTIVE_MOVEMENT \ - if(active_movement) { \ - var/__move_args = active_movement; \ - active_movement = null; \ - Moved(arglist(__move_args)); \ - } diff --git a/code/__DEFINES/text_defines.dm b/code/__DEFINES/text_defines.dm index cd4b28b6d75d..e45e0787f0ec 100644 --- a/code/__DEFINES/text_defines.dm +++ b/code/__DEFINES/text_defines.dm @@ -6,6 +6,7 @@ #define MAX_CHARACTERS_PER_BOOKPAGE 5000 #define MAX_SUMMARY_LEN 1500 #define MAX_NAME_LEN 50 //diona names can get loooooooong +#define MAX_FLAVORTEXT_PRINT 400 //Amount of flavor text characters to print before cutting off. /// Removes characters incompatible with file names. #define SANITIZE_FILENAME(text) (GLOB.filename_forbidden_chars.Replace(text, "")) diff --git a/code/__DEFINES/vehicle_defines.dm b/code/__DEFINES/vehicle_defines.dm index 4cd27e39aa69..be45aea5fac7 100644 --- a/code/__DEFINES/vehicle_defines.dm +++ b/code/__DEFINES/vehicle_defines.dm @@ -30,10 +30,16 @@ /// The vehicle being ridden requires pixel offsets for all directions #define RIDING_OFFSET_ALL "ALL" +/// Compensating for time dilation +GLOBAL_VAR_INIT(glide_size_multiplier, 1.0) + ///Broken down, here's what this does: /// divides the world icon_size (32) by delay divided by ticklag to get the number of pixels something should be moving each tick. /// The division result is given a min value of 1 to prevent obscenely slow glide sizes from being set /// Then that's multiplied by the global glide size multiplier. 1.25 by default feels pretty close to spot on. This is just to try to get byond to behave. /// The whole result is then clamped to within the range above. /// Not very readable but it works -#define DELAY_TO_GLIDE_SIZE(delay) (clamp(((world.icon_size / max((delay) / world.tick_lag, 1))), 1, 32)) +#define DELAY_TO_GLIDE_SIZE(delay) (clamp(((world.icon_size / max((delay) / world.tick_lag, 1)) * GLOB.glide_size_multiplier), MIN_GLIDE_SIZE, MAX_GLIDE_SIZE)) + +///Similar to DELAY_TO_GLIDE_SIZE, except without the clamping, and it supports piping in an unrelated scalar +#define MOVEMENT_ADJUSTED_GLIDE_SIZE(delay, movement_disparity) (world.icon_size / ((delay) / world.tick_lag) * movement_disparity * GLOB.glide_size_multiplier) diff --git a/code/__HELPERS/lists.dm b/code/__HELPERS/lists.dm index 959af27e822a..47947cb245f1 100644 --- a/code/__HELPERS/lists.dm +++ b/code/__HELPERS/lists.dm @@ -49,6 +49,44 @@ };\ } while(FALSE) +#define SORT_FIRST_INDEX(list) (list[1]) +#define SORT_COMPARE_DIRECTLY(thing) (thing) +#define SORT_VAR_NO_TYPE(varname) var/varname + +/**** + * Even more custom binary search sorted insert, using defines instead of vars + * INPUT: Item to be inserted + * LIST: List to insert INPUT into + * TYPECONT: A define setting the var to the typepath of the contents of the list + * COMPARE: The item to compare against, usualy the same as INPUT + * COMPARISON: A define that takes an item to compare as input, and returns their comparable value + * COMPTYPE: How should the list be compared? Either COMPARE_KEY or COMPARE_VALUE. + */ +#define BINARY_INSERT_DEFINE(INPUT, LIST, TYPECONT, COMPARE, COMPARISON, COMPTYPE) \ + do {\ + var/list/__BIN_LIST = LIST;\ + var/__BIN_CTTL = length(__BIN_LIST);\ + if(!__BIN_CTTL) {\ + __BIN_LIST += INPUT;\ + } else {\ + var/__BIN_LEFT = 1;\ + var/__BIN_RIGHT = __BIN_CTTL;\ + var/__BIN_MID = (__BIN_LEFT + __BIN_RIGHT) >> 1;\ + ##TYPECONT(__BIN_ITEM);\ + while(__BIN_LEFT < __BIN_RIGHT) {\ + __BIN_ITEM = COMPTYPE;\ + if(##COMPARISON(__BIN_ITEM) <= ##COMPARISON(COMPARE)) {\ + __BIN_LEFT = __BIN_MID + 1;\ + } else {\ + __BIN_RIGHT = __BIN_MID;\ + };\ + __BIN_MID = (__BIN_LEFT + __BIN_RIGHT) >> 1;\ + };\ + __BIN_ITEM = COMPTYPE;\ + __BIN_MID = ##COMPARISON(__BIN_ITEM) > ##COMPARISON(COMPARE) ? __BIN_MID : __BIN_MID + 1;\ + __BIN_LIST.Insert(__BIN_MID, INPUT);\ + };\ + } while(FALSE) // Generic listoflist safe add and removal macros: ///If value is a list, wrap it in a list so it can be used with list add/remove operations diff --git a/code/__HELPERS/mob_helpers.dm b/code/__HELPERS/mob_helpers.dm index 23e6df82eedd..d3732086582f 100644 --- a/code/__HELPERS/mob_helpers.dm +++ b/code/__HELPERS/mob_helpers.dm @@ -336,7 +336,7 @@ var/user_loc = user.loc var/drifting = 0 - if(!user.Process_Spacemove(0) && user.inertia_dir) + if(GLOB.move_manager.processing_on(user, SSspacedrift)) drifting = 1 var/target_loc = target.loc @@ -367,7 +367,7 @@ break continue - if(drifting && !user.inertia_dir) + if(drifting && !GLOB.move_manager.processing_on(user, SSspacedrift)) drifting = 0 user_loc = user.loc @@ -398,7 +398,7 @@ var/atom/Uloc = user.loc var/drifting = FALSE - if(!allow_moving && !user.Process_Spacemove(0) && user.inertia_dir) + if(!allow_moving && GLOB.move_manager.processing_on(user, SSspacedrift)) drifting = TRUE var/holding = user.get_active_hand() @@ -426,7 +426,7 @@ if(progress) progbar.update(world.time - starttime) if(!allow_moving) - if(drifting && !user.inertia_dir) + if(drifting && !GLOB.move_manager.processing_on(user, SSspacedrift)) drifting = FALSE Uloc = user.loc if(!drifting && user.loc != Uloc) diff --git a/code/__HELPERS/trait_helpers.dm b/code/__HELPERS/trait_helpers.dm index 5243e3473fda..824927828226 100644 --- a/code/__HELPERS/trait_helpers.dm +++ b/code/__HELPERS/trait_helpers.dm @@ -437,6 +437,10 @@ Remember to update _globalvars/traits.dm if you're adding/removing/renaming trai // Causes the effect to go through a teleporter instead of being deleted by it. #define TRAIT_EFFECT_CAN_TELEPORT "trait_effect_can_teleport" +//***** MOVABLE ATOM TRAITS *****// +// Prevents the atom from being transitioned to another Z level when approaching the edge of the map. +#define TRAIT_NO_EDGE_TRANSITIONS "trait_no_edge_transitions" + //***** PROC WRAPPERS *****// /// Proc wrapper of add_trait. You should only use this for callback. Otherwise, use the macro. /proc/callback_add_trait(datum/target, trait, source) diff --git a/code/__HELPERS/unsorted.dm b/code/__HELPERS/unsorted.dm index d9b0875dd4d2..99a0b48e5734 100644 --- a/code/__HELPERS/unsorted.dm +++ b/code/__HELPERS/unsorted.dm @@ -1748,6 +1748,9 @@ GLOBAL_DATUM_INIT(dview_mob, /mob/dview, new) matches[key] = value return matches +/proc/return_typenames(type) + return splittext("[type]", "/") + //Key thing that stops lag. Cornerstone of performance in ss13, Just sitting here, in unsorted.dm. //Increases delay as the server gets more overloaded, diff --git a/code/_globalvars/traits.dm b/code/_globalvars/traits.dm index 7e4d94bf4d13..c9a69c212ba9 100644 --- a/code/_globalvars/traits.dm +++ b/code/_globalvars/traits.dm @@ -1,6 +1,6 @@ /* FUN ZONE OF ADMIN LISTINGS - Try to keep this in sync with __DEFINES/traits.dm + Try to keep this in sync with __HELPERS/trait_helpers.dm quirks have it's own panel so we don't need them here. */ GLOBAL_LIST_INIT(traits_by_type, list( @@ -150,6 +150,10 @@ GLOBAL_LIST_INIT(traits_by_type, list( /obj/effect = list( "TRAIT_EFFECT_CAN_TELEPORT" = TRAIT_EFFECT_CAN_TELEPORT + ), + + /atom/movable = list( + "TRAIT_NO_EDGE_TRANSITIONS" = TRAIT_NO_EDGE_TRANSITIONS ) )) diff --git a/code/controllers/subsystem/SSair.dm b/code/controllers/subsystem/SSair.dm index 2701124ec466..435c0766588d 100644 --- a/code/controllers/subsystem/SSair.dm +++ b/code/controllers/subsystem/SSair.dm @@ -17,6 +17,10 @@ SUBSYSTEM_DEF(air) flags = SS_BACKGROUND | SS_TICKER /// How long we actually wait between ticks. Will round up to the next server tick. var/self_wait = 0.15 SECONDS + /// MC seems to not be good at tracking whether SSair pauses, so track that ourselves. + var/was_paused = FALSE + /// And that means we also nee a replacement for times_fired. + var/milla_tick = 0 runlevels = RUNLEVEL_GAME | RUNLEVEL_POSTGAME offline_implications = "Turfs will no longer process atmos, and all atmospheric machines (including cryotubes) will no longer function. Shuttle call recommended." cpu_display = SS_CPUDISPLAY_HIGH @@ -186,11 +190,15 @@ SUBSYSTEM_DEF(air) currentpart = SSair.currentpart milla_idle = SSair.milla_idle +/datum/controller/subsystem/air/pause() + was_paused = TRUE + return ..() + /datum/controller/subsystem/air/fire(resumed = 0) // All atmos stuff assumes MILLA is synchronous. Ensure it actually is. var/now = world.timeofday + (world.tick_lag * world.tick_usage) / 100 var/elapsed = now - last_complete_tick - if(!milla_idle || (elapsed >= 0 && elapsed < self_wait)) + if(!milla_idle || length(sleepers) || (elapsed >= 0 && elapsed < self_wait)) return if(last_tick_start <= last_complete_tick) @@ -200,12 +208,13 @@ SUBSYSTEM_DEF(air) // Run the sleepless callbacks again in case more showed up since on_milla_tick_finished() run_sleepless_callbacks() - fire_sleepless(resumed) + fire_sleepless(resumed || was_paused) /datum/controller/subsystem/air/proc/fire_sleepless(resumed) // Any proc that wants MILLA to be synchronous should not sleep. SHOULD_NOT_SLEEP(TRUE) in_milla_safe_code = TRUE + was_paused = FALSE var/timer = TICK_USAGE_REAL @@ -317,6 +326,7 @@ SUBSYSTEM_DEF(air) timer = TICK_USAGE_REAL spawn_milla_tick_thread() + milla_tick++ milla_idle = FALSE cost_milla_tick = MC_AVERAGE(cost_milla_tick, get_milla_tick_time()) @@ -415,9 +425,9 @@ SUBSYSTEM_DEF(air) // Bind the MILLA tile we got, if needed. if(isnull(T.bound_air)) bind_turf(T, milla_tile) - else if(T.bound_air.lastread < times_fired) + else if(T.bound_air.lastread < milla_tick) T.bound_air.copy_from_milla(milla_tile) - T.bound_air.lastread = times_fired + T.bound_air.lastread = milla_tick T.bound_air.readonly = null T.bound_air.dirty = FALSE T.bound_air.synchronized = FALSE @@ -446,7 +456,7 @@ SUBSYSTEM_DEF(air) if(isnull(S.wind_tick)) // Didn't have wind before, add it. windy_tiles += S - S.wind_tick = times_fired + S.wind_tick = milla_tick S.wind_x = x_flow S.wind_y = y_flow T.high_pressure_movements(x_flow, y_flow) @@ -463,15 +473,17 @@ SUBSYSTEM_DEF(air) var/list/currentrun = src.currentrun while(length(currentrun)) var/turf/simulated/S = currentrun[length(currentrun)] - currentrun.len-- if(!istype(S)) + currentrun.len-- continue if(S.update_hotspot()) // Is still a hotspot, keep it. new_hotspots += S + currentrun.len-- + if(MC_TICK_CHECK) return @@ -627,33 +639,12 @@ SUBSYSTEM_DEF(air) /datum/controller/subsystem/air/proc/setup_turfs(turf/low_corner = locate(1, 1, 1), turf/high_corner = locate(world.maxx, world.maxy, world.maxz)) for(var/turf/T as anything in block(low_corner, high_corner)) - T.Initialize_Atmos(times_fired) + T.Initialize_Atmos(milla_tick) milla_load_turfs(low_corner, high_corner) for(var/turf/T as anything in block(low_corner, high_corner)) T.milla_data.len = 0 T.milla_data = null -/datum/controller/subsystem/air/proc/setup_write_to_milla() - var/watch = start_watch() - log_startup_progress("Writing tiles to MILLA...") - - //cache for sanic speed (lists are references anyways) - var/list/cache = bound_mixtures - var/count = length(cache) - while(length(cache)) - var/datum/gas_mixture/bound_to_turf/mixture = cache[length(cache)] - cache.len-- - if(mixture.dirty) - in_milla_safe_code = TRUE - // This is one of two places expected to call this otherwise-unsafe method. - mixture.private_unsafe_write() - in_milla_safe_code = FALSE - mixture.bound_turf.bound_air = null - mixture.bound_turf = null - CHECK_TICK - - log_startup_progress("Wrote [count] tiles in [stop_watch(watch)]s.") - /datum/controller/subsystem/air/proc/setup_atmos_machinery(list/machines_to_init) var/watch = start_watch() log_startup_progress("Initializing atmospherics machinery...") @@ -713,7 +704,7 @@ SUBSYSTEM_DEF(air) milla_tile = new/list(MILLA_TILE_SIZE) get_tile_atmos(T, milla_tile) B.copy_from_milla(milla_tile) - B.lastread = src.times_fired + B.lastread = src.milla_tick B.readonly = null B.dirty = FALSE B.synchronized = FALSE @@ -832,11 +823,11 @@ SUBSYSTEM_DEF(air) soft_assert_safe() // This is one of two intended places to call this otherwise-unsafe proc. var/datum/gas_mixture/bound_to_turf/air = T.private_unsafe_get_air() - if(air.lastread < SSair.times_fired) + if(air.lastread < SSair.milla_tick) var/list/milla_tile = new/list(MILLA_TILE_SIZE) get_tile_atmos(T, milla_tile) air.copy_from_milla(milla_tile) - air.lastread = SSair.times_fired + air.lastread = SSair.milla_tick air.readonly = null air.dirty = FALSE if(!air.synchronized) @@ -882,11 +873,11 @@ SUBSYSTEM_DEF(air) soft_assert_safe() // This is one of two intended places to call this otherwise-unsafe proc. var/datum/gas_mixture/bound_to_turf/air = T.private_unsafe_get_air() - if(air.lastread < SSair.times_fired) + if(air.lastread < SSair.milla_tick) var/list/milla_tile = new/list(MILLA_TILE_SIZE) get_tile_atmos(T, milla_tile) air.copy_from_milla(milla_tile) - air.lastread = SSair.times_fired + air.lastread = SSair.milla_tick air.readonly = null air.dirty = FALSE if(!air.synchronized) diff --git a/code/controllers/subsystem/SSspacedrift.dm b/code/controllers/subsystem/SSspacedrift.dm deleted file mode 100644 index 2707f12518fb..000000000000 --- a/code/controllers/subsystem/SSspacedrift.dm +++ /dev/null @@ -1,66 +0,0 @@ -SUBSYSTEM_DEF(spacedrift) - name = "Space Drift" - priority = FIRE_PRIORITY_SPACEDRIFT - wait = 5 - flags = SS_NO_INIT|SS_KEEP_TIMING - runlevels = RUNLEVEL_GAME | RUNLEVEL_POSTGAME - offline_implications = "Mobs will no longer respect a lack of gravity. No immediate action is needed." - cpu_display = SS_CPUDISPLAY_LOW - - var/list/currentrun = list() - var/list/processing = list() - -/datum/controller/subsystem/spacedrift/get_stat_details() - return "P:[length(processing)]" - -/datum/controller/subsystem/spacedrift/get_metrics() - . = ..() - var/list/cust = list() - cust["processing"] = length(processing) - .["custom"] = cust - -/datum/controller/subsystem/spacedrift/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[length(currentrun)] - currentrun.len-- - if(!AM) - processing -= AM - if(MC_TICK_CHECK) - return - continue - - if(AM.inertia_next_move > world.time) - if(MC_TICK_CHECK) - return - continue - - if(!AM.loc || AM.loc != AM.inertia_last_loc || AM.Process_Spacemove(0)) - AM.inertia_dir = 0 - - if(!AM.inertia_dir) - AM.inertia_last_loc = null - processing -= AM - if(MC_TICK_CHECK) - return - continue - - var/old_dir = AM.dir - var/old_loc = AM.loc - AM.inertia_moving = TRUE - AM.Move(get_step(AM, AM.inertia_dir), AM.inertia_dir, AM.inertia_move_delay) - AM.inertia_moving = FALSE - AM.inertia_next_move = world.time + AM.inertia_move_delay - if(AM.loc == old_loc) - AM.inertia_dir = 0 - - AM.setDir(old_dir) - AM.inertia_last_loc = AM.loc - if(MC_TICK_CHECK) - return - diff --git a/code/controllers/subsystem/SSthrowing.dm b/code/controllers/subsystem/SSthrowing.dm index 7c452f930f7b..16f9b57b9b64 100644 --- a/code/controllers/subsystem/SSthrowing.dm +++ b/code/controllers/subsystem/SSthrowing.dm @@ -224,7 +224,7 @@ SUBSYSTEM_DEF(throwing) finalize() return - if(!AM.Move(step, get_dir(AM, step))) // we hit something during our move... + if(!AM.Move(step, get_dir(AM, step), DELAY_TO_GLIDE_SIZE(1 / speed))) // we hit something during our move... if(AM.throwing) // ...but finalize() wasn't called on Bump() because of a higher level definition that doesn't always call parent. finalize() return diff --git a/code/controllers/subsystem/SStime_track.dm b/code/controllers/subsystem/SStime_track.dm index 5f15a1bf9e42..e645077e8621 100644 --- a/code/controllers/subsystem/SStime_track.dm +++ b/code/controllers/subsystem/SStime_track.dm @@ -29,6 +29,7 @@ SUBSYSTEM_DEF(time_track) time_dilation_avg_fast = MC_AVERAGE_FAST(time_dilation_avg_fast, time_dilation_current) time_dilation_avg = MC_AVERAGE(time_dilation_avg, time_dilation_avg_fast) time_dilation_avg_slow = MC_AVERAGE_SLOW(time_dilation_avg_slow, time_dilation_avg) + GLOB.glide_size_multiplier = (current_byondtime - last_tick_byond_time) / (current_realtime - last_tick_realtime) else first_run = FALSE last_tick_realtime = current_realtime diff --git a/code/controllers/subsystem/movement/SSmovement.dm b/code/controllers/subsystem/movement/SSmovement.dm new file mode 100644 index 000000000000..d6cad4a734d3 --- /dev/null +++ b/code/controllers/subsystem/movement/SSmovement.dm @@ -0,0 +1,134 @@ +SUBSYSTEM_DEF(movement) + name = "Movement Loops" + flags = SS_NO_INIT|SS_BACKGROUND|SS_TICKER + wait = 1 //Fire each tick + /* + A breif aside about the bucketing system here + + The goal is to allow for higher loads of semi long delays while reducing cpu usage + Bucket insertion and management are much less complex then what you might see in SStimer + This is intentional, as we loop our delays much more often then that ss is designed for + We also have much shorter term timers, so we need to worry about redundant buckets much less + */ + ///Assoc list of "target time" -> list(things to process). Used for quick lookup + var/list/buckets = list() + ///Sorted list of list(target time, bucket to process) + var/list/sorted_buckets = list() + ///The time we started our last fire at + var/canonical_time = 0 + ///The visual delay of the subsystem + var/visual_delay = 1 + +/datum/controller/subsystem/movement/stat_entry(msg) + var/total_len = 0 + for(var/list/bucket as anything in sorted_buckets) + total_len += length(bucket[MOVEMENT_BUCKET_LIST]) + msg = "B:[length(sorted_buckets)] E:[total_len]" + return ..() + +/datum/controller/subsystem/movement/Recover() + //Get ready this is gonna be horrible + //We need to do this to support subtypes by the by + var/list/typenames = return_typenames(src.type) + var/our_name = typenames[length(typenames)] //Get the last name in the list, IE the subsystem identifier + + var/datum/controller/subsystem/movement/old_version = global.vars["SS[our_name]"] + buckets = old_version.buckets + sorted_buckets = old_version.sorted_buckets + +/datum/controller/subsystem/movement/fire(resumed) + if(!resumed) + canonical_time = world.time + + for(var/list/bucket_info as anything in sorted_buckets) + var/time = bucket_info[MOVEMENT_BUCKET_TIME] + if(time > canonical_time || MC_TICK_CHECK) + return + pour_bucket(bucket_info) + +/// Processes a bucket of movement loops (This should only ever be called by fire(), it exists to prevent runtime fuckery) +/datum/controller/subsystem/movement/proc/pour_bucket(list/bucket_info) + var/list/processing = bucket_info[MOVEMENT_BUCKET_LIST] // Cache for lookup speed + while(processing.len) + var/datum/move_loop/loop = processing[processing.len] + processing.len-- + // No longer queued since we just got removed from the loop + loop.queued_time = null + loop.process() //This shouldn't get nulls, if it does, runtime + if(!QDELETED(loop) && loop.status & MOVELOOP_STATUS_QUEUED) //Re-Insert the loop + loop.status &= ~MOVELOOP_STATUS_QUEUED + loop.timer = world.time + loop.delay + queue_loop(loop) + if(MC_TICK_CHECK) + break + + if(length(processing)) + return // Still work to be done + var/bucket_time = bucket_info[MOVEMENT_BUCKET_TIME] + smash_bucket(1, bucket_time) // We assume we're the first bucket in the queue right now + visual_delay = MC_AVERAGE_FAST(visual_delay, max((world.time - canonical_time) / wait, 1)) + +/// Removes a bucket from our system. You only need to pass in the time, but if you pass in the index of the list you save us some work +/datum/controller/subsystem/movement/proc/smash_bucket(index, bucket_time) + var/sorted_length = length(sorted_buckets) + if(!index) + index = sorted_length + 1 // let's setup the failure condition + for(var/i in 1 to sorted_length) + var/list/bucket_info = sorted_buckets[i] + if(bucket_info[MOVEMENT_BUCKET_TIME] != bucket_time) + continue + index = i + break + //This is technically possible, if our bucket is smashed inside the loop's process + //Let's be nice, the cost of doing it is cheap + if(index > sorted_length || !buckets["[bucket_time]"]) + return + + sorted_buckets.Cut(index, index + 1) //Removes just this list + //Removes the assoc lookup too + buckets -= "[bucket_time]" + +/datum/controller/subsystem/movement/proc/queue_loop(datum/move_loop/loop) + if(loop.status & MOVELOOP_STATUS_QUEUED) + stack_trace("A move loop attempted to queue while already queued") + return + loop.queued_time = loop.timer + loop.status |= MOVELOOP_STATUS_QUEUED + var/list/our_bucket = buckets["[loop.queued_time]"] + // If there's no bucket for this, lets set them up + if(!our_bucket) + buckets["[loop.queued_time]"] = list() + our_bucket = buckets["[loop.queued_time]"] + // This makes assoc buckets and sorted buckets point to the same place, allowing for quicker inserts + var/list/new_bucket = list(list(loop.queued_time, our_bucket)) + var/list/compare_item = list(loop.queued_time) + BINARY_INSERT_DEFINE(new_bucket, sorted_buckets, SORT_VAR_NO_TYPE, compare_item, SORT_FIRST_INDEX, COMPARE_KEY) + + our_bucket += loop + +/datum/controller/subsystem/movement/proc/dequeue_loop(datum/move_loop/loop) + // Go home, you're not here anyway + if(!(loop.status & MOVELOOP_STATUS_QUEUED)) + return + if(isnull(loop.queued_time)) // This happens if a moveloop is dequeued while handling process() + loop.status &= ~MOVELOOP_STATUS_QUEUED + return + var/list/our_entries = buckets["[loop.queued_time]"] + our_entries -= loop + if(!length(our_entries)) + smash_bucket(bucket_time = loop.queued_time) // We can't pass an index in for context because we don't know our position + loop.queued_time = null + loop.status &= ~MOVELOOP_STATUS_QUEUED + +/datum/controller/subsystem/movement/proc/add_loop(datum/move_loop/add) + if(add.status & MOVELOOP_STATUS_QUEUED) + CRASH("Loop being added that is already queued.") + add.loop_started() + if(QDELETED(add) || add.status & MOVELOOP_STATUS_QUEUED) + return + queue_loop(add) + +/datum/controller/subsystem/movement/proc/remove_loop(datum/move_loop/remove) + dequeue_loop(remove) + remove.loop_stopped() + diff --git a/code/controllers/subsystem/movement/SSspacedrift.dm b/code/controllers/subsystem/movement/SSspacedrift.dm new file mode 100644 index 000000000000..4002b5eb555f --- /dev/null +++ b/code/controllers/subsystem/movement/SSspacedrift.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/subsystem/movement/movement_types.dm b/code/controllers/subsystem/movement/movement_types.dm new file mode 100644 index 000000000000..2bf8212316b9 --- /dev/null +++ b/code/controllers/subsystem/movement/movement_types.dm @@ -0,0 +1,832 @@ +///Template class of the movement datums, handles the timing portion of the loops +/datum/move_loop + ///The movement packet that owns us + var/datum/movement_packet/owner + ///The subsystem we're processing on + var/datum/controller/subsystem/movement/controller + ///An extra reference we pass around + ///It is on occasion useful to have a reference to some datum without storing it on the moving object + ///Mostly comes up in high performance senarios where we care about things being singletons + ///This feels horrible, but constantly making components seems worse + var/datum/extra_info + ///The thing we're moving about + var/atom/movable/moving + ///Defines how different move loops override each other. Higher numbers beat lower numbers + var/priority = MOVEMENT_DEFAULT_PRIORITY + ///Bitfield of different things that affect how a loop operates, and other mechanics around it as well. + var/flags + ///Time till we stop processing in deci-seconds, defaults to forever + var/lifetime = INFINITY + ///Delay between each move in deci-seconds + var/delay = 1 + ///The next time we should process + ///Used primarially as a hint to be reasoned about by our [controller], and as the id of our bucket + var/timer = 0 + ///The time we are CURRENTLY queued for processing + ///Do not modify this directly + var/queued_time = -1 + /// Status bitfield for what state the move loop is currently in + var/status = NONE + +/datum/move_loop/New(datum/movement_packet/owner, datum/controller/subsystem/movement/controller, atom/moving, priority, flags, datum/extra_info) + src.owner = owner + src.controller = controller + src.extra_info = extra_info + if(extra_info) + RegisterSignal(extra_info, COMSIG_PARENT_QDELETING, PROC_REF(info_deleted)) + src.moving = moving + src.priority = priority + src.flags = flags + +/datum/move_loop/proc/setup(delay = 1, timeout = INFINITY) + if(!ismovable(moving) || !owner) + return FALSE + + src.delay = max(delay, world.tick_lag) //Please... + src.lifetime = timeout + return TRUE + +///check if this exact moveloop datum already exists (in terms of vars) so we can avoid creating a new one to overwrite the old duplicate +/datum/move_loop/proc/compare_loops(datum/move_loop/loop_type, priority, flags, extra_info, delay = 1, timeout = INFINITY) + SHOULD_CALL_PARENT(TRUE) + if(loop_type == type && priority == src.priority && flags == src.flags && delay == src.delay && timeout == lifetime) + return TRUE + return FALSE + +///Called when a loop is starting by a movement subsystem +/datum/move_loop/proc/loop_started() + SHOULD_CALL_PARENT(TRUE) + SEND_SIGNAL(src, COMSIG_MOVELOOP_START) + status |= MOVELOOP_STATUS_RUNNING + //If this is our first time starting to move with this loop + //And we're meant to start instantly + if(!timer && flags & MOVEMENT_LOOP_START_FAST) + timer = world.time + return + timer = world.time + delay + +///Called when a loop is stopped, doesn't stop the loop itself +/datum/move_loop/proc/loop_stopped() + SHOULD_CALL_PARENT(TRUE) + status &= ~MOVELOOP_STATUS_RUNNING + SEND_SIGNAL(src, COMSIG_MOVELOOP_STOP) + +/datum/move_loop/proc/info_deleted(datum/source) + SIGNAL_HANDLER + extra_info = null + +/datum/move_loop/Destroy() + if(owner) + owner.remove_loop(controller, src) + owner = null + moving = null + controller = null + extra_info = null + return ..() + +///Exists as a helper so outside code can modify delay in a sane way +/datum/move_loop/proc/set_delay(new_delay) + delay = max(new_delay, world.tick_lag) + +///Pauses the move loop for some passed in period +///This functionally means shifting its timer up, and clearing it from its current bucket +/datum/move_loop/proc/pause_for(time) + if(!controller || !(status & MOVELOOP_STATUS_RUNNING)) //No controller or not running? go away + return + //Dequeue us from our current bucket + controller.dequeue_loop(src) + //Offset our timer + timer = world.time + time + //Now requeue us with our new target start time + controller.queue_loop(src) + +/datum/move_loop/process() + if(isnull(controller)) + qdel(src) + return + + var/old_delay = delay //The signal can sometimes change delay + + if(SEND_SIGNAL(src, COMSIG_MOVELOOP_PREPROCESS_CHECK) & MOVELOOP_SKIP_STEP) //Chance for the object to react + return + + lifetime -= old_delay //This needs to be based on work over time, not just time passed + + if(lifetime < 0) //Otherwise lag would make things look really weird + qdel(src) + return + + var/visual_delay = controller.visual_delay + var/old_dir = moving.dir + var/old_loc = moving.loc + + owner?.processing_move_loop_flags = flags + var/result = move() //Result is an enum value. Enums defined in __DEFINES/movement.dm + if(moving) + var/direction = get_dir(old_loc, moving.loc) + SEND_SIGNAL(moving, COMSIG_MOVABLE_MOVED_FROM_LOOP, src, old_dir, direction) + owner?.processing_move_loop_flags = NONE + + SEND_SIGNAL(src, COMSIG_MOVELOOP_POSTPROCESS, result, delay * visual_delay) + + if(QDELETED(src) || result != MOVELOOP_SUCCESS) //Can happen + return + + if(flags & MOVEMENT_LOOP_IGNORE_GLIDE) + return + + 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() + return MOVELOOP_FAILURE + + +///Pause our loop untill restarted with resume_loop() +/datum/move_loop/proc/pause_loop() + if(!controller || !(status & MOVELOOP_STATUS_RUNNING) || (status & MOVELOOP_STATUS_PAUSED)) //we dead + return + + //Dequeue us from our current bucket + controller.dequeue_loop(src) + status |= MOVELOOP_STATUS_PAUSED + +///Resume our loop after being paused by pause_loop() +/datum/move_loop/proc/resume_loop() + if(!controller || (status & MOVELOOP_STATUS_RUNNING|MOVELOOP_STATUS_PAUSED) != (MOVELOOP_STATUS_RUNNING|MOVELOOP_STATUS_PAUSED)) + return + + timer = world.time + controller.queue_loop(src) + status &= ~MOVELOOP_STATUS_PAUSED + +///Removes the atom from some movement subsystem. Defaults to 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 + return our_info.remove_subsystem(subsystem) + +/** + * Replacement for walk() + * + * Returns TRUE if the loop sucessfully started, or FALSE if it failed + * + * Arguments: + * moving - The atom we want to move + * direction - The direction we want to move in + * 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/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() +/datum/move_loop/move + var/direction + +/datum/move_loop/move/setup(delay, timeout, dir) + . = ..() + if(!.) + return + direction = dir + +/datum/move_loop/move/compare_loops(datum/move_loop/loop_type, priority, flags, extra_info, delay, timeout, dir) + if(..() && direction == dir) + return TRUE + return FALSE + +/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)) + // 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 + + +/** + * Like move(), but we don't care about collision at all + * + * Returns TRUE if the loop sucessfully started, or FALSE if it failed + * + * Arguments: + * moving - The atom we want to move + * direction - The direction we want to move in + * 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/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 + +/datum/move_loop/move/force/move() + var/atom/old_loc = moving.loc + moving.forceMove(get_step(moving, direction)) + return old_loc != moving?.loc ? MOVELOOP_SUCCESS : MOVELOOP_FAILURE + + +/datum/move_loop/has_target + ///The thing we're moving in relation to, either at or away from + var/atom/target + +/datum/move_loop/has_target/setup(delay, timeout, atom/chasing) + . = ..() + if(!.) + return + if(!isatom(chasing)) + qdel(src) + return FALSE + + target = chasing + + if(!isturf(target)) + RegisterSignal(target, COMSIG_PARENT_QDELETING, PROC_REF(handle_no_target)) //Don't do this for turfs, because we don't care + +/datum/move_loop/has_target/compare_loops(datum/move_loop/loop_type, priority, flags, extra_info, delay, timeout, atom/chasing) + if(..() && chasing == target) + return TRUE + return FALSE + +/datum/move_loop/has_target/Destroy() + target = null + return ..() + +/datum/move_loop/has_target/proc/handle_no_target() + SIGNAL_HANDLER + qdel(src) + + +/** + * Used for force-move loops, similar to move_towards_legacy() but not quite the same + * + * 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 + * 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/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 +/datum/move_loop/has_target/force_move + +/datum/move_loop/has_target/force_move/move() + var/atom/old_loc = moving.loc + moving.forceMove(get_step(moving, get_dir(moving, target))) + return old_loc != moving?.loc ? MOVELOOP_SUCCESS : MOVELOOP_FAILURE + + +/** + * Used for following jps defined paths. The proc signature here's a bit long, I'm sorry + * + * 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 + * +**/ +/datum/move_manager/proc/jps_move(moving, + chasing, + delay, + timeout, + repath_delay, + max_path_length, + minimum_distance, + list/access, + simulated_only, + turf/avoid, + skip_first, + subsystem, + diagonal_handling, + priority, + flags, + datum/extra_info, + initial_path) + return add_to_loop(moving, + subsystem, + /datum/move_loop/has_target/jps, + priority, + flags, + extra_info, + delay, + timeout, + chasing, + repath_delay, + max_path_length, + minimum_distance, + access, + simulated_only, + avoid, + skip_first, + diagonal_handling, + initial_path) + +/datum/move_loop/has_target/jps + ///How often we're allowed to recalculate our path + var/repath_delay + ///Max amount of steps to search + var/max_path_length + ///Minimum distance to the target before path returns + var/minimum_distance + ///A list representing what access we have and what doors we can open. + var/list/access + ///Whether we consider turfs without atmos simulation (AKA do we want to ignore space) + var/simulated_only + ///A perticular turf to avoid + var/turf/avoid + ///Should we skip the first step? This is the tile we're currently on, which breaks some things + var/skip_first + ///Whether we replace diagonal movements with cardinal movements or follow through with them + var/diagonal_handling + ///A list for the path we're currently following + var/list/movement_path + ///Cooldown for repathing, prevents spam + COOLDOWN_DECLARE(repath_cooldown) + ///Bool used to determine if we're already making a path in JPS. this prevents us from re-pathing while we're already busy. + var/is_pathing = FALSE + ///Callbacks to invoke once we make a path + var/list/datum/callback/on_finish_callbacks = list() + +/datum/move_loop/has_target/jps/New(datum/movement_packet/owner, datum/controller/subsystem/movement/controller, atom/moving, priority, flags, datum/extra_info) + . = ..() + on_finish_callbacks += CALLBACK(src, PROC_REF(on_finish_pathing)) + +/datum/move_loop/has_target/jps/setup(delay, timeout, atom/chasing, repath_delay, max_path_length, minimum_distance, list/access, simulated_only, turf/avoid, skip_first, diagonal_handling, list/initial_path) + . = ..() + if(!.) + return + src.repath_delay = repath_delay + src.max_path_length = max_path_length + src.minimum_distance = minimum_distance + src.access = access + src.simulated_only = simulated_only + src.avoid = avoid + src.skip_first = skip_first + src.diagonal_handling = diagonal_handling + movement_path = initial_path?.Copy() + +/datum/move_loop/has_target/jps/compare_loops(datum/move_loop/loop_type, priority, flags, extra_info, delay, timeout, atom/chasing, repath_delay, max_path_length, minimum_distance, list/access, simulated_only, turf/avoid, skip_first, initial_path) + if(..() && repath_delay == src.repath_delay && max_path_length == src.max_path_length && minimum_distance == src.minimum_distance && access ~= src.access && simulated_only == src.simulated_only && avoid == src.avoid) + return TRUE + return FALSE + +/datum/move_loop/has_target/jps/loop_started() + . = ..() + if(!movement_path) + INVOKE_ASYNC(src, PROC_REF(recalculate_path)) + +/datum/move_loop/has_target/jps/loop_stopped() + . = ..() + movement_path = null + +/datum/move_loop/has_target/jps/Destroy() + avoid = null + on_finish_callbacks = null + return ..() + +///Tries to calculate a new path for this moveloop. +/datum/move_loop/has_target/jps/proc/recalculate_path() + if(!COOLDOWN_FINISHED(src, repath_cooldown)) + return + COOLDOWN_START(src, repath_cooldown, repath_delay) + if(SSpathfinder.pathfind(moving, target, max_path_length, minimum_distance, access, simulated_only, avoid, skip_first, diagonal_handling, on_finish = on_finish_callbacks)) + is_pathing = TRUE + SEND_SIGNAL(src, COMSIG_MOVELOOP_JPS_REPATH) + +///Called when a path has finished being created +/datum/move_loop/has_target/jps/proc/on_finish_pathing(list/path) + movement_path = path + is_pathing = FALSE + SEND_SIGNAL(src, COMSIG_MOVELOOP_JPS_FINISHED_PATHING, path) + +/datum/move_loop/has_target/jps/move() + if(!length(movement_path)) + if(is_pathing) + return MOVELOOP_NOT_READY + else + INVOKE_ASYNC(src, PROC_REF(recalculate_path)) + return MOVELOOP_FAILURE + + 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)) + . = (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 + // to the side while moving but could maybe still follow their path without needing a whole new path + if(get_turf(moving) == next_step) + if(length(movement_path)) + movement_path.Cut(1,2) + else + INVOKE_ASYNC(src, PROC_REF(recalculate_path)) + return MOVELOOP_FAILURE + + +///Base class of move_to and move_away, deals with the distance and target aspect of things +/datum/move_loop/has_target/dist_bound + var/distance = 0 + +/datum/move_loop/has_target/dist_bound/setup(delay, timeout, atom/chasing, dist = 0) + . = ..() + if(!.) + return + distance = dist + +/datum/move_loop/has_target/dist_bound/compare_loops(datum/move_loop/loop_type, priority, flags, extra_info, delay, timeout, atom/chasing, dist = 0) + if(..() && distance == dist) + return TRUE + return FALSE + +///Returns FALSE if the movement should pause, TRUE otherwise +/datum/move_loop/has_target/dist_bound/proc/check_dist() + return FALSE + +/datum/move_loop/has_target/dist_bound/move() + if(!check_dist()) //If we're too close don't do the move + return MOVELOOP_FAILURE + return MOVELOOP_SUCCESS + + +/** + * Wrapper around walk_to() + * + * 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 + * +**/ +/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() +/datum/move_loop/has_target/dist_bound/move_to + +/datum/move_loop/has_target/dist_bound/move_to/check_dist() + return (get_dist(moving, target) > distance) //If you get too close, stop moving closer + +/datum/move_loop/has_target/dist_bound/move_to/move() + . = ..() + if(!.) + return + var/atom/old_loc = moving.loc + var/turf/next = get_step_to(moving, target) + moving.Move(next, get_dir(moving, next), FALSE, !(flags & MOVEMENT_LOOP_NO_DIR_UPDATE)) + return old_loc != moving?.loc ? MOVELOOP_SUCCESS : MOVELOOP_FAILURE + +/** + * Wrapper around GLOB.move_manager.move_away() + * + * 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 + * +**/ +/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 GLOB.move_manager.move_away() +/datum/move_loop/has_target/dist_bound/move_away + +/datum/move_loop/has_target/dist_bound/move_away/check_dist() + return (get_dist(moving, target) < distance) //If you get too far out, stop moving away + +/datum/move_loop/has_target/dist_bound/move_away/move() + . = ..() + if(!.) + 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)) + return old_loc != moving?.loc ? MOVELOOP_SUCCESS : MOVELOOP_FAILURE + + +/** + * Helper proc for the move_towards datum + * + * 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 + * +**/ +/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) + +/** + * Helper proc for homing onto something with move_towards + * + * 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 + * +**/ +/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 GLOB.move_manager.home_onto +/datum/move_loop/has_target/move_towards + ///The turf we want to move into, used for course correction + var/turf/moving_towards + ///Should we try and stay on the path, or is deviation alright + var/home = FALSE + ///When this gets larger then 1 we move a turf + var/x_ticker = 0 + var/y_ticker = 0 + ///The rate at which we move, between 0 and 1 + var/x_rate = 1 + var/y_rate = 1 + //We store the signs of x and y seperately, because byond will round negative numbers down + //So doing all our operations with absolute values then multiplying them is easier + var/x_sign = 0 + var/y_sign = 0 + +/datum/move_loop/has_target/move_towards/setup(delay, timeout, atom/chasing, home = FALSE) + . = ..() + if(!.) + return FALSE + src.home = home + + if(home) + if(ismovable(target)) + RegisterSignal(target, COMSIG_MOVABLE_MOVED, PROC_REF(update_slope)) //If it can move, update your slope when it does + RegisterSignal(moving, COMSIG_MOVABLE_MOVED, PROC_REF(handle_move)) + update_slope() + +/datum/move_loop/has_target/move_towards/compare_loops(datum/move_loop/loop_type, priority, flags, extra_info, delay, timeout, atom/chasing, home = FALSE) + if(..() && home == src.home) + return TRUE + return FALSE + +/datum/move_loop/has_target/move_towards/Destroy() + if(home) + if(ismovable(target)) + UnregisterSignal(target, COMSIG_MOVABLE_MOVED) + if(moving) + UnregisterSignal(moving, COMSIG_MOVABLE_MOVED) + return ..() + +/datum/move_loop/has_target/move_towards/move() + //Move our tickers forward a step, we're guaranteed at least one step forward because of how the code is written + if(x_rate) //Did you know that rounding by 0 throws a divide by 0 error? + x_ticker = FLOOR(x_ticker + x_rate, x_rate) + if(y_rate) + y_ticker = FLOOR(y_ticker + y_rate, y_rate) + + var/x = moving.x + var/y = moving.y + var/z = moving.z + + moving_towards = locate(x + round(x_ticker) * x_sign, y + round(y_ticker) * y_sign, z) + //The tickers serve as good methods of tracking remainder + if(x_ticker >= 1) + x_ticker = MODULUS(x_ticker, 1) //I swear to god if you somehow go up by one then one in a tick I'm gonna go mad + 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)) + + //YOU FOUND THEM! GOOD JOB + if(home && get_turf(moving) == get_turf(target)) + x_rate = 0 + y_rate = 0 + return + return old_loc != moving?.loc ? MOVELOOP_SUCCESS : MOVELOOP_FAILURE + +/datum/move_loop/has_target/move_towards/proc/handle_move(source, atom/OldLoc, Dir, Forced = FALSE) + SIGNAL_HANDLER + if(moving.loc != moving_towards && home) //If we didn't go where we should have, update slope to account for the deviation + update_slope() + +/datum/move_loop/has_target/move_towards/handle_no_target() + if(home) + return ..() + target = null + +/** + * Recalculates the slope between our object and the target, sets our rates to it + * + * The math below is reminiscent of something like y = mx + b + * Except we don't need to care about axis, since we do all our movement in steps of 1 + * Because of that all that matters is we only move one tile at a time + * So we take the smaller delta, divide it by the larger one, and get smaller step per large step + * Then we set the large step to 1, and we're done. This way we're guaranteed to never move more then a tile at once + * And we can have nice lines +**/ +/datum/move_loop/has_target/move_towards/proc/update_slope() + SIGNAL_HANDLER + + //You'll notice this is rise over run, except we flip the formula upside down depending on the larger number + //This is so we never move more then one tile at once + var/delta_y = target.y - moving.y + var/delta_x = target.x - moving.x + //It's more convienent to store delta x and y as absolute values + //and modify them right at the end then it is to deal with rounding errors + x_sign = (delta_x > 0) ? 1 : -1 + y_sign = (delta_y > 0) ? 1 : -1 + delta_x = abs(delta_x) + delta_y = abs(delta_y) + + if(delta_x >= delta_y) + if(delta_x == 0) //Just go up/down + x_rate = 0 + y_rate = 1 + return + x_rate = 1 + y_rate = delta_y / delta_x //rise over run, you know the deal + else + if(delta_y == 0) //Just go right/left + x_rate = 1 + y_rate = 0 + return + x_rate = delta_x / delta_y //Keep the larger step size at 1 + y_rate = 1 + +/** + * Wrapper for GLOB.move_manager.home_onto, not reccomended, as its movement ends up being a bit stilted + * + * 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 + * 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/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 GLOB.move_manager.home_onto() +/datum/move_loop/has_target/move_towards_budget + +/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)) + return old_loc != moving?.loc ? MOVELOOP_SUCCESS : MOVELOOP_FAILURE + +/** + * Assigns a target to a move loop that immediately freezes for a set duration of time. + * + * Returns TRUE if the loop sucessfully started, or FALSE if it failed + * + * Arguments: + * moving - The atom we want to move + * halted_turf - The turf we want to freeze on. This should typically be the loc of moving. + * 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. This should be considered extremely non-optional as it will completely stun out the movement loop forever if unset. + * 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/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. +/datum/move_loop/freeze + +/datum/move_loop/freeze/move() + return MOVELOOP_SUCCESS // it's successful because it's not moving. we autoclear outselves when `timeout` is reached + +/** + * Helper proc for the move_rand datum + * + * Returns TRUE if the loop sucessfully started, or FALSE if it failed + * + * Arguments: + * moving - The atom we want to move + * directions - A list of acceptable directions to try and move in. Defaults to GLOB.alldirs + * 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/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) + +/** + * This isn't actually the same as walk_rand + * Because walk_rand is really more like walk_to_rand + * It appears to pick a spot outside of range, and move towards it, then pick a new spot, etc. + * I can't actually replicate this on our side, because of how bad our pathfinding is, and cause I'm not totally sure I know what it's doing. + * I can just implement a random-walk though +**/ +/datum/move_loop/move_rand + var/list/potential_directions + +/datum/move_loop/move_rand/setup(delay, timeout, list/directions) + . = ..() + if(!.) + return + potential_directions = directions + +/datum/move_loop/move_rand/compare_loops(datum/move_loop/loop_type, priority, flags, extra_info, delay, timeout, list/directions) + if(..() && (length(potential_directions | directions) == length(potential_directions))) //i guess this could be useful if actually it really has yet to move + return MOVELOOP_SUCCESS + return MOVELOOP_FAILURE + +/datum/move_loop/move_rand/move() + var/list/potential_dirs = potential_directions.Copy() + while(potential_dirs.len) + 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)) + if(old_loc != moving?.loc) //If it worked, we're done + return MOVELOOP_SUCCESS + potential_dirs -= testdir + return MOVELOOP_FAILURE + +/** + * Wrapper around walk_rand(), doesn't actually result in a random walk, it's more like moving to random places in viewish + * + * Returns TRUE if the loop sucessfully started, or FALSE if it failed + * + * Arguments: + * moving - The atom we want to move + * 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/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 +/datum/move_loop/move_to_rand + +/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)) + return old_loc != moving?.loc ? MOVELOOP_SUCCESS : MOVELOOP_FAILURE diff --git a/code/datums/components/drift.dm b/code/datums/components/drift.dm new file mode 100644 index 000000000000..6d6945ba28d1 --- /dev/null +++ b/code/datums/components/drift.dm @@ -0,0 +1,194 @@ +///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_PARENT_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) + +/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 ..() + +/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.setDir(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/datums/components/jetpack_component.dm b/code/datums/components/jetpack_component.dm new file mode 100644 index 000000000000..c82ce4fda72b --- /dev/null +++ b/code/datums/components/jetpack_component.dm @@ -0,0 +1,152 @@ +// Welcome to the jetpack component +// Apply this to something when you want it to be "like a jetpack" +// So propulsion through space on move, that sort of thing +/datum/component/jetpack + dupe_mode = COMPONENT_DUPE_UNIQUE_PASSARGS + /// Checks to ensure if we can move & if we can activate + var/datum/callback/check_on_move + /// If we should stabilize ourselves when not drifting + var/stabilize = FALSE + /// The signal we listen for as an activation + var/activation_signal + /// The signal we listen for as a de-activation + var/deactivation_signal + /// The return flag our parent expects for a failed activation + var/return_flag + /// The effect system for the jet pack trail + var/datum/effect_system/trail_follow/trail + /// The typepath to instansiate our trail as, when we need it + var/effect_type + +/** + * Arguments: + * * stabilize - If we should drift when we finish moving, or sit stable in space] + * * activation_signal - Signal we activate on + * * deactivation_signal - Signal we deactivate on + * * return_flag - Flag to return if activation fails + * * check_on_move - Callback we call each time we attempt a move, we expect it to retun true if the move is ok, false otherwise. It expects an arg, TRUE if fuel should be consumed, FALSE othewise + * * effect_type - Type of trail_follow to spawn + */ +/datum/component/jetpack/Initialize(stabilize, activation_signal, deactivation_signal, return_flag, datum/callback/check_on_move, datum/effect_system/trail_follow/effect_type) + . = ..() + if(!isatom(parent)) + return COMPONENT_INCOMPATIBLE + if(!activation_signal) // Can't activate? go away + return COMPONENT_INCOMPATIBLE + + RegisterSignal(parent, activation_signal, PROC_REF(activate)) + if(deactivation_signal) + RegisterSignal(parent, deactivation_signal, PROC_REF(deactivate)) + + src.stabilize = stabilize + src.check_on_move = check_on_move + src.activation_signal = activation_signal + src.deactivation_signal = deactivation_signal + src.return_flag = return_flag + src.effect_type = effect_type + +/datum/component/jetpack/InheritComponent(datum/component/component, original, stabilize, activation_signal, deactivation_signal, return_flag, datum/callback/check_on_move, datum/effect_system/trail_follow/effect_type) + UnregisterSignal(parent, src.activation_signal) + if(src.deactivation_signal) + UnregisterSignal(parent, src.deactivation_signal) + RegisterSignal(parent, activation_signal, PROC_REF(activate)) + if(deactivation_signal) + RegisterSignal(parent, deactivation_signal, PROC_REF(deactivate)) + + src.stabilize = stabilize + src.check_on_move = check_on_move + src.activation_signal = activation_signal + src.deactivation_signal = deactivation_signal + src.return_flag = return_flag + src.effect_type = effect_type + + if(trail && trail.effect_type != effect_type) + setup_trail(trail.holder) + +/datum/component/jetpack/Destroy(force) + if(trail) + QDEL_NULL(trail) + check_on_move = null + return ..() + +/datum/component/jetpack/proc/setup_trail(mob/user) + if(trail) + QDEL_NULL(trail) + + trail = new effect_type + trail.auto_process = FALSE + trail.set_up(user) + trail.start() + +/datum/component/jetpack/proc/activate(datum/source, mob/user) + SIGNAL_HANDLER + + if(!check_on_move.Invoke(TRUE)) + return return_flag + + RegisterSignal(user, COMSIG_MOVABLE_MOVED, PROC_REF(move_react)) + RegisterSignal(user, COMSIG_MOVABLE_PRE_MOVE, PROC_REF(pre_move_react)) + RegisterSignal(user, COMSIG_MOVABLE_SPACEMOVE, PROC_REF(spacemove_react)) + RegisterSignal(user, COMSIG_MOVABLE_DRIFT_VISUAL_ATTEMPT, PROC_REF(block_starting_visuals)) + RegisterSignal(user, COMSIG_MOVABLE_DRIFT_BLOCK_INPUT, PROC_REF(ignore_ending_block)) + + setup_trail(user) + +/datum/component/jetpack/proc/deactivate(datum/source, mob/user) + SIGNAL_HANDLER + + UnregisterSignal(user, COMSIG_MOVABLE_MOVED) + UnregisterSignal(user, COMSIG_MOVABLE_PRE_MOVE) + UnregisterSignal(user, COMSIG_MOVABLE_SPACEMOVE) + UnregisterSignal(user, COMSIG_MOVABLE_DRIFT_VISUAL_ATTEMPT) + UnregisterSignal(user, COMSIG_MOVABLE_DRIFT_BLOCK_INPUT) + + if(trail) + QDEL_NULL(trail) + +/datum/component/jetpack/proc/move_react(mob/user) + SIGNAL_HANDLER + if(!user || !user.client)//Don't allow jet self using + return + if(!isturf(user.loc))//You can't use jet in nowhere or from mecha/closet + return + if(user.mob_has_gravity() || user.buckled)//You don't want use jet in gravity or while buckled. + return + if(user.pulledby)//You can't use jet if someone pull you + return + if(user.throwing)//You can't use jet if you thrown + return + if(user.client.calculate_move_dir())//You use jet when press keys. yes. + thrust() + +/datum/component/jetpack/proc/pre_move_react(mob/user) + SIGNAL_HANDLER + if(!trail) + return FALSE + trail.oldposition = get_turf(user) + +/datum/component/jetpack/proc/spacemove_react(mob/user, movement_dir, continuous_move) + SIGNAL_HANDLER + if(!continuous_move && movement_dir) + return COMSIG_MOVABLE_STOP_SPACEMOVE + // Check if we have the fuel to stop this. Do NOT cosume any fuel, just check + // This is done because things other then us can use our fuel + if(stabilize && check_on_move.Invoke(FALSE)) + return COMSIG_MOVABLE_STOP_SPACEMOVE + +/// Returns true if the thrust went well, false otherwise +/datum/component/jetpack/proc/thrust() + if(!check_on_move.Invoke(TRUE)) + return FALSE + trail.generate_effect() + return TRUE + +/// Basically, tell the drift component not to do its starting visuals, because they look dumb for us +/datum/component/jetpack/proc/block_starting_visuals(datum/source) + SIGNAL_HANDLER + return DRIFT_VISUAL_FAILED + +/// If we're on, don't let the drift component block movements at the end since we can speed +/datum/component/jetpack/proc/ignore_ending_block(datum/source) + SIGNAL_HANDLER + return DRIFT_ALLOW_INPUT diff --git a/code/datums/components/riding/riding_vehicle.dm b/code/datums/components/riding/riding_vehicle.dm index 0f5825f1b398..440ba225b267 100644 --- a/code/datums/components/riding/riding_vehicle.dm +++ b/code/datums/components/riding/riding_vehicle.dm @@ -70,7 +70,7 @@ if(!turf_check(next, current)) to_chat(user, "[movable_parent] cannot go onto [next]!") return - if(!Process_Spacemove(direction) || !isturf(movable_parent.loc)) + if(GLOB.move_manager.processing_on(user, SSspacedrift) || !isturf(movable_parent.loc)) return step(movable_parent, direction) diff --git a/code/datums/datumvars.dm b/code/datums/datumvars.dm index e0825b725e7d..fa6044d15cc0 100644 --- a/code/datums/datumvars.dm +++ b/code/datums/datumvars.dm @@ -786,7 +786,7 @@ to_chat(usr, "This can only be used on instances of type /mob/living/carbon/human") return - var/haltype = input(usr, "Select the hallucination type:", "Hallucinate") as null|anything in (subtypesof(/obj/effect/hallucination) + subtypesof(/datum/hallucination_manager)) + var/haltype = tgui_input_list(usr, "Select Hallucination Type", "Hallucinate", (subtypesof(/obj/effect/hallucination) + subtypesof(/datum/hallucination_manager))) if(!haltype) return C.invoke_hallucination(haltype) diff --git a/code/datums/move_manager.dm b/code/datums/move_manager.dm new file mode 100644 index 000000000000..23ddcbecdb70 --- /dev/null +++ b/code/datums/move_manager.dm @@ -0,0 +1,173 @@ +/** + * Acts as a namespace for movement packet/type related procs + * + * Exists to provide an in code implementation of movement looping + * Replaces things like walk() or walk_to(), among others + * + * Because we're doing things in engine, we have a lot more control over how different operations are performed + * We also get more say in when things happen, so we can subject movements to the whims of the master controller + * Rather then using a fuck ton of cpu just moving mobs or meteors + * + * The goal is to keep the loops themselves reasonably barebone, and implement more advanced behavior and control via the signals + * + * This may be bypassed in cases where snowflakes are nessesary, or where performance is important. S not a hard and fast thing + * + * Every atom can have a movement packet, which contains information and behavior about currently active loops, and queuing info + * Loops control how movement actually happens. So there's a "move in this direction" loop, a "move randomly" loop + * + * 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/move_manager/proc/add_to_loop] helper procs that use them + * +**/ +/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/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) + + var/list/arguments = args.Copy(2) //Drop the atom, since the movement packet already knows about it + return our_data.add_loop(arglist(arguments)) + +///Returns the subsystem's loop if we're processing on it, null otherwise +/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 + var/datum/move_loop/linked_loop = packet.existing_loops[subsystem] + if(!linked_loop) + return + if(linked_loop.flags & MOVEMENT_LOOP_IGNORE_PRIORITY) + return linked_loop + if(linked_loop != packet.running_loop) + return + return linked_loop + +///A packet of information that describes the current state of a moving object +/datum/movement_packet + ///Our parent atom + var/atom/movable/parent + ///The move loop that's currently running, excluding those that ignore priority. + var/datum/move_loop/running_loop + /** + * Flags passed from the move loop before it calls move() and unset right after. + * Allows for properties of a move loop to be easily checked by mechanics outside of it. + * Having this a bitfield rather than a type var means we don't get screwed over + * if the move loop gets deleted mid-move, FYI. + */ + var/processing_move_loop_flags = NONE + ///Assoc list of subsystems -> loop datum. Only one datum is allowed per subsystem + var/list/existing_loops = list() + +/datum/movement_packet/New(atom/movable/parent) + src.parent = parent + parent.move_packet = src + +/datum/movement_packet/Destroy(force) + parent.move_packet = null + parent = null + for(var/datum/controller/subsystem/processor as anything in existing_loops) + var/datum/move_loop/loop = existing_loops[processor] + if(QDELETED(loop)) + continue + qdel(loop) + existing_loops.Cut() + existing_loops = null //Catch anyone modifying this post del + return ..() + +///Adds a loop to our parent. Returns the created loop if a success, null otherwise +/datum/movement_packet/proc/add_loop(datum/controller/subsystem/movement/subsystem, datum/move_loop/loop_type, priority, flags, datum/extra_info) + var/datum/move_loop/existing_loop = existing_loops[subsystem] + + if(existing_loop && existing_loop.priority > priority) + if(!(existing_loop.flags & MOVEMENT_LOOP_IGNORE_PRIORITY) && !(flags & MOVEMENT_LOOP_IGNORE_PRIORITY)) + return //Give up + + if(existing_loop?.compare_loops(arglist(args.Copy(2)))) + return //it already exists stop trying to make the same moveloop + + var/datum/move_loop/new_loop = new loop_type(src, subsystem, parent, priority, flags, extra_info) //Pass the mob to move and ourselves in via new + var/list/arguments = args.Copy(6) //Just send the args we've not already dealt with + + var/worked_out = new_loop.setup(arglist(arguments)) //Here goes the rest + if(!worked_out) + qdel(new_loop) + return + + existing_loops[subsystem] = new_loop + if(existing_loop) + qdel(existing_loop) //We need to do this here because otherwise the packet would think it was empty, and self destruct + contest_running_loop(new_loop) + return new_loop + +///Attempts to contest the current running move loop. Returns TRUE if the loop is active, FALSE otherwise +/datum/movement_packet/proc/contest_running_loop(datum/move_loop/contestant) + var/datum/controller/subsystem/movement/contesting_subsystem = contestant.controller + + if(contestant.flags & MOVEMENT_LOOP_IGNORE_PRIORITY) + contesting_subsystem.add_loop(contestant) + return TRUE + if(!running_loop) + running_loop = contestant + contesting_subsystem.add_loop(running_loop) + return TRUE + if(running_loop.priority > contestant.priority) + return FALSE + + var/datum/controller/subsystem/movement/current_subsystem = running_loop.controller + + var/current_running_loop = running_loop + running_loop = contestant + current_subsystem.remove_loop(current_running_loop) + if(running_loop != contestant) // A signal registrant could have messed with things + return FALSE + contesting_subsystem.add_loop(contestant) + return TRUE + +///Tries to figure out the current favorite loop to run. More complex then just deciding between two different loops, assumes no running loop currently exists +/datum/movement_packet/proc/decide_on_running_loop() + if(running_loop) + return + if(!length(existing_loops)) //Die + qdel(src) + return + var/datum/move_loop/favorite + for(var/datum/controller/subsystem/movement/owner as anything in existing_loops) + var/datum/move_loop/checking = existing_loops[owner] + if(checking.flags & MOVEMENT_LOOP_IGNORE_PRIORITY) + continue + if(favorite && favorite.priority > checking.priority) + continue + favorite = checking + + if(!favorite) //This isn't an error state, since some loops ignore the concept of a running loop + return + + var/datum/controller/subsystem/movement/favorite_subsystem = favorite.controller + + running_loop = favorite + favorite_subsystem.add_loop(running_loop) + +/datum/movement_packet/proc/remove_loop(datum/controller/subsystem/movement/remove_from, datum/move_loop/loop_to_remove) + if(loop_to_remove == running_loop) + running_loop = null + remove_from.remove_loop(loop_to_remove) + if(loop_to_remove.flags & MOVEMENT_LOOP_IGNORE_PRIORITY) + remove_from.remove_loop(loop_to_remove) + if(QDELETED(src)) + return + if(existing_loops[remove_from] == loop_to_remove) + existing_loops -= remove_from + decide_on_running_loop() + return + +/datum/movement_packet/proc/remove_subsystem(datum/controller/subsystem/movement/remove) + var/datum/move_loop/our_loop = existing_loops[remove] + if(!our_loop) + return FALSE + qdel(our_loop) + return TRUE diff --git a/code/datums/ruins/space_ruins.dm b/code/datums/ruins/space_ruins.dm index 6f6d1e35a839..fe924bec1cdd 100644 --- a/code/datums/ruins/space_ruins.dm +++ b/code/datums/ruins/space_ruins.dm @@ -225,7 +225,6 @@ name = "Suspicious Supply Depot" description = "A syndicate supply depot, heavily stocked, but heavily guarded with an assortment of shields, sentry bots, armed operatives and more." allow_duplicates = FALSE // One of these is enough - always_place = TRUE // This is on the always spawn list because of the shielding chance /datum/map_template/ruin/space/ussp_tele id = "ussp_tele" diff --git a/code/datums/spell_targeting/cone.dm b/code/datums/spell_targeting/cone.dm new file mode 100644 index 000000000000..7cc9b7a95610 --- /dev/null +++ b/code/datums/spell_targeting/cone.dm @@ -0,0 +1,74 @@ +/datum/spell_targeting/cone + max_targets = INFINITY + use_intercept_click = TRUE + /// This controls how many levels the cone has. Increase this value to make a bigger cone. + var/cone_levels = 3 + /// This value determines if the cone penetrates walls. + var/respect_density = FALSE + +/datum/spell_targeting/cone/choose_targets(mob/user, datum/spell/spell, params, atom/clicked_atom) + var/list/turfs_to_return = list() + var/turf/turf_to_use = get_turf(user) + var/turf/left_turf + var/turf/right_turf + var/dir_to_use = get_dir(user, clicked_atom) + var/right_dir + var/left_dir + switch(dir_to_use) + if(NORTH) + left_dir = WEST + right_dir = EAST + if(SOUTH) + left_dir = EAST + right_dir = WEST + if(EAST) + left_dir = NORTH + right_dir = SOUTH + if(WEST) + left_dir = SOUTH + right_dir = NORTH + + // Go though every level of the cone levels and generate the cone. + for(var/level in 1 to cone_levels) + var/list/level_turfs = list() + // Our center turf always exists, it's straight ahead of the caster. + turf_to_use = get_step(turf_to_use, dir_to_use) + level_turfs += turf_to_use + // Level 1 only ever has 1 turf, it's a cone. + if(level != 1) + var/level_width_in_each_direction = round((calculate_cone_shape(level) - 1) / 2) + left_turf = turf_to_use + right_turf = turf_to_use + // Check turfs to the left... + for(var/left_of_center in 1 to level_width_in_each_direction) + if(respect_density && left_turf.density) + break + left_turf = get_step(left_turf, left_dir) + level_turfs += left_turf + // And turfs to the right. + for(var/right_of_enter in 1 to level_width_in_each_direction) + if(respect_density && right_turf.density) + break + right_turf = get_step(right_turf, right_dir) + level_turfs += right_turf + // Add the list of all turfs on this level to the turfs to return + turfs_to_return += list(level_turfs) + + // If we're at the last level, we're done + if(level == cone_levels) + break + // But if we're not at the last level, we should check that we can keep going + if(respect_density && turf_to_use.density) + break + + return turfs_to_return + +/** + * Adjusts the width of the cone at the passed level. + * This is never called on the first level of the cone (level 1 is always 1 width) + * + * Return a number - the TOTAL width of the cone at the passed level. + */ +/datum/spell_targeting/cone/proc/calculate_cone_shape(current_level) + // Default formula: (1 (innate) -> 3 -> 5 -> 5 -> 7 -> 7 -> 9 -> 9 -> ...) + return current_level + (current_level % 2) + 1 diff --git a/code/datums/spells/cones/cone_spell.dm b/code/datums/spells/cones/cone_spell.dm new file mode 100644 index 000000000000..11b249c9f0d3 --- /dev/null +++ b/code/datums/spells/cones/cone_spell.dm @@ -0,0 +1,45 @@ +/datum/spell/cone + + +/datum/spell/cone/create_new_targeting() + return new /datum/spell_targeting/cone + +/datum/spell/cone/cast(list/targets, mob/user) + var/level_counter = 1 + for(var/list/turf_list in targets) + do_cone_effects(turf_list, user, level_counter) + level_counter++ + +/datum/spell/cone/proc/do_cone_effects(list/targets, mob/user, level) + for(var/turf/target_turf as anything in targets) + if(QDELETED(target_turf)) //if turf is no longer there + continue + + do_turf_cone_effect(target_turf, user, level) + if(iswallturf(target_turf)) + continue + + for(var/atom/movable/movable_content as anything in target_turf) + if(isobj(movable_content)) + do_obj_cone_effect(movable_content, user, level) + else if(isliving(movable_content)) + do_mob_cone_effect(movable_content, user, level) + +/datum/spell/cone/proc/do_turf_cone_effect(turf/target_turf, mob/caster, level) + return + +/datum/spell/cone/proc/do_obj_cone_effect(obj/target_obj, mob/caster, level) + return + +/datum/spell/cone/proc/do_mob_cone_effect(mob/target_mob, mob/caster, level) + return + +/datum/spell/cone/staggered + /// The delay between each cone level triggering. + var/delay_between_level = 0.2 SECONDS + +/datum/spell/cone/staggered/cast(list/targets, mob/user) + var/level_counter = 0 + for(var/list/turf_list in targets) + level_counter++ + addtimer(CALLBACK(src, PROC_REF(do_cone_effects), turf_list, user, level_counter), delay_between_level * level_counter) diff --git a/code/datums/spell.dm b/code/datums/spells/spell_base.dm similarity index 100% rename from code/datums/spell.dm rename to code/datums/spells/spell_base.dm diff --git a/code/datums/uplink_items/uplink_general.dm b/code/datums/uplink_items/uplink_general.dm index 43de5d7988b7..a3faae850e92 100644 --- a/code/datums/uplink_items/uplink_general.dm +++ b/code/datums/uplink_items/uplink_general.dm @@ -957,7 +957,10 @@ GLOBAL_LIST_INIT(uplink_items, subtypesof(/datum/uplink_item)) Can be used to parry incoming melee attacks." reference = "MBK" item = /obj/item/storage/box/syndie_kit/syndie_mantis - cost = 60 + cost = 75 + surplus = 0 + can_discount = FALSE + excludefrom = list(UPLINK_TYPE_NUCLEAR) //////////////////////////////////////// // MARK: POINTLESS BADASSERY diff --git a/code/datums/uplink_items/uplink_traitor.dm b/code/datums/uplink_items/uplink_traitor.dm index 214ba14e43ef..3c7aed661e79 100644 --- a/code/datums/uplink_items/uplink_traitor.dm +++ b/code/datums/uplink_items/uplink_traitor.dm @@ -228,7 +228,7 @@ /datum/uplink_item/jobspecific/telegun name = "Telegun" - desc = "An extremely high-tech energy gun that utilizes bluespace technology to teleport away living targets. Select the target beacon on the telegun itself; projectiles will send targets to the beacon locked onto. Can only send targets to beacons in-sector unless they are emagged!" + desc = "An extremely high-tech energy gun that utilizes jury-rigged bluespace technology to teleport away living targets. Select the target beacon on the telegun itself; projectiles will send targets to the beacon locked onto. Can only send targets to beacons in-sector unless they are emagged!" reference = "TG" item = /obj/item/gun/energy/telegun cost = 50 diff --git a/code/game/atoms_movable.dm b/code/game/atoms_movable.dm index 2c102af007a7..d9f72df023c8 100644 --- a/code/game/atoms_movable.dm +++ b/code/game/atoms_movable.dm @@ -22,15 +22,21 @@ var/atom/movable/pulling /// Face towards the atom while pulling it var/face_while_pulling = FALSE - /// Whether this atom should have its dir automatically changed when it moves. Setting this to FALSE allows for things such as directional windows to retain dir on moving without snowflake code all of the place. + /// Whether this atom should have its dir automatically changed when it + /// moves. Setting this to FALSE allows for things such as directional windows + /// to retain dir on moving without snowflake code all of the place. + /// PARA: Doesn't set this currently to maintain current behavior for pulling items around, + /// because modifying direction on pull is expected. var/set_dir_on_move = TRUE var/throwforce = 0 - var/inertia_dir = 0 - var/atom/inertia_last_loc - var/inertia_moving = 0 - var/inertia_next_move = 0 + ///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 + ///The last time we pushed off something + ///This is a hack to get around dumb him him me scenarios + var/last_pushoff var/moving_diagonally = 0 //0: not doing a diagonal move. 1 and 2: doing the first/second step of the diagonal move var/list/client_mobs_in_contents @@ -69,6 +75,10 @@ /// Used for icon smoothing. Won't smooth if it ain't anchored and can be unanchored. Only set to true on windows var/can_be_unanchored = FALSE + ///attempt to resume grab after moving instead of before. + var/atom/movable/moving_from_pull + ///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 /// How far (in pixels) should this atom scatter when created/dropped/etc. Does not apply to mapped-in items. var/scatter_distance = 0 @@ -116,6 +126,10 @@ loc = null if(pulledby) pulledby.stop_pulling() + if(move_packet) + if(!QDELETED(move_packet)) + qdel(move_packet) + move_packet = null if(opacity && istype(T)) var/old_has_opaque_atom = T.has_opaque_atom @@ -296,17 +310,22 @@ RESOLVE_ACTIVE_MOVEMENT -/atom/movable/Move(atom/newloc, direct = 0, movetime) +/atom/movable/Move(atom/newloc, direct = 0, glide_size_override = 0, update_dir = TRUE) + var/atom/movable/pullee = pulling + var/turf/current_turf = loc if(!loc || !newloc) return FALSE var/atom/oldloc = loc + if(SEND_SIGNAL(src, COMSIG_MOVABLE_PRE_MOVE, newloc) & COMPONENT_MOVABLE_BLOCK_PRE_MOVE) + return FALSE + + if(glide_size_override && glide_size != glide_size_override) + set_glide_size(glide_size_override) + if(loc != newloc) - if(movetime > 0) - glide_for(movetime) - if(IS_DIR_CARDINAL(direct)) - . = ..(newloc, direct) // don't pass up movetime - setDir(direct) + if(!IS_DIR_DIAGONAL(direct)) //Cardinal move + . = ..(newloc, direct) else //Diagonal move, split it into cardinal moves moving_diagonally = FIRST_DIAG_STEP var/first_step_dir = 0 @@ -328,31 +347,60 @@ moving_diagonally = SECOND_DIAG_STEP . = step(src, direct_NS) if(first_step_dir != 0) - if(!.) + if(!. && set_dir_on_move && update_dir) setDir(first_step_dir) + Moved(oldloc, first_step_dir) else if(!inertia_moving) - inertia_next_move = world.time + inertia_move_delay newtonian_move(direct) + if(client_mobs_in_contents) + update_parallax_contents() moving_diagonally = 0 return if(!loc || (loc == oldloc && oldloc != newloc)) last_move = 0 + return + if(. && pulling && pulling == pullee && pulling != moving_from_pull) //we were pulling a thing and didn't lose it during our move. + if(pulling.anchored) + stop_pulling() + else + //puller and pullee more than one tile away or in diagonal position and whatever the pullee is pulling isn't already moving from a pull as it'll most likely result in an infinite loop a la ouroborus. + if(!pulling.pulling?.moving_from_pull) + var/pull_dir = get_dir(pulling, src) + var/target_turf = current_turf + + if(target_turf != current_turf || (moving_diagonally != SECOND_DIAG_STEP && IS_DIR_DIAGONAL(pull_dir)) || get_dist(src, pulling) > 1) + pulling.move_from_pull(src, target_turf, glide_size) + + // PARA: There was code here for handling multi-z, which isn't relevant to us. + check_pulling() + + //glide_size strangely enough can change mid movement animation and update correctly while the animation is playing + //This means that if you don't override it late like this, it will just be set back by the movement update that's called when you move turfs. + if(glide_size_override) + set_glide_size(glide_size_override) + last_move = direct - move_speed = world.time - l_move_time - l_move_time = world.time - if(. && has_buckled_mobs() && !handle_buckled_mob_movement(loc, direct, movetime)) //movement failed due to buckled mob + if(. && has_buckled_mobs() && !handle_buckled_mob_movement(loc, direct, glide_size_override)) //movement failed due to buckled mob . = FALSE -// Called after a successful Move(). By this point, we've already moved -/atom/movable/proc/Moved(atom/old_loc, Dir, Forced = FALSE) - SEND_SIGNAL(src, COMSIG_MOVABLE_MOVED, old_loc, Dir, Forced) - if(!inertia_moving) - inertia_next_move = world.time + inertia_move_delay - newtonian_move(Dir) +/** + * Called after a successful Move(). By this point, we've already moved. + * Arguments: + * * old_loc is the location prior to the move. Can be null to indicate nullspace. + * * movement_dir is the direction the movement took place. Can be NONE if it was some sort of teleport. + * * The forced flag indicates whether this was a forced move, which skips many checks of regular movement. + * * The old_locs is an optional argument, in case the moved movable was present in multiple locations before the movement. + * * momentum_change represents whether this movement is due to a "new" force if TRUE or an already "existing" force if FALSE + **/ +/atom/movable/proc/Moved(atom/old_loc, movement_dir, forced, list/old_locs, momentum_change = TRUE) + SEND_SIGNAL(src, COMSIG_MOVABLE_MOVED, old_loc, movement_dir, forced, old_locs, momentum_change) + + if(!inertia_moving && momentum_change) + newtonian_move(movement_dir) if(length(client_mobs_in_contents)) update_parallax_contents() @@ -369,6 +417,12 @@ L.source_atom.update_light() return TRUE +/// Called when src is being moved to a target turf because another movable (puller) is moving around. +/atom/movable/proc/move_from_pull(atom/movable/puller, turf/target_turf, glide_size_override) + moving_from_pull = puller + Move(target_turf, get_dir(src, target_turf), glide_size_override) + moving_from_pull = null + // Make sure you know what you're doing if you call this // You probably want CanPass() /atom/movable/Cross(atom/movable/crossed_atom) @@ -401,7 +455,7 @@ */ /atom/movable/Uncross() SHOULD_NOT_OVERRIDE(TRUE) - CRASH("Uncross() should not be being called, please read the doc-comment for it for why.") + CRASH("Unexpected atom/movable/Uncross() call") /** * default byond proc that is normally called on everything inside the previous turf @@ -554,19 +608,26 @@ update_runechat_msg_location() -//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() below -//return FALSE to have src start/keep drifting in a no-grav area and TRUE to stop/not start drifting -//Mobs should return TRUE if they should be able to move of their own volition, see client/Move() in mob_movement.dm -//movement_dir == 0 when stopping or any dir when trying to move -/atom/movable/proc/Process_Spacemove(movement_dir = 0) +/** + * 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 TRUE 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(src)) return TRUE - if(pulledby && !pulledby.pulling) + if(SEND_SIGNAL(src, COMSIG_MOVABLE_SPACEMOVE, movement_dir, continuous_move) & COMSIG_MOVABLE_STOP_SPACEMOVE) return TRUE - if(SEND_SIGNAL(src, COMSIG_MOVABLE_SPACEMOVE, movement_dir) & COMSIG_MOVABLE_STOP_SPACEMOVE) + if(pulledby && pulledby.pulledby != src) return TRUE if(throwing) @@ -577,17 +638,15 @@ return FALSE -/atom/movable/proc/newtonian_move(direction) //Only moves the object if it's under no gravity - if(!loc || Process_Spacemove(0)) - inertia_dir = 0 +/atom/movable/proc/newtonian_move(direction, instant = FALSE, start_delay = 0) + if(!isturf(loc) || Process_Spacemove(direction, continuous_move = TRUE)) return FALSE - inertia_dir = direction - if(!direction) + if(SEND_SIGNAL(src, COMSIG_MOVABLE_NEWTONIAN_MOVE, direction, start_delay) & COMPONENT_MOVABLE_NEWTONIAN_BLOCK) return TRUE - inertia_last_loc = loc - SSspacedrift.processing[src] = src + AddComponent(/datum/component/drift, direction, instant, start_delay) + return TRUE //called when src is thrown into hit_atom @@ -684,6 +743,7 @@ /// This proc is recursive, and calls itself to constantly set the glide size of an atom/movable /atom/movable/proc/set_glide_size(target = 8) + SEND_SIGNAL(src, COMSIG_MOVABLE_UPDATE_GLIDE_SIZE, target) glide_size = target for(var/mob/buckled_mob as anything in buckled_mobs) @@ -708,14 +768,12 @@ if(master) return master.attack_hand(a, b, c) -/atom/movable/proc/handle_buckled_mob_movement(newloc,direct,movetime) +/atom/movable/proc/handle_buckled_mob_movement(newloc, direct, glide_size_override) for(var/m in buckled_mobs) var/mob/living/buckled_mob = m - if(!buckled_mob.Move(newloc, direct, movetime)) + if(!buckled_mob.Move(newloc, direct, glide_size_override)) forceMove(buckled_mob.loc) last_move = buckled_mob.last_move - inertia_dir = last_move - buckled_mob.inertia_dir = last_move return FALSE return TRUE diff --git a/code/game/gamemodes/cult/cult_items.dm b/code/game/gamemodes/cult/cult_items.dm index 9e36aeaf9f54..2c51ad4dd049 100644 --- a/code/game/gamemodes/cult/cult_items.dm +++ b/code/game/gamemodes/cult/cult_items.dm @@ -727,7 +727,7 @@ name = "reality sunderer" icon = 'icons/obj/cult.dmi' icon_state = "amulet" - desc = "Some amulet made out of metal, bluespace crystals, and blood. Allows cultists to open portals over teleport runes, destroying the rune in the process." + desc = "An elaborately carved amulet resembling a human eye. Looking directly at it sends shivers down your spine. Allows cultists to open portals over teleport runes, destroying the rune in the process." w_class = WEIGHT_CLASS_SMALL diff --git a/code/game/gamemodes/dynamic/antag_rulesets.dm b/code/game/gamemodes/dynamic/antag_rulesets.dm index 3e56784bdbb2..500f9aa419f1 100644 --- a/code/game/gamemodes/dynamic/antag_rulesets.dm +++ b/code/game/gamemodes/dynamic/antag_rulesets.dm @@ -49,6 +49,8 @@ var/antag_amount = 0 /// All of the minds that we will make into our antagonist type var/list/datum/mind/pre_antags = list() + /// If non-zero, how long from the start of the game should a latespawn for this role occur? + var/latespawn_time /datum/ruleset/Destroy(force, ...) stack_trace("[src] ([type]) was destroyed.") @@ -63,7 +65,7 @@ /datum/ruleset/proc/antagonist_possible(budget) return budget >= antag_cost -/datum/ruleset/proc/pre_setup() +/datum/ruleset/proc/roundstart_pre_setup() if(antag_amount == 0) return if(antag_amount < 0) @@ -81,7 +83,7 @@ for(var/datum/mind/antag as anything in possible_antags) if(antag_amount <= 0) break - if(!can_apply(antag)) + if(!roundstart_can_apply(antag)) continue pre_antags += antag if(assign_job_role) @@ -94,7 +96,7 @@ refund("Missing [antag_amount] antagonists for [src] ruleset.") return antag_cost * antag_amount // shitty refund for now -/datum/ruleset/proc/can_apply(datum/mind/antag) +/datum/ruleset/proc/roundstart_can_apply(datum/mind/antag) if(EXCLUSIVE_OR(antag.current.client.prefs.active_character.species in banned_species, banned_species_only)) SEND_SIGNAL(src, COMSIG_RULESET_FAILED_SPECIES) return FALSE @@ -102,7 +104,7 @@ return FALSE return TRUE -/datum/ruleset/proc/post_setup(datum/game_mode/dynamic) +/datum/ruleset/proc/roundstart_post_setup(datum/game_mode/dynamic) for(var/datum/mind/antag as anything in pre_antags) antag.add_antag_datum(antagonist_type) @@ -113,6 +115,47 @@ // Currently unimplemented. Will be useful for a possible future PR where latejoin antagonists are factored in. return +/datum/ruleset/proc/get_latejoin_players() + var/list/candidates = list() + + // Assemble a list of active players without jobbans. + for(var/mob/living/carbon/human/player in GLOB.player_list) + // Has a mind + if(!player.mind) + continue + // Connected and not AFK + if(!player.client || (locate(player) in SSafk.afk_players)) + continue + // Not antag-banned and not specific antag banned + if(jobban_isbanned(player, ROLE_SYNDICATE) || jobban_isbanned(player, antagonist_type::job_rank)) + continue + // Make sure they want to play antag, and that they're not already something (off station or antag) + if(player.client.skip_antag || player.mind.offstation_role || player.mind.special_role) + continue + // Make sure they actually want to be this antagonist + if(!(antagonist_type::job_rank in player.client.prefs.be_special)) + continue + // Make sure their species CAN be this antagonist + if(EXCLUSIVE_OR(player.dna.species.name in banned_species, banned_species_only)) + continue + // Make sure they're not in a banned job + if(player.mind.assigned_role in banned_jobs) + continue + + candidates += player.mind + + return shuffle(candidates) + +/datum/ruleset/proc/latespawn(datum/game_mode/dynamic/dynamic) + // latespawning is only used by traitors at this point, so we're just going to be naive and allocate all budget when this proc is called. + var/late_antag_amount = floor(dynamic.budget_overflow / antag_cost) + dynamic.budget_overflow -= (late_antag_amount * antag_cost) + + var/list/datum/mind/possible_antags = get_latejoin_players() + for(var/i in 1 to late_antag_amount) + var/datum/mind/antag = pick_n_take(possible_antags) + antag.add_antag_datum(antagonist_type) + /datum/ruleset/traitor name = "Traitor" ruleset_weight = 11 @@ -120,15 +163,14 @@ antag_weight = 2 antagonist_type = /datum/antagonist/traitor -/datum/ruleset/traitor/post_setup(datum/game_mode/dynamic) - var/random_time = rand(5 MINUTES, 15 MINUTES) +/datum/ruleset/traitor/roundstart_post_setup(datum/game_mode/dynamic) + latespawn_time = rand(5 MINUTES, 15 MINUTES) for(var/datum/mind/antag as anything in pre_antags) var/datum/antagonist/traitor/traitor_datum = new antagonist_type() if(ishuman(antag.current)) traitor_datum.delayed_objectives = TRUE - traitor_datum.addtimer(CALLBACK(traitor_datum, TYPE_PROC_REF(/datum/antagonist/traitor, reveal_delayed_objectives)), random_time, TIMER_DELETE_ME) + traitor_datum.addtimer(CALLBACK(traitor_datum, TYPE_PROC_REF(/datum/antagonist/traitor, reveal_delayed_objectives)), latespawn_time, TIMER_DELETE_ME) antag.add_antag_datum(traitor_datum) - addtimer(CALLBACK(dynamic, TYPE_PROC_REF(/datum/game_mode, fill_antag_slots)), random_time) /datum/ruleset/vampire name = "Vampire" diff --git a/code/game/gamemodes/dynamic/dynamic.dm b/code/game/gamemodes/dynamic/dynamic.dm index 1e0e1ec4ad2e..dfff3aa7aae3 100644 --- a/code/game/gamemodes/dynamic/dynamic.dm +++ b/code/game/gamemodes/dynamic/dynamic.dm @@ -3,7 +3,6 @@ GLOBAL_LIST_EMPTY(dynamic_forced_rulesets) /datum/game_mode/dynamic name = "Dynamic" config_tag = "dynamic" - secondary_restricted_jobs = list("AI") required_players = 10 /// Non-implied rulesets in play var/list/datum/ruleset/rulesets = list() @@ -126,7 +125,7 @@ GLOBAL_LIST_EMPTY(dynamic_forced_rulesets) for(var/datum/ruleset/ruleset in (rulesets + implied_rulesets)) // rulesets first, then implied rulesets // log_dynamic("Applying [ruleset.antag_amount] [ruleset.name]\s.") - budget_overflow += ruleset.pre_setup() + budget_overflow += ruleset.roundstart_pre_setup() // log_dynamic("Budget overflow: [budget_overflow].") // for the future, maybe try readding antagonists with apply_antag_budget(budget_overflow) @@ -137,13 +136,11 @@ GLOBAL_LIST_EMPTY(dynamic_forced_rulesets) for(var/datum/ruleset/ruleset in (rulesets + implied_rulesets)) // if(length(ruleset.pre_antags)) // log_dynamic("Making antag datums for [ruleset.name] ruleset.") - ruleset.post_setup(src) + ruleset.roundstart_post_setup(src) + if(ruleset.latespawn_time) + addtimer(CALLBACK(ruleset, TYPE_PROC_REF(/datum/ruleset, latespawn), src), ruleset.latespawn_time) ..() -/datum/game_mode/dynamic/traitors_to_add() - . = floor(budget_overflow / /datum/ruleset/traitor::antag_cost) - budget_overflow -= (. * /datum/ruleset/traitor::antag_cost) - /datum/game_mode/dynamic/latespawn(mob) . = ..() budget_overflow++ diff --git a/code/game/gamemodes/game_mode.dm b/code/game/gamemodes/game_mode.dm index 50960ce80b97..143a8c90ff66 100644 --- a/code/game/gamemodes/game_mode.dm +++ b/code/game/gamemodes/game_mode.dm @@ -319,7 +319,10 @@ // Less if there are not enough valid players in the game entirely to make recommended_enemies. // Just the above proc but for alive players -/// Gets all alive players for a specific role. Disables offstation roles by default +/** + * DEPRECATED! + * Gets all alive players for a specific role. Disables offstation roles by default + */ /datum/game_mode/proc/get_alive_players_for_role(role, override_jobbans = FALSE, allow_offstation_roles = FALSE) var/list/players = list() var/list/candidates = list() @@ -645,6 +648,9 @@ /datum/game_mode/proc/traitors_to_add() return 0 +/** + * DEPRECATED! + */ /datum/game_mode/proc/fill_antag_slots() var/traitors_to_add = 0 diff --git a/code/game/gamemodes/miniantags/guardian/guardian.dm b/code/game/gamemodes/miniantags/guardian/guardian.dm index 83e47bff1c16..e566a3eac3a8 100644 --- a/code/game/gamemodes/miniantags/guardian/guardian.dm +++ b/code/game/gamemodes/miniantags/guardian/guardian.dm @@ -185,7 +185,7 @@ ghostize() qdel(src) -/mob/living/simple_animal/hostile/guardian/Process_Spacemove(movement_dir = 0) +/mob/living/simple_animal/hostile/guardian/Process_Spacemove(movement_dir = 0, continuous_move = FALSE) return TRUE //Works better in zero G, and not useless in space //Manifest, Recall, Communicate diff --git a/code/game/gamemodes/vampire/traitor_vamp.dm b/code/game/gamemodes/vampire/traitor_vamp.dm index 68224edcc120..c45cb7dcd1f9 100644 --- a/code/game/gamemodes/vampire/traitor_vamp.dm +++ b/code/game/gamemodes/vampire/traitor_vamp.dm @@ -13,7 +13,7 @@ /datum/game_mode/traitor/vampire/announce() to_chat(world, "The current game mode is - Traitor+Vampire!") - to_chat(world, "There are Bluespace Vampires infesting your fellow crew on the station along with some syndicate operatives out for their own gain! Do not let the vampires and the traitors succeed!") + to_chat(world, "There are Vampires on the station along with syndicate operatives out for their own gain! Do not let the vampires and the traitors succeed!") /datum/game_mode/traitor/vampire/pre_setup() diff --git a/code/game/gamemodes/vampire/vampire_gamemode.dm b/code/game/gamemodes/vampire/vampire_gamemode.dm index 05b15dae3a0c..4ad4a77db415 100644 --- a/code/game/gamemodes/vampire/vampire_gamemode.dm +++ b/code/game/gamemodes/vampire/vampire_gamemode.dm @@ -12,7 +12,7 @@ /datum/game_mode/vampire/announce() to_chat(world, "The current game mode is - Vampires!") - to_chat(world, "There are Bluespace Vampires infesting your fellow crewmates, keep your blood close and neck safe!") + to_chat(world, "There are Vampires aboard, keep your blood close and neck safe!") /datum/game_mode/vampire/pre_setup() diff --git a/code/game/gamemodes/wizard/soulstone.dm b/code/game/gamemodes/wizard/soulstone.dm index 2cf42faeaee8..73675382d745 100644 --- a/code/game/gamemodes/wizard/soulstone.dm +++ b/code/game/gamemodes/wizard/soulstone.dm @@ -1,12 +1,12 @@ // This whole file really needs reorganising at some point, or at the very least the construct stuff should be moved somewhere else. /obj/item/soulstone - name = "soul stone shard" + name = "soul stone" icon = 'icons/obj/wizard.dmi' icon_state = "soulstone" item_state = "electronic" belt_icon = "soulstone" var/icon_state_full = "soulstone2" - desc = "A fragment of the legendary treasure known simply as the 'Soul Stone'. The shard still flickers with a fraction of the full artifact's power." + desc = "A weighty shard of dark crystal, flickering with eldritch energy. A soul can be bound within, forced to obey the commands of the owner." w_class = WEIGHT_CLASS_TINY slot_flags = ITEM_SLOT_BELT origin_tech = "bluespace=4;materials=5" diff --git a/code/game/machinery/dance_machine.dm b/code/game/machinery/dance_machine.dm index c2389895e0cb..d545b1c6e13a 100644 --- a/code/game/machinery/dance_machine.dm +++ b/code/game/machinery/dance_machine.dm @@ -510,7 +510,7 @@ /obj/machinery/disco/immobile name = "radiant dance machine mark V" - desc = "The mark V is nigh-immovable, thanks to its bluespace-plastitanium anchor. The technology required to stop visitors from stealing this thing is astounding." + desc = "A massive disco ball permanently anchored to the floor with heat-sealed bolts. Merely being in the presence of such a majestic contraption fills you with the urge to dance." anchored = TRUE /obj/machinery/disco/immobile/wrench_act() diff --git a/code/game/machinery/doors/airlock.dm b/code/game/machinery/doors/airlock.dm index e2d0c901c88c..4455b7d26927 100644 --- a/code/game/machinery/doors/airlock.dm +++ b/code/game/machinery/doors/airlock.dm @@ -103,7 +103,6 @@ GLOBAL_LIST_EMPTY(airlock_emissive_underlays) var/doorDeni = 'sound/machines/deniedbeep.ogg' // i'm thinkin' Deni's var/boltUp = 'sound/machines/boltsup.ogg' var/boltDown = 'sound/machines/boltsdown.ogg' - var/is_special = FALSE /// Our ID tag for map-based linking shenanigans var/id_tag /// List of people who have shocked this door for logging purposes diff --git a/code/game/machinery/hologram.dm b/code/game/machinery/hologram.dm index 118340d2df83..cecc1cf7a4fe 100644 --- a/code/game/machinery/hologram.dm +++ b/code/game/machinery/hologram.dm @@ -555,7 +555,7 @@ For the other part of the code, check silicon say.dm. Particularly robot talk.*/ HC.Disconnect(HC.calling_holopad) return ..() -/obj/effect/overlay/holo_pad_hologram/Process_Spacemove(movement_dir = 0) +/obj/effect/overlay/holo_pad_hologram/Process_Spacemove(movement_dir = 0, continuous_move = FALSE) return 1 /obj/effect/overlay/holo_pad_hologram/examine(mob/user) diff --git a/code/game/machinery/tcomms/tcomms_base.dm b/code/game/machinery/tcomms/tcomms_base.dm index 6c7520a80b80..2ec9d81d8170 100644 --- a/code/game/machinery/tcomms/tcomms_base.dm +++ b/code/game/machinery/tcomms/tcomms_base.dm @@ -133,7 +133,7 @@ GLOBAL_LIST_EMPTY(tcomms_machines) if(active) active = FALSE // This needs a timer because otherwise its on the shuttle Z and the message is missed - addtimer(CALLBACK(src, TYPE_PROC_REF(/atom, visible_message), "Radio equipment on [src] has been overloaded by heavy bluespace interference. Please restart the machine."), 5) + addtimer(CALLBACK(src, TYPE_PROC_REF(/atom, visible_message), "Radio equipment on [src] has suffered an unidentified malfunction. Please restart the machine."), 5) update_icon(UPDATE_ICON_STATE) diff --git a/code/game/mecha/equipment/tools/janitor_tools.dm b/code/game/mecha/equipment/tools/janitor_tools.dm index 62f424914ca3..ba3b3143d648 100644 --- a/code/game/mecha/equipment/tools/janitor_tools.dm +++ b/code/game/mecha/equipment/tools/janitor_tools.dm @@ -220,8 +220,8 @@ // Garbage Magnet /obj/item/mecha_parts/mecha_equipment/janitor/garbage_magnet name = "\improper WA1E Garbage Magnet" - desc = "Bluespace technology integrated with an oversized garbage bag and heavy duty magnets allows this device to pick up all manner of litter. \ - The complex technology prevents users from directly looking inside the bag." + desc = "An industrial vaccuum cleaner integrated with an oversized garbage bag and heavy duty magnets allows this device to pick up all manner of litter. \ + The device's safety systems prevent users from directly looking inside the bag." icon_state = "mecha_trash_magnet" equip_cooldown = 1.5 SECONDS energy_drain = 5 diff --git a/code/game/mecha/equipment/weapons/weapons.dm b/code/game/mecha/equipment/weapons/weapons.dm index 6d55f9a41ef3..9b3ff37da45c 100644 --- a/code/game/mecha/equipment/weapons/weapons.dm +++ b/code/game/mecha/equipment/weapons/weapons.dm @@ -233,10 +233,10 @@ if(isobj(H.shoes) && !(H.shoes.flags & NODROP)) var/thingy = H.shoes H.drop_item_to_ground(thingy) - walk_away(thingy,chassis,15,2) + GLOB.move_manager.move_away(thingy, chassis, 15, 2) spawn(20) if(thingy) - walk(thingy,0) + GLOB.move_manager.stop_looping(thingy) for(var/obj/mecha/combat/reticence/R in oview(6, chassis)) R.occupant_message("\The [R] has protected you from [chassis]'s HONK at the cost of some power.") R.use_power(R.get_charge() / 4) diff --git a/code/game/mecha/mecha.dm b/code/game/mecha/mecha.dm index df4cad6e0014..4ffdcdd9df4a 100644 --- a/code/game/mecha/mecha.dm +++ b/code/game/mecha/mecha.dm @@ -286,7 +286,7 @@ //////// MARK: Movement procs ////////////////////////////////// -/obj/mecha/Process_Spacemove(movement_dir = 0) +/obj/mecha/Process_Spacemove(movement_dir = 0, continuous_move = FALSE) . = ..() if(.) return TRUE diff --git a/code/game/objects/effects/decals/Cleanable/alien_blood.dm b/code/game/objects/effects/decals/Cleanable/alien_blood.dm index 2e02edee4a22..1f062d451125 100644 --- a/code/game/objects/effects/decals/Cleanable/alien_blood.dm +++ b/code/game/objects/effects/decals/Cleanable/alien_blood.dm @@ -2,7 +2,7 @@ name = "xeno blood" desc = "It's green and acidic. It looks like... blood?" icon = 'icons/effects/blood.dmi' - basecolor = "#05EE05" + basecolor = COLOR_BLOOD_XENO bloodiness = BLOOD_AMOUNT_PER_DECAL blood_state = BLOOD_STATE_XENO @@ -15,11 +15,7 @@ desc = "Gnarly..." icon_state = "xgib1" random_icon_states = list("xgib1", "xgib2", "xgib3", "xgib4", "xgib5", "xgib6") - basecolor = "#05EE05" - -/obj/effect/decal/cleanable/blood/gibs/xeno/update_icon() - color = "#FFFFFF" - . = ..(NONE) + basecolor = COLOR_BLOOD_XENO /obj/effect/decal/cleanable/blood/gibs/xeno/up random_icon_states = list("xgib1", "xgib2", "xgib3", "xgib4", "xgib5", "xgib6", "xgibup1", "xgibup1", "xgibup1") @@ -37,7 +33,7 @@ random_icon_states = list("xgibmid1", "xgibmid2", "xgibmid3") /obj/effect/decal/cleanable/blood/xtracks - basecolor = "#05EE05" + basecolor = COLOR_BLOOD_XENO /// this is the alien blood file, slimes are aliens. /obj/effect/decal/cleanable/blood/slime diff --git a/code/game/objects/effects/decals/Cleanable/humans.dm b/code/game/objects/effects/decals/Cleanable/humans.dm index f9d8e1f4acba..b071cea77247 100644 --- a/code/game/objects/effects/decals/Cleanable/humans.dm +++ b/code/game/objects/effects/decals/Cleanable/humans.dm @@ -14,6 +14,7 @@ random_icon_states = list("mfloor1", "mfloor2", "mfloor3", "mfloor4", "mfloor5", "mfloor6", "mfloor7") blood_DNA = list() var/base_icon = 'icons/effects/blood.dmi' + base_icon_state = "mfloor1" var/blood_state = BLOOD_STATE_HUMAN bloodiness = BLOOD_AMOUNT_PER_DECAL var/basecolor = "#A10808" // Color when wet. @@ -21,7 +22,8 @@ var/dry_timer = 0 var/off_floor = FALSE var/image/weightless_image - inertia_move_delay = 1 // so they dont collide with who emitted them + var/weightless_icon = 'icons/effects/blood_weightless.dmi' + inertia_move_delay = 5 // so they dont collide with who emitted them /obj/effect/decal/cleanable/blood/replace_decal(obj/effect/decal/cleanable/blood/C) if(C == src) @@ -33,18 +35,32 @@ C.bloodiness += bloodiness return ..() -/obj/effect/decal/cleanable/blood/Initialize(mapload) +/obj/effect/decal/cleanable/blood/Initialize(mapload, decal_color) . = ..() - weightless_image = new() + if(decal_color) + basecolor = decal_color + else + if(basecolor == "rainbow") + basecolor = "#[pick("FF0000","FF7F00","FFFF00","00FF00","0000FF","4B0082","8F00FF")]" + + color = basecolor + base_icon_state = icon_state + + var/turf/T = get_turf(src) + check_gravity(T) update_icon() - if(!gravity_check) + if(gravity_check) + if(!. && !QDELETED(src)) + dry_timer = addtimer(CALLBACK(src, PROC_REF(dry)), DRYING_TIME * (amount+1), TIMER_STOPPABLE) + else + if(prob(50)) + animate_float(src, -1, rand(30,120)) + else + animate_levitate(src, -1, rand(30,120)) //weightless blood cannot dry return - if(!. && !QDELETED(src)) - dry_timer = addtimer(CALLBACK(src, PROC_REF(dry)), DRYING_TIME * (amount+1), TIMER_STOPPABLE) - var/static/list/loc_connections = list( COMSIG_ATOM_ENTERED = PROC_REF(on_atom_entered), ) @@ -56,38 +72,32 @@ QDEL_NULL(weightless_image) return ..() -/obj/effect/decal/cleanable/blood/update_icon() - var/turf/T = get_turf(src) - check_gravity(T) +/obj/effect/decal/cleanable/blood/update_overlays() + . = ..() + + if(gravity_check) + return + + if(!weightless_image) + color = COLOR_WHITE + weightless_image = image(weightless_icon, base_icon_state) + weightless_image.icon += basecolor + . += weightless_image + +/obj/effect/decal/cleanable/blood/update_icon() if(should_be_off_floor()) off_floor = TRUE layer = ABOVE_MOB_LAYER plane = GAME_PLANE - if(basecolor == "rainbow") - basecolor = "#[pick("FF0000","FF7F00","FFFF00","00FF00","0000FF","4B0082","8F00FF")]" - - color = basecolor - - if(!gravity_check) - if(prob(50)) - animate_float(src, -1, rand(30,120)) - else - animate_levitate(src, -1, rand(30,120)) - - if(weightless_image && weightless_image.icon_state) - icon_state = weightless_image.icon_state - - overlays -= weightless_image - color = "#FFFFFF" - icon = 'icons/effects/blood_weightless.dmi' - weightless_image = image(icon, icon_state) - icon_state = "empty" - weightless_image.icon += basecolor - overlays += weightless_image + if(gravity_check) + icon = initial(icon) + icon_state = base_icon_state + color = basecolor else - overlays.Cut() + icon_state = null + ..() /obj/effect/decal/cleanable/blood/proc/should_be_off_floor() @@ -116,32 +126,17 @@ return if(loc != T) forceMove(T) //move to the turf to splatter on - animate(src) //stop floating gravity_check = ALWAYS_IN_GRAVITY - icon = initial(icon) - icon_state = weightless_image.icon_state layer = initial(layer) plane = initial(plane) + animate(src) update_icon() - -/obj/effect/decal/cleanable/blood/Process_Spacemove(movement_dir) +/obj/effect/decal/cleanable/blood/Process_Spacemove(movement_dir = 0, continuous_move = FALSE) if(gravity_check) return TRUE - if(has_gravity(src)) - if(!gravity_check) - splat(get_step(src, movement_dir)) - return TRUE - - if(pulledby && !pulledby.pulling) - return TRUE - - if(throwing) - return TRUE - - return FALSE - + return ..() /obj/effect/decal/cleanable/blood/Bump(atom/A) if(gravity_check) @@ -162,8 +157,11 @@ return ..() /obj/effect/decal/cleanable/blood/proc/bloodyify_human(mob/living/carbon/human/H) - if(inertia_dir && H.inertia_dir == inertia_dir) //if they are moving the same direction we are, no collison - return + // Originally this code would check to see if both us and the human + // we collided with had inertia in the same direction, and avoided collision + // if so. This might be possible with movement loops but, realistically, + // if we've gotten here, the objects have collided no matter what direction + // they were going in. var/list/obj/item/things_to_potentially_bloody = list() var/count = amount + 1 @@ -317,17 +315,21 @@ mergeable_decal = TRUE /obj/effect/decal/cleanable/blood/gibs/proc/streak(list/directions) - set waitfor = 0 + var/delay = 2 + var/range = pick(1, 200; 2, 150; 3, 50; 4) var/direction = pick(directions) - for(var/i = 0, i < pick(1, 200; 2, 150; 3, 50; 4), i++) - sleep(3) - if(i > 0) - var/obj/effect/decal/cleanable/blood/b = new /obj/effect/decal/cleanable/blood/splatter(loc) - b.basecolor = src.basecolor - b.update_icon() - if(step_to(src, get_step(src, direction), 0)) - break + var/datum/move_loop/loop = GLOB.move_manager.move_to(src, get_step(src, direction), delay = delay, timeout = range * delay, priority = MOVEMENT_ABOVE_SPACE_PRIORITY) + RegisterSignal(loop, COMSIG_MOVELOOP_POSTPROCESS, PROC_REF(spread_movement_effects)) + +/obj/effect/decal/cleanable/blood/gibs/proc/spread_movement_effects(datum/move_loop/has_target/source) + SIGNAL_HANDLER // COMSIG_MOVELOOP_POSTPROCESS + var/obj/effect/decal/cleanable/blood/target = source.target + var/obj/effect/decal/cleanable/blood/splatter/splatter = new(loc, istype(target) ? target.basecolor : basecolor) + + if(istype(target)) + splatter.basecolor = target.basecolor + splatter.update_icon() /obj/effect/decal/cleanable/blood/old/Initialize(mapload) . = ..() diff --git a/code/game/objects/effects/decals/Cleanable/misc_cleanables.dm b/code/game/objects/effects/decals/Cleanable/misc_cleanables.dm index 8048ab7e23d1..f0ddd75c6be5 100644 --- a/code/game/objects/effects/decals/Cleanable/misc_cleanables.dm +++ b/code/game/objects/effects/decals/Cleanable/misc_cleanables.dm @@ -159,9 +159,8 @@ /obj/effect/decal/cleanable/vomit/Initialize(mapload) . = ..() var/turf/T = get_turf(src) - gravity_check = has_gravity(src, T) - if(loc != T) - forceMove(T) + check_gravity(T) + if(!gravity_check) layer = MOB_LAYER plane = GAME_PLANE @@ -177,9 +176,17 @@ AddElement(/datum/element/connect_loc, loc_connections) /obj/effect/decal/cleanable/vomit/Bump(atom/A) - . = ..() - if(A.density) + if(gravity_check) + return ..() + + if(iswallturf(A) || istype(A, /obj/structure/window)) splat(A) + return + else if(A.density) + splat(get_turf(A)) + return + + return ..() /obj/effect/decal/cleanable/vomit/proc/on_atom_entered(datum/source, atom/movable/entered) if(!gravity_check) @@ -204,22 +211,11 @@ plane = initial(plane) animate(src) -/obj/effect/decal/cleanable/vomit/Process_Spacemove(movement_dir) +/obj/effect/decal/cleanable/vomit/Process_Spacemove(movement_dir = 0, continuous_move = FALSE) if(gravity_check) - return 1 - - if(has_gravity(src)) - if(!gravity_check) - splat(get_step(src, movement_dir)) - return 1 + return TRUE - if(pulledby && !pulledby.pulling) - return 1 - - if(throwing) - return 1 - - return 0 + return ..() /obj/effect/decal/cleanable/vomit/green name = "green vomit" diff --git a/code/game/objects/effects/decals/misc_decals.dm b/code/game/objects/effects/decals/misc_decals.dm index f8b34c230237..d287bbd31433 100644 --- a/code/game/objects/effects/decals/misc_decals.dm +++ b/code/game/objects/effects/decals/misc_decals.dm @@ -12,6 +12,19 @@ /obj/effect/decal/chempuff/blob_act(obj/structure/blob/B) return +/obj/effect/decal/chempuff/proc/loop_ended(datum/source) + SIGNAL_HANDLER // COMSIG_PARENT_QDELETING + if(QDELETED(src)) + return + qdel(src) + +/obj/effect/decal/chempuff/proc/check_move(datum/move_loop/source, succeeded) + SIGNAL_HANDLER // COMSIG_MOVELOOP_POSTPROCESS + var/turf/our_turf = get_turf(src) + reagents.reaction(our_turf) + for(var/atom/T in our_turf) + reagents.reaction(T) + /obj/effect/decal/snow name = "snow" density = FALSE diff --git a/code/game/objects/effects/effect_system/effects_other.dm b/code/game/objects/effects/effect_system/effects_other.dm index ab4a464d0016..fa5464921bf0 100644 --- a/code/game/objects/effects/effect_system/effects_other.dm +++ b/code/game/objects/effects/effect_system/effects_other.dm @@ -1,3 +1,59 @@ +/datum/effect_system/trail_follow + var/turf/oldposition + var/active = FALSE + var/allow_overlap = FALSE + var/auto_process = TRUE + var/qdel_in_time = 10 + var/fadetype = "ion_fade" + var/fade = TRUE + var/nograv_required = FALSE + +/datum/effect_system/trail_follow/set_up(atom/atom) + attach(atom) + oldposition = get_turf(atom) + +/datum/effect_system/trail_follow/Destroy() + oldposition = null + stop() + return ..() + +/datum/effect_system/trail_follow/proc/stop() + oldposition = null + STOP_PROCESSING(SSfastprocess, src) + active = FALSE + return TRUE + +/datum/effect_system/trail_follow/start() + oldposition = get_turf(holder) + if(!check_conditions()) + return FALSE + if(auto_process) + START_PROCESSING(SSfastprocess, src) + active = TRUE + return TRUE + +/datum/effect_system/trail_follow/process() + generate_effect() + +/datum/effect_system/trail_follow/generate_effect() + if(!check_conditions()) + return stop() + if(oldposition && !(oldposition == get_turf(holder))) + if(!has_gravity(oldposition) || !nograv_required) + var/obj/effect/E = new effect_type(oldposition) + set_dir(E) + if(fade) + flick(fadetype, E) + E.icon_state = "" + if(qdel_in_time) + QDEL_IN(E, qdel_in_time) + oldposition = get_turf(holder) + +/datum/effect_system/trail_follow/proc/check_conditions() + if(!get_turf(holder)) + return FALSE + return TRUE + /// Ion trails for jetpacks, ion thrusters and other space-flying things /obj/effect/particle_effect/ion_trails name = "ion trails" @@ -8,6 +64,17 @@ dir = targetdir QDEL_IN(src, 0.6 SECONDS) +/datum/effect_system/trail_follow/ion + effect_type = /obj/effect/particle_effect/ion_trails + nograv_required = TRUE + qdel_in_time = 20 + +/datum/effect_system/trail_follow/proc/set_dir(obj/effect/particle_effect/ion_trails/I) + I.setDir(holder.dir) + +/datum/effect_system/trail_follow/ion/grav_allowed + nograv_required = FALSE + //Reagent-based explosion effect /datum/effect_system/reagents_explosion var/amount // TNT equivalent diff --git a/code/game/objects/effects/meteors.dm b/code/game/objects/effects/meteors.dm index 0b062f8b8e1d..de1020d61ce1 100644 --- a/code/game/objects/effects/meteors.dm +++ b/code/game/objects/effects/meteors.dm @@ -29,8 +29,8 @@ GLOBAL_LIST_INIT(meteors_gore, list(/obj/effect/meteor/meaty = 5, /obj/effect/me while(!isspaceturf(pickedstart)) var/startSide = pick(GLOB.cardinal) var/startZ = level_name_to_num(MAIN_STATION) - pickedstart = spaceDebrisStartLoc(startSide, startZ) - pickedgoal = spaceDebrisFinishLoc(startSide, startZ) + pickedstart = pick_edge_loc(startSide, startZ) + pickedgoal = pick_edge_loc(REVERSE_DIR(startSide), startZ) max_i-- if(max_i <= 0) return @@ -38,41 +38,23 @@ GLOBAL_LIST_INIT(meteors_gore, list(/obj/effect/meteor/meaty = 5, /obj/effect/me var/obj/effect/meteor/M = new Me(pickedstart, pickedgoal) M.dest = pickedgoal -/proc/spaceDebrisStartLoc(startSide, Z) +/proc/pick_edge_loc(startSide, Z) var/starty var/startx switch(startSide) if(NORTH) - starty = world.maxy-(TRANSITIONEDGE + MAP_EDGE_PAD) - startx = rand((TRANSITIONEDGE + MAP_EDGE_PAD), world.maxx-(TRANSITIONEDGE + MAP_EDGE_PAD)) + starty = world.maxy + startx = rand(1, world.maxx) if(EAST) - starty = rand((TRANSITIONEDGE + MAP_EDGE_PAD),world.maxy-(TRANSITIONEDGE + MAP_EDGE_PAD)) - startx = world.maxx-(TRANSITIONEDGE + MAP_EDGE_PAD) + starty = rand(1, world.maxy) + startx = world.maxx if(SOUTH) - starty = (TRANSITIONEDGE + MAP_EDGE_PAD) - startx = rand((TRANSITIONEDGE + MAP_EDGE_PAD), world.maxx-(TRANSITIONEDGE + MAP_EDGE_PAD)) + starty = 1 + startx = rand(1, world.maxx) if(WEST) - starty = rand((TRANSITIONEDGE + MAP_EDGE_PAD), world.maxy-(TRANSITIONEDGE + MAP_EDGE_PAD)) - startx = (TRANSITIONEDGE + MAP_EDGE_PAD) - . = locate(startx, starty, Z) - -/proc/spaceDebrisFinishLoc(startSide, Z) - var/endy - var/endx - switch(startSide) - if(NORTH) - endy = (TRANSITIONEDGE + MAP_EDGE_PAD) - endx = rand((TRANSITIONEDGE + MAP_EDGE_PAD), world.maxx-(TRANSITIONEDGE + MAP_EDGE_PAD)) - if(EAST) - endy = rand((TRANSITIONEDGE + MAP_EDGE_PAD), world.maxy-(TRANSITIONEDGE + MAP_EDGE_PAD)) - endx = (TRANSITIONEDGE + MAP_EDGE_PAD) - if(SOUTH) - endy = world.maxy-(TRANSITIONEDGE + MAP_EDGE_PAD) - endx = rand((TRANSITIONEDGE + MAP_EDGE_PAD), world.maxx-(TRANSITIONEDGE + MAP_EDGE_PAD)) - if(WEST) - endy = rand((TRANSITIONEDGE + MAP_EDGE_PAD),world.maxy-(TRANSITIONEDGE + MAP_EDGE_PAD)) - endx = world.maxx-(TRANSITIONEDGE + MAP_EDGE_PAD) - . = locate(endx, endy, Z) + starty = rand(1, world.maxy) + startx = 1 + return locate(startx, starty, Z) /////////////////////// //The meteor effect @@ -96,7 +78,8 @@ GLOBAL_LIST_INIT(meteors_gore, list(/obj/effect/meteor/meaty = 5, /obj/effect/me var/list/meteordrop = list(/obj/item/stack/ore/iron) var/dropamt = 2 -/obj/effect/meteor/Move() +/obj/effect/meteor/Move(atom/newloc, direction, glide_size_override = 0, update_dir = TRUE) + // Delete if we reach our goal or somehow leave the Z level. if(z != z_original || loc == dest) qdel(src) return FALSE @@ -114,17 +97,21 @@ GLOBAL_LIST_INIT(meteors_gore, list(/obj/effect/meteor/meaty = 5, /obj/effect/me if(timerid) deltimer(timerid) GLOB.meteor_list -= src - walk(src, 0) //this cancels the walk_towards() proc + GLOB.move_manager.stop_looping(src) //this cancels the GLOB.move_manager.home_onto() proc return ..() /obj/effect/meteor/Initialize(mapload, target) . = ..() + ADD_TRAIT(src, TRAIT_NO_EDGE_TRANSITIONS, ROUNDSTART_TRAIT) z_original = z GLOB.meteor_list += src SpinAnimation() timerid = QDEL_IN(src, lifetime) chase_target(target) +/obj/effect/meteor/Process_Spacemove(movement_dir, continuous_move) + return TRUE + /obj/effect/meteor/Bump(atom/A) if(A) ram_turf(get_turf(A)) @@ -174,7 +161,7 @@ GLOBAL_LIST_INIT(meteors_gore, list(/obj/effect/meteor/meaty = 5, /obj/effect/me /obj/effect/meteor/proc/chase_target(atom/chasing, delay = 1) set waitfor = FALSE if(chasing) - walk_towards(src, chasing, delay) + GLOB.move_manager.home_onto(src, chasing, delay) /obj/effect/meteor/proc/meteor_effect() if(heavy) diff --git a/code/game/objects/effects/spawners/depot_spawners.dm b/code/game/objects/effects/spawners/depot_spawners.dm index e49d5b51122f..153871d088e9 100644 --- a/code/game/objects/effects/spawners/depot_spawners.dm +++ b/code/game/objects/effects/spawners/depot_spawners.dm @@ -65,37 +65,9 @@ ) // Loot -/obj/effect/spawner/random/syndicate/loot - spawn_inside = /obj/structure/closet/secure_closet/depot - -/obj/effect/spawner/random/syndicate/loot/common - name = "syndicate depot loot, common" - icon_state = "loot" - spawn_loot_chance = 50 - // Loot schema: costumes, toys, useless gimmick items - loot = list( - /obj/item/clothing/mask/gas/syndicate, - /obj/item/clothing/shoes/magboots/syndie, - /obj/item/clothing/suit/jacket/bomber/syndicate, - /obj/item/clothing/suit/storage/iaa/blackjacket/armored, - /obj/item/clothing/under/syndicate/combat, - /obj/item/clothing/under/syndicate/sniper, - /obj/item/coin/antagtoken/syndicate, - /obj/item/deck/cards/syndicate, - /obj/item/lighter/zippo/gonzofist, - /obj/item/soap/syndie, - /obj/item/stamp/chameleon, - /obj/item/storage/fancy/cigarettes/cigpack_syndicate, - /obj/item/storage/secure/briefcase/syndie, - /obj/item/storage/toolbox/syndicate, - /obj/item/suppressor, - /obj/item/toy/syndicateballoon, - ) - -/obj/effect/spawner/random/syndicate/loot/stetchkin +/obj/effect/spawner/random/syndicate/stetchkin name = "syndicate depot loot, 20pct stetchkin" icon_state = "stetchkin" - spawn_inside = null spawn_loot_chance = 80 loot = list( /obj/item/gun/projectile/automatic/pistol, @@ -104,84 +76,6 @@ /obj/item/wrench, ) -/obj/effect/spawner/random/syndicate/loot/rare - name = "syndicate depot loot, rare" - icon_state = "doubleloot" - spawn_loot_chance = 50 - // Basic stealth, utility and environmental gear. - loot = list( - /obj/item/ammo_box/magazine/m10mm, - /obj/item/clothing/gloves/color/black/thief, - /obj/item/clothing/shoes/chameleon/noslip, - /obj/item/clothing/under/syndicate/silicon_cham, - /obj/item/clothing/mask/chameleon/voice_change, - /obj/item/flash/cameraflash, - /obj/item/gun/projectile/automatic/toy/pistol/riot, - /obj/item/mod/control/pre_equipped/traitor, - /obj/item/mod/module/chameleon, - /obj/item/mod/module/holster/hidden, - /obj/item/mod/module/noslip, - /obj/item/mod/module/visor/night, - /obj/item/mod/module/plate_compression, - /obj/item/reagent_containers/hypospray/autoinjector/hyper_medipen, - /obj/item/reagent_containers/hypospray/autoinjector/nanocalcium, - /obj/item/stack/sheet/mineral/gold{amount = 20}, - /obj/item/stack/sheet/mineral/plasma{amount = 20}, - /obj/item/stack/sheet/mineral/silver{amount = 20}, - /obj/item/stack/sheet/mineral/uranium{amount = 20}, - /obj/item/storage/backpack/duffel/syndie/med/surgery, - /obj/item/storage/backpack/satchel_flat, - /obj/item/storage/belt/military, - /obj/item/storage/box/syndie_kit/camera_bug, - /obj/item/storage/box/syndie_kit/chameleon, - /obj/item/storage/box/syndie_kit/space, - ) - -/obj/effect/spawner/random/syndicate/loot/officer - name = "syndicate depot loot, officer" - spawn_loot_chance = 40 - // Primarily utility items with occasional low damage weaponry. - loot = list( - /obj/item/borg/upgrade/syndicate, - /obj/item/clothing/glasses/hud/security/chameleon, - /obj/item/clothing/glasses/thermal, - /obj/item/clothing/shoes/magboots/elite, - /obj/item/door_remote/omni/access_tuner, - /obj/item/encryptionkey/binary, - /obj/item/gun/projectile/automatic/c20r/toy/riot, - /obj/item/jammer, - /obj/item/mod/module/power_kick, - /obj/item/mod/module/stealth, - /obj/item/mod/module/visor/thermal, - /obj/item/pen/edagger, - /obj/item/pinpointer/advpinpointer, - /obj/item/stack/sheet/mineral/diamond{amount = 10}, - /obj/item/storage/belt/sheath/snakesfang, - /obj/item/storage/box/syndidonkpockets, - /obj/item/storage/box/syndie_kit/stechkin, - /obj/item/storage/firstaid/tactical, - ) - -/obj/effect/spawner/random/syndicate/loot/armory - name = "syndicate depot loot, armory" - spawn_inside = /obj/structure/closet/secure_closet/depot/armory - // Combat orientated items that could give the player an advantage if an antag messes with them. - loot = list( - /obj/item/bio_chip_implanter/proto_adrenalin, - /obj/item/chameleon, - /obj/item/cqc_manual, - /obj/item/gun/medbeam, - /obj/item/gun/projectile/automatic/sniper_rifle/toy, - /obj/item/melee/energy/sword/saber, - /obj/item/mod/control/pre_equipped/traitor_elite, - /obj/item/organ/internal/cyberimp/arm/razorwire, - /obj/item/organ/internal/cyberimp/brain/sensory_enhancer, - /obj/item/reagent_containers/hypospray/autoinjector/stimulants, - /obj/item/shield/energy, - /obj/item/storage/box/syndie_kit/teleporter, - /obj/item/weaponcrafting/gunkit/universal_gun_kit, - ) - // Layout-affecting spawns /obj/effect/spawner/random/syndicate/walldoor diff --git a/code/game/objects/effects/spawners/random/bluespace_tap_spawners.dm b/code/game/objects/effects/spawners/random/bluespace_tap_spawners.dm index 77f011d04ab9..32beefb70549 100644 --- a/code/game/objects/effects/spawners/random/bluespace_tap_spawners.dm +++ b/code/game/objects/effects/spawners/random/bluespace_tap_spawners.dm @@ -140,7 +140,7 @@ /obj/effect/spawner/random/bluespace_tap/cultural_rare name = "rare cultural artifacts" loot = list( - /obj/vehicle/space/speedbike/red, + /obj/tgvehicle/speedbike/red, /obj/item/gun/projectile/automatic/l6_saw/toy, /obj/item/gun/projectile/automatic/sniper_rifle/toy, /obj/item/bedsheet/centcom, diff --git a/code/game/objects/effects/spawners/random/pool/pool_spawner.dm b/code/game/objects/effects/spawners/random/pool/pool_spawner.dm index 2cfcaaff9bd2..8005014f407e 100644 --- a/code/game/objects/effects/spawners/random/pool/pool_spawner.dm +++ b/code/game/objects/effects/spawners/random/pool/pool_spawner.dm @@ -4,10 +4,10 @@ icon_state = "loot" /// How much this spawner will subtract from the available budget if it - /// spawns. A value of `INFINITY` (i.e., not setting the value on a subtype) + /// spawns. A value of `-1` (i.e., not setting the value on a subtype) /// does not attempt to subtract from the budget. This is useful for /// spawners which themselves spawn other spawners. - var/point_value = INFINITY + var/point_value = -1 /// Whether non-spawner items should be removed from the shared loot pool /// after spawning. var/unique_picks = FALSE @@ -43,6 +43,7 @@ pool.guaranteed_spawners |= src else pool.known_spawners |= src + return INITIALIZE_HINT_QDEL /obj/effect/spawner/random/pool/generate_loot_list() var/datum/spawn_pool/pool = GLOB.spawn_pool_manager.get(spawn_pool_id) @@ -79,7 +80,7 @@ deduct_points = FALSE // If we don't have a sane point value, don't deduct points - if(point_value == INFINITY) + if(point_value == -1) deduct_points = FALSE // If we deduct points, we need to check affordability diff --git a/code/game/objects/effects/spawners/random/pool/space_loot.dm b/code/game/objects/effects/spawners/random/pool/space_loot.dm new file mode 100644 index 000000000000..1cec5c1408f6 --- /dev/null +++ b/code/game/objects/effects/spawners/random/pool/space_loot.dm @@ -0,0 +1,340 @@ +/datum/spawn_pool/spaceloot + id = "space_loot_spawn_pool" + available_points = 1700 + +/obj/effect/spawner/random/pool/spaceloot + icon = 'icons/effects/random_spawners.dmi' + icon_state = "giftbox" + spawn_pool_id = "space_loot_spawn_pool" + record_spawn = TRUE + +/obj/effect/spawner/random/pool/spaceloot/record_item(type_path_to_make) + if(ispath(type_path_to_make, /obj/effect)) + return + + SSblackbox.record_feedback("tally", "space_loot_spawns", 1, "[type_path_to_make]") + +/obj/effect/spawner/random/pool/spaceloot/dvorak_core_table + point_value = 100 + guaranteed = TRUE + loot = list( + /obj/item/rcd/combat, + /obj/item/gun/medbeam, + /obj/item/gun/energy/wormhole_projector, + /obj/item/storage/box/syndie_kit/oops_all_extraction_flares, + ) + +/obj/effect/spawner/random/pool/spaceloot/dvorak_emp_loot + point_value = 35 + guaranteed = TRUE + loot = list( + /obj/item/grenade/empgrenade = 8, + /obj/item/gun/energy/ionrifle/carbine = 1, + /obj/item/gun/energy/ionrifle = 1, + ) + +/obj/effect/spawner/random/pool/spaceloot/dvorak_displaycase + point_value = 100 + guaranteed = TRUE + loot = list(/obj/structure/displaycase/dvoraks_treat) + +/obj/effect/spawner/random/pool/spaceloot/syndicate/common + name = "syndicate depot loot, common" + icon_state = "loot" + point_value = 10 + loot = list( + // Loot schema: costumes, toys, useless gimmick items + /obj/item/clothing/mask/gas/syndicate, + /obj/item/clothing/shoes/magboots/syndie, + /obj/item/clothing/suit/jacket/bomber/syndicate, + /obj/item/clothing/suit/storage/iaa/blackjacket/armored, + /obj/item/clothing/under/syndicate/combat, + /obj/item/clothing/under/syndicate/sniper, + /obj/item/coin/antagtoken/syndicate, + /obj/item/deck/cards/syndicate, + /obj/item/lighter/zippo/gonzofist, + /obj/item/soap/syndie, + /obj/item/stamp/chameleon, + /obj/item/storage/fancy/cigarettes/cigpack_syndicate, + /obj/item/storage/toolbox/syndicate, + /obj/item/suppressor, + /obj/item/toy/syndicateballoon, + ) + +/obj/effect/spawner/random/pool/spaceloot/syndicate/common/depot + spawn_inside = /obj/structure/closet/secure_closet/depot + spawn_loot_chance = 40 + loot = list( + // Loot schema: costumes, toys, useless gimmick items + /obj/item/clothing/mask/gas/syndicate, + /obj/item/clothing/shoes/magboots/syndie, + /obj/item/clothing/suit/jacket/bomber/syndicate, + /obj/item/clothing/suit/storage/iaa/blackjacket/armored, + /obj/item/clothing/under/syndicate/combat, + /obj/item/clothing/under/syndicate/sniper, + /obj/item/coin/antagtoken/syndicate, + /obj/item/deck/cards/syndicate, + /obj/item/lighter/zippo/gonzofist, + /obj/item/soap/syndie, + /obj/item/stamp/chameleon, + /obj/item/storage/fancy/cigarettes/cigpack_syndicate, + /obj/item/storage/toolbox/syndicate, + /obj/item/suppressor, + /obj/item/toy/syndicateballoon, + + // only in depot for common-tier + /obj/item/storage/secure/briefcase/syndie, + ) + +/obj/effect/spawner/random/pool/spaceloot/syndicate/stetchkin + name = "syndicate depot loot, 20% stetchkin" + icon_state = "stetchkin" + spawn_loot_chance = 80 + point_value = 25 + loot = list(/obj/item/gun/projectile/automatic/pistol) + +/obj/effect/spawner/random/pool/spaceloot/syndicate/rare + name = "syndicate depot loot, rare" + icon_state = "doubleloot" + point_value = 45 + // Basic stealth, utility and environmental gear. + loot = list( + /obj/item/ammo_box/magazine/m10mm, + /obj/item/clothing/gloves/color/black/thief, + /obj/item/clothing/shoes/chameleon/noslip, + /obj/item/clothing/under/syndicate/silicon_cham, + /obj/item/clothing/mask/chameleon/voice_change, + /obj/item/flash/cameraflash, + /obj/item/gun/projectile/automatic/toy/pistol/riot, + /obj/item/lighter/zippo/gonzofist, + /obj/item/mod/module/chameleon, + /obj/item/mod/module/holster/hidden, + /obj/item/mod/module/noslip, + /obj/item/mod/module/visor/night, + /obj/item/mod/module/plate_compression, + /obj/item/reagent_containers/hypospray/autoinjector/hyper_medipen, + /obj/item/reagent_containers/hypospray/autoinjector/nanocalcium, + /obj/item/stack/sheet/mineral/gold{amount = 20}, + /obj/item/stack/sheet/mineral/plasma{amount = 20}, + /obj/item/stack/sheet/mineral/silver{amount = 20}, + /obj/item/stack/sheet/mineral/uranium{amount = 20}, + /obj/item/stamp/chameleon, + /obj/item/storage/backpack/duffel/syndie/med/surgery, + /obj/item/storage/backpack/satchel_flat, + /obj/item/storage/belt/military, + /obj/item/storage/box/syndie_kit/camera_bug, + /obj/item/storage/box/syndie_kit/chameleon, + /obj/item/storage/box/syndie_kit/space, + + // common -> rare-tier for ruins + /obj/item/storage/secure/briefcase/syndie, + ) + +/obj/effect/spawner/random/pool/spaceloot/syndicate/rare/depot + spawn_inside = /obj/structure/closet/secure_closet/depot + spawn_loot_chance = 40 + loot = list( + /obj/item/ammo_box/magazine/m10mm, + /obj/item/clothing/gloves/color/black/thief, + /obj/item/clothing/shoes/chameleon/noslip, + /obj/item/clothing/under/syndicate/silicon_cham, + /obj/item/clothing/mask/chameleon/voice_change, + /obj/item/flash/cameraflash, + /obj/item/gun/projectile/automatic/toy/pistol/riot, + /obj/item/lighter/zippo/gonzofist, + /obj/item/mod/module/chameleon, + /obj/item/mod/module/holster/hidden, + /obj/item/mod/module/noslip, + /obj/item/mod/module/visor/night, + /obj/item/mod/module/plate_compression, + /obj/item/reagent_containers/hypospray/autoinjector/hyper_medipen, + /obj/item/reagent_containers/hypospray/autoinjector/nanocalcium, + /obj/item/stack/sheet/mineral/gold{amount = 20}, + /obj/item/stack/sheet/mineral/plasma{amount = 20}, + /obj/item/stack/sheet/mineral/silver{amount = 20}, + /obj/item/stack/sheet/mineral/uranium{amount = 20}, + /obj/item/stamp/chameleon, + /obj/item/storage/backpack/duffel/syndie/med/surgery, + /obj/item/storage/backpack/satchel_flat, + /obj/item/storage/belt/military, + /obj/item/storage/box/syndie_kit/camera_bug, + /obj/item/storage/box/syndie_kit/chameleon, + /obj/item/storage/box/syndie_kit/space, + ) + +/obj/effect/spawner/random/pool/spaceloot/syndicate/officer + name = "syndicate depot loot, officer" + point_value = 110 + // Primarily utility items with occasional low damage weaponry, and a blood-red, because that's too good for rare-tier. + loot = list( + /obj/item/borg/upgrade/syndicate, + /obj/item/clothing/glasses/hud/security/chameleon, + /obj/item/clothing/glasses/thermal, + /obj/item/clothing/shoes/magboots/elite, + /obj/item/door_remote/omni/access_tuner, + /obj/item/encryptionkey/binary, + /obj/item/jammer, + /obj/item/mod/module/power_kick, + /obj/item/mod/module/visor/thermal, + /obj/item/pen/edagger, + /obj/item/pinpointer/advpinpointer, + /obj/item/stack/sheet/mineral/diamond{amount = 10}, + /obj/item/storage/belt/sheath/snakesfang, + /obj/item/storage/box/syndidonkpockets, + /obj/item/storage/box/syndie_kit/stechkin, + /obj/item/mod/control/pre_equipped/traitor, + ) + +/obj/effect/spawner/random/pool/spaceloot/syndicate/officer/depot + spawn_inside = /obj/structure/closet/secure_closet/depot + spawn_loot_chance = 40 + loot = list( + /obj/item/borg/upgrade/syndicate, + /obj/item/clothing/glasses/hud/security/chameleon, + /obj/item/clothing/glasses/thermal, + /obj/item/clothing/shoes/magboots/elite, + /obj/item/door_remote/omni/access_tuner, + /obj/item/encryptionkey/binary, + /obj/item/jammer, + /obj/item/mod/module/power_kick, + /obj/item/mod/module/visor/thermal, + /obj/item/pen/edagger, + /obj/item/pinpointer/advpinpointer, + /obj/item/stack/sheet/mineral/diamond{amount = 10}, + /obj/item/storage/belt/sheath/snakesfang, + /obj/item/storage/box/syndidonkpockets, + /obj/item/storage/box/syndie_kit/stechkin, + /obj/item/mod/control/pre_equipped/traitor, + + // only in depot for officer-tier + /obj/item/mod/module/stealth, + ) + + +/obj/effect/spawner/random/pool/spaceloot/syndicate/armory + name = "syndicate depot loot, armory" + // Combat orientated items that could give the player an advantage if an antag messes with them. + point_value = 200 + loot = list( + /obj/item/bio_chip_implanter/proto_adrenalin, + /obj/item/chameleon, + /obj/item/gun/medbeam, + /obj/item/gun/projectile/automatic/sniper_rifle/toy, + /obj/item/melee/energy/sword/saber, + /obj/item/mod/control/pre_equipped/traitor_elite, + /obj/item/organ/internal/cyberimp/arm/razorwire, + /obj/item/organ/internal/cyberimp/brain/sensory_enhancer, + /obj/item/reagent_containers/hypospray/autoinjector/stimulants, + /obj/item/shield/energy, + /obj/item/weaponcrafting/gunkit/universal_gun_kit, + + // officer -> armory tier for ruins + /obj/item/mod/module/stealth, + ) + +/obj/effect/spawner/random/pool/spaceloot/syndicate/armory/depot + guaranteed = TRUE + spawn_inside = /obj/structure/closet/secure_closet/depot/armory + loot = list( + /obj/item/bio_chip_implanter/proto_adrenalin, + /obj/item/chameleon, + /obj/item/gun/medbeam, + /obj/item/gun/projectile/automatic/sniper_rifle/toy, + /obj/item/melee/energy/sword/saber, + /obj/item/mod/control/pre_equipped/traitor_elite, + /obj/item/organ/internal/cyberimp/arm/razorwire, + /obj/item/organ/internal/cyberimp/brain/sensory_enhancer, + /obj/item/reagent_containers/hypospray/autoinjector/stimulants, + /obj/item/shield/energy, + /obj/item/weaponcrafting/gunkit/universal_gun_kit, + + // only in armory tier for depot + /obj/item/storage/box/syndie_kit/teleporter, + /obj/item/cqc_manual, + ) + + +/obj/effect/spawner/random/pool/spaceloot/syndicate/mixed + loot = list( + /obj/effect/spawner/random/pool/spaceloot/syndicate/common = 30, + /obj/effect/spawner/random/pool/spaceloot/syndicate/rare = 20, + /obj/effect/spawner/random/pool/spaceloot/syndicate/officer = 5, + /obj/effect/spawner/random/pool/spaceloot/syndicate/armory = 1, + ) + +// Only two of these +/obj/effect/spawner/random/pool/spaceloot/zoo + unique_picks = TRUE + guaranteed = TRUE + point_value = 20 + loot = list( + /obj/item/gun/energy/floragun, + /obj/item/gun/energy/temperature, + ) + +/obj/effect/spawner/random/pool/spaceloot/modsuit_syndie + point_value = 100 + spawn_loot_chance = 50 + loot = list(/mob/living/simple_animal/hostile/syndicate/ranged/space/autogib) + +/obj/effect/spawner/random/pool/spaceloot/moonoutpost19 + name = "moon outpost 19 loot spawner" + point_value = 30 + guaranteed = TRUE + spawn_all_loot = TRUE + +/obj/effect/spawner/random/pool/spaceloot/moonoutpost19/vault1 + loot = list(/obj/item/paper/researchnotes) + +/obj/effect/spawner/random/pool/spaceloot/moonoutpost19/vault2 + loot = list( + /obj/item/storage/lockbox/experimental_weapon, + /obj/item/assembly/signaler/anomaly/random, + ) + +/obj/effect/spawner/random/pool/spaceloot/moonoutpost19/vault3 + loot = list( + /obj/item/mecha_parts/core, + /obj/item/stock_parts/cell/infinite/abductor, + ) + +/obj/effect/spawner/random/pool/spaceloot/deepstorage/main + name = "warehouse main reward spawner" + guaranteed = TRUE + point_value = 100 + loot = list( + /obj/item/storage/belt/champion/wrestling, + /obj/item/storage/box/weaver_kit, + /obj/item/gun/medbeam, + /obj/item/storage/lockbox/experimental_weapon, + ) + +/obj/effect/spawner/random/pool/spaceloot/mechtransport + name = "mech transport storage loot spawner" + guaranteed = TRUE + point_value = 20 + spawn_all_loot = TRUE + spawn_random_offset = TRUE + spawn_random_offset_max_pixels = 8 + + +/obj/effect/spawner/random/pool/spaceloot/mechtransport/storage1 + loot = list( + /obj/item/mecha_parts/mecha_equipment/repair_droid, + /obj/item/mecha_parts/mecha_equipment/extinguisher, + /obj/item/mecha_modkit/voice/honk, + ) + +/obj/effect/spawner/random/pool/spaceloot/mechtransport/storage2 + loot = list( + /obj/item/mecha_parts/mecha_equipment/drill/diamonddrill, + /obj/item/mecha_parts/mecha_equipment/drill, + /obj/item/mecha_parts/mecha_equipment/drill, + ) + +/obj/effect/spawner/random/pool/spaceloot/mechtransport/storage3 + loot = list(/obj/item/mecha_parts/mecha_equipment/medical/sleeper) + +/obj/effect/spawner/random/pool/spaceloot/mechtransport/storage4 + loot = list(/obj/item/mecha_parts/core) + diff --git a/code/game/objects/effects/spawners/random/pool/spawn_pool.dm b/code/game/objects/effects/spawners/random/pool/spawn_pool.dm index 8588a1b1dcbe..7c1ff9434c5f 100644 --- a/code/game/objects/effects/spawners/random/pool/spawn_pool.dm +++ b/code/game/objects/effects/spawners/random/pool/spawn_pool.dm @@ -55,5 +55,6 @@ qdel(spawner) + log_game("finished spawner [id] with [length(known_spawners)] remaining spawners and [available_points] points remaining.") QDEL_LIST_CONTENTS(known_spawners) diff --git a/code/game/objects/effects/spawners/random/random_spawner.dm b/code/game/objects/effects/spawners/random/random_spawner.dm index 4d7487f65e62..c3f1c6eec5bc 100644 --- a/code/game/objects/effects/spawners/random/random_spawner.dm +++ b/code/game/objects/effects/spawners/random/random_spawner.dm @@ -70,9 +70,10 @@ var/list/spawn_locations = get_spawn_locations(spawn_scatter_radius) var/spawn_loot_count = isnull(lootcount_override) ? src.spawn_loot_count : lootcount_override + var/atom/container if(spawn_inside) - new spawn_inside(loc) + container = new spawn_inside(loc) if(spawn_all_loot) spawn_loot_count = INFINITY @@ -127,6 +128,10 @@ spawned_loot.pixel_x = spawn_loot_split_pixel_offsets * (loot_spawned % pixel_divider) + (column * spawn_loot_split_pixel_offsets) spawned_loot.pixel_y = spawn_loot_split_pixel_offsets * (loot_spawned % pixel_divider) + if(container) + spawned_loot.forceMove(container) + + /** * Makes the actual item related to our spawner. If `record_spawn` is `TRUE`, * this is when the items spawned are recorded to blackbox (except for `/obj/effect`s). diff --git a/code/game/objects/effects/spawners/random/traders/trader_department_spawners.dm b/code/game/objects/effects/spawners/random/traders/trader_department_spawners.dm index 9d1175f13dcd..7f781448d467 100644 --- a/code/game/objects/effects/spawners/random/traders/trader_department_spawners.dm +++ b/code/game/objects/effects/spawners/random/traders/trader_department_spawners.dm @@ -181,8 +181,8 @@ /obj/vehicle/motorcycle, /obj/vehicle/snowmobile, /obj/vehicle/snowmobile/blue, - /obj/vehicle/space/speedbike/red, - /obj/vehicle/space/speedbike, + /obj/tgvehicle/speedbike/red, + /obj/tgvehicle/speedbike, ) /obj/effect/spawner/random/traders/vehicle/make_item(spawn_loc, type_path_to_make) diff --git a/code/game/objects/items/control_wand.dm b/code/game/objects/items/control_wand.dm index d3905586c9ab..195c4a6ed18e 100644 --- a/code/game/objects/items/control_wand.dm +++ b/code/game/objects/items/control_wand.dm @@ -16,8 +16,10 @@ var/additional_access = list() var/obj/item/card/id/ID -/obj/item/door_remote/New() - ..() + new_attack_chain = TRUE + +/obj/item/door_remote/Initialize(mapload) + . = ..() ID = new /obj/item/card/id for(var/region in region_access) ID.access += get_region_accesses(region) @@ -28,7 +30,10 @@ QDEL_NULL(ID) return ..() -/obj/item/door_remote/attack_self__legacy__attackchain(mob/user) +/obj/item/door_remote/activate_self(mob/user) + if(..()) + return + var/list/options = list(WAND_OPEN = image(icon = 'icons/mob/radial.dmi', icon_state = "radial_open"), WAND_BOLT = image(icon = 'icons/mob/radial.dmi', icon_state = "radial_bolt"), WAND_EMERGENCY = image(icon = 'icons/mob/radial.dmi', icon_state = "radial_ea"), @@ -49,21 +54,25 @@ . = ..() . += "It's current mode is: [mode]" -/obj/item/door_remote/afterattack__legacy__attackchain(obj/target, mob/user) +/obj/item/door_remote/interact_with_atom(atom/target, mob/living/user, list/modifiers) if(istype(target, /obj/machinery/door/airlock)) access_airlock(target, user) if(istype(target, /obj/machinery/door/window)) access_windoor(target, user) + return ITEM_INTERACT_COMPLETE + +/obj/item/door_remote/ranged_interact_with_atom(atom/target, mob/living/user, list/modifiers) + if(istype(target, /obj/machinery/door/airlock)) + access_airlock(target, user) + if(istype(target, /obj/machinery/door/window)) + access_windoor(target, user) + return ITEM_INTERACT_COMPLETE /obj/item/door_remote/proc/access_airlock(obj/machinery/door/airlock/D, mob/user) if(HAS_TRAIT(D, TRAIT_CMAGGED)) to_chat(user, "The door doesn't respond to [src]!") return - if(D.is_special) - to_chat(user, "[src] cannot access this kind of door!") - return - if(!(D.arePowerSystemsOn())) to_chat(user, "[D] has no power!") return @@ -184,10 +193,20 @@ /// How far can we use this. Leave `null` for infinite range var/range -/obj/item/door_remote/omni/access_tuner/afterattack__legacy__attackchain(obj/machinery/door/D, mob/user) - if(!istype(D, /obj/machinery/door/airlock) && !istype(D, /obj/machinery/door/window)) +/obj/item/door_remote/omni/access_tuner/interact_with_atom(atom/target, mob/living/user, list/modifiers) + if(!hack(target, user)) // if the hack is successful, calls the parent proc and does the door stuff + return ITEM_INTERACT_COMPLETE + return ..() + +/obj/item/door_remote/omni/access_tuner/ranged_interact_with_atom(atom/target, mob/living/user, list/modifiers) + if(!hack(target, user)) + return ITEM_INTERACT_COMPLETE + return ..() + +/obj/item/door_remote/omni/access_tuner/proc/hack(atom/target, mob/user) + if(!istype(target, /obj/machinery/door/airlock) && !istype(target, /obj/machinery/door/window)) return - if(!isnull(range) && get_dist(src, D) > range) + if(!isnull(range) && get_dist(src, target) > range) return if(busy) @@ -195,9 +214,11 @@ return icon_state = "hacktool-g" busy = TRUE - to_chat(user, "[src] is attempting to interface with [D]...") - if(do_after(user, hack_speed, target = D)) - . = ..() + to_chat(user, "[src] is attempting to interface with [target]...") + if(do_after(user, hack_speed, target = target)) + busy = FALSE + icon_state = "hacktool" + return TRUE busy = FALSE icon_state = "hacktool" @@ -224,41 +245,54 @@ var/last_airlock_uid additional_access = list(ACCESS_MEDICAL, ACCESS_RESEARCH, ACCESS_CONSTRUCTION, ACCESS_MAILSORTING, ACCESS_CARGO, ACCESS_MINING, ACCESS_KITCHEN, ACCESS_BAR, ACCESS_JANITOR, ACCESS_CHAPEL_OFFICE) +/obj/item/door_remote/janikeyring/Initialize(mapload) + . = ..() + RegisterSignal(src, COMSIG_ACTIVATE_SELF, TYPE_PROC_REF(/datum, signal_cancel_activate_self)) + /obj/item/door_remote/janikeyring/examine(mob/user) . = ..() . += "This keyring has access to Medbay, Science, Engineering, Cargo, the Bar and the Kitchen!" -/obj/item/door_remote/janikeyring/attack_self__legacy__attackchain(mob/user) - if(cooldown > world.time) +/obj/item/door_remote/janikeyring/activate_self(mob/user) + if(..() || cooldown > world.time) return + to_chat(user, "You shake [src]!") playsound(src, 'sound/items/keyring_shake.ogg', 50) cooldown = world.time + JANGLE_COOLDOWN -/obj/item/door_remote/janikeyring/afterattack__legacy__attackchain(obj/machinery/door/D, mob/user, proximity) - if(!proximity) - return - if(!istype(D, /obj/machinery/door/airlock) && !istype(D, /obj/machinery/door/window)) +/obj/item/door_remote/janikeyring/interact_with_atom(obj/machinery/door/target, mob/living/user, list/modifiers) + if(!unlock(target, user)) + return ITEM_INTERACT_COMPLETE + return ..() + +/obj/item/door_remote/janikeyring/ranged_interact_with_atom(atom/target, mob/living/user, list/modifiers) // THOSE AINT MAGICAL REMOTE KEYS + return ITEM_INTERACT_COMPLETE + + +/obj/item/door_remote/janikeyring/proc/unlock(obj/machinery/door/target, mob/living/user) + if(!istype(target, /obj/machinery/door/airlock) && !istype(target, /obj/machinery/door/window)) return if(busy) - to_chat(user, "You are already using [src] on the [D]'s access panel!") + to_chat(user, "You are already using [src] on the [target]'s access panel!") return busy = TRUE var/mob/living/carbon/human/H = user - if(H.mind.assigned_role == "Janitor" && last_airlock_uid == D.UID()) - to_chat(user, "You recognize [D] and look for the key you used...") + if(H.mind.assigned_role == "Janitor" && last_airlock_uid == target.UID()) + to_chat(user, "You recognize [target] and look for the key you used...") hack_speed = 5 SECONDS else - to_chat(user, "You fiddle with [src], trying different keys to open [D]...") + to_chat(user, "You fiddle with [src], trying different keys to open [target]...") if(H.mind.assigned_role != "Janitor") hack_speed = rand(30, 60) SECONDS else hack_speed = rand(5, 20) SECONDS playsound(src, 'sound/items/keyring_unlock.ogg', 50) - if(do_after(user, hack_speed, target = D, progress = 0)) - if(D.check_access(ID)) - last_airlock_uid = D.UID() - . = ..() + if(do_after(user, hack_speed, target = target, progress = 0)) + if(target.check_access(ID)) + last_airlock_uid = target.UID() + busy = FALSE + return TRUE busy = FALSE /obj/item/door_remote/janikeyring/access_airlock(obj/machinery/door/airlock/D, mob/user) @@ -266,10 +300,6 @@ to_chat(user, "[src] won't fit in the [D] airlock's access panel, there's slime everywhere!") return - if(D.is_special) - to_chat(user, "[src] cannot fit in the [D] airlock's access panel!") - return - if(!D.arePowerSystemsOn()) to_chat(user, "The [D] airlock has no power!") return diff --git a/code/game/objects/items/crayons.dm b/code/game/objects/items/crayons.dm index e95e8c945677..36ab5e3bd7a0 100644 --- a/code/game/objects/items/crayons.dm +++ b/code/game/objects/items/crayons.dm @@ -40,8 +40,8 @@ user.visible_message("[user] is jamming the [name] up [user.p_their()] nose and into [user.p_their()] brain. It looks like [user.p_theyre()] trying to commit suicide!") return BRUTELOSS|OXYLOSS -/obj/item/toy/crayon/New() - ..() +/obj/item/toy/crayon/Initialize(mapload) + . = ..() drawtype = pick(pick(graffiti), pick(letters), "rune[rand(1, 8)]") /obj/item/toy/crayon/activate_self(mob/user) @@ -207,7 +207,8 @@ colour = COLOR_PURPLE dye_color = DYE_PURPLE -/obj/item/toy/crayon/random/New() +/obj/item/toy/crayon/random/Initialize(mapload) + . = ..() icon_state = pick("crayonred", "crayonorange", "crayonyellow", "crayongreen", "crayonblue", "crayonpurple") switch(icon_state) if("crayonred") @@ -234,7 +235,6 @@ name = "purple crayon" colour = COLOR_PURPLE dye_color = DYE_PURPLE - ..() /obj/item/toy/crayon/black name = "black crayon" @@ -315,8 +315,9 @@ dye_color = null // not technically a crayon, so we're not gonna have it dye stuff in the laundry machine consumable = FALSE // To stop you from eating spraycans. It's TOO SILLY! -/obj/item/toy/crayon/spraycan/New() - ..() +/obj/item/toy/crayon/spraycan/Initialize(mapload) + . = ..() + RegisterSignal(src, COMSIG_ACTIVATE_SELF, TYPE_PROC_REF(/datum, signal_cancel_activate_self)) update_icon() /obj/item/toy/crayon/spraycan/activate_self(mob/user) @@ -329,7 +330,7 @@ capped = !capped update_icon() if("Change Drawing") - ..() + update_window(user) if("Change Color") colour = tgui_input_color(user,"Please select a paint color.","Spray Can Color") if(isnull(colour)) diff --git a/code/game/objects/items/salvage.dm b/code/game/objects/items/salvage.dm index 47a35d5c854a..2921a25dfe40 100644 --- a/code/game/objects/items/salvage.dm +++ b/code/game/objects/items/salvage.dm @@ -79,7 +79,7 @@ /obj/item/salvage/loot/pirate name = "stolen jewellery" - desc = "A collection of stolen jewellery, fashioned from pilfered bluespace crystals and gems. Rumour has it, local pirates have been known to use these accessories to avoid capture." + desc = "A collection of stolen jewellery and gemstones. Gold, silver, sapphire, amethyst, and more, this bounty will surely fetch a good price on the market." icon_state = "pirate_treasure" hitsound = 'sound/items/handling/taperecorder_drop.ogg' pickup_sound = 'sound/items/handling/taperecorder_pickup.ogg' diff --git a/code/game/objects/items/weapons/bio_chips/bio_chip_fluff.dm b/code/game/objects/items/weapons/bio_chips/bio_chip_fluff.dm index b0b32d1da98e..4b1b34bc813f 100644 --- a/code/game/objects/items/weapons/bio_chips/bio_chip_fluff.dm +++ b/code/game/objects/items/weapons/bio_chips/bio_chip_fluff.dm @@ -142,7 +142,7 @@ name = "Syndicate S3 \"Stealth\" Bio-chip" life = "Unknown. No collected sample has been active long enough to determine lifespan." notes = "Manually activated by the user." - function = "Allows the user to summon a box from a bluespace pocket located inside the implant. The exterior of this box is lined with experimental cloaking panels which render the box invisible to the naked eye." + function = "A biochip housing a highly specialized cloaking nanoswarm. When activated, the nanoswarm will assemble into a box-like shape around the user and render them invisible. Solid impacts will temporarily disrupt the cloaking mechanism." /datum/implant_fluff/shock name = "Syndicate ARC-7 \"Power\" Bio-chip" diff --git a/code/game/objects/items/weapons/grenades/clusterbuster.dm b/code/game/objects/items/weapons/grenades/clusterbuster.dm index ce1e42e9181f..2a4a30a6b6c1 100644 --- a/code/game/objects/items/weapons/grenades/clusterbuster.dm +++ b/code/game/objects/items/weapons/grenades/clusterbuster.dm @@ -47,7 +47,7 @@ icon_state = "clusterbang_segment_active" payload = payload_type active = TRUE - walk_away(src, loc, rand(1,4)) + GLOB.move_manager.move_away(src, loc, rand(1,4)) spawn(rand(15,60)) prime() @@ -69,7 +69,7 @@ var/obj/item/grenade/P = new type(loc) if(istype(P, /obj/item/grenade)) P.active = TRUE - walk_away(P,loc,rand(1,4)) + GLOB.move_manager.move_away(P,loc,rand(1,4)) spawn(rand(15,60)) if(!QDELETED(P)) diff --git a/code/game/objects/items/weapons/grenades/grenade.dm b/code/game/objects/items/weapons/grenades/grenade.dm index 27f0f27aec24..137c51bb545f 100644 --- a/code/game/objects/items/weapons/grenades/grenade.dm +++ b/code/game/objects/items/weapons/grenades/grenade.dm @@ -107,12 +107,11 @@ /obj/item/grenade/attack_hand() ///We need to clear the walk_to on grabbing a moving grenade to have it not leap straight out of your hand - walk(src, null, null) + GLOB.move_manager.stop_looping(src) ..() /obj/item/grenade/Destroy() - ///We need to clear the walk_to on destroy to allow a grenade which uses walk_to or related to properly GC - walk_to(src, 0) + GLOB.move_manager.stop_looping(src) return ..() /obj/item/grenade/cmag_act(mob/user) diff --git a/code/game/objects/items/weapons/storage/backpack.dm b/code/game/objects/items/weapons/storage/backpack.dm index 3a767524ad78..436fc8d1bd8e 100644 --- a/code/game/objects/items/weapons/storage/backpack.dm +++ b/code/game/objects/items/weapons/storage/backpack.dm @@ -50,7 +50,7 @@ /obj/item/storage/backpack/holding name = "Bag of Holding" - desc = "A backpack that opens into a localized pocket of Bluespace." + desc = "A bleeding-edge backpack that uses bluespace technology to create a localized dimensional pocket for storage." origin_tech = "bluespace=5;materials=4;engineering=4;plasmatech=5" icon_state = "holdingpack" item_state = "holdingpack" diff --git a/code/game/objects/items/weapons/storage/bags.dm b/code/game/objects/items/weapons/storage/bags.dm index 724e387b6d1c..8205c863ce0b 100644 --- a/code/game/objects/items/weapons/storage/bags.dm +++ b/code/game/objects/items/weapons/storage/bags.dm @@ -98,7 +98,7 @@ /obj/item/storage/bag/trash/bluespace name = "trash bag of holding" - desc = "The latest and greatest in custodial convenience, a trashbag that is capable of holding vast quantities of garbage." + desc = "An advanced trash bag that uses experimental bluespace technology to send stored trash to a specialized pocket dimension." icon_state = "bluetrashbag" belt_icon = "trashbag_blue" origin_tech = "materials=4;bluespace=4;engineering=4;plasmatech=3" @@ -348,8 +348,7 @@ // Make each item scatter a bit for(var/obj/item/I in oldContents) - I.forceMove(M) - INVOKE_ASYNC(src, PROC_REF(scatter_tray_items), I) + do_scatter(I) if(prob(50)) playsound(M, 'sound/items/trayhit1.ogg', 50, 1) @@ -359,13 +358,18 @@ if(ishuman(M) && prob(10)) M.KnockDown(4 SECONDS) -/obj/item/storage/bag/tray/proc/scatter_tray_items(obj/item/I) - if(!I) - return +/obj/item/storage/bag/tray/proc/do_scatter(obj/item/tray_item) + var/delay = rand(2, 4) + var/datum/move_loop/loop = GLOB.move_manager.move_rand(tray_item, GLOB.cardinal, delay, timeout = rand(1, 2) * delay, flags = MOVEMENT_LOOP_START_FAST) + //This does mean scattering is tied to the tray. Not sure how better to handle it + RegisterSignal(loop, COMSIG_MOVELOOP_POSTPROCESS, PROC_REF(change_speed)) - for(var/i in 1 to rand(1, 2)) - step(I, pick(NORTH,SOUTH,EAST,WEST)) - sleep(rand(2, 4)) +/obj/item/storage/bag/tray/proc/change_speed(datum/move_loop/source) + SIGNAL_HANDLER // COMSIG_MOVELOOP_POSTPROCESS + var/new_delay = rand(2, 4) + var/count = source.lifetime / source.delay + source.lifetime = count * new_delay + source.delay = new_delay /obj/item/storage/bag/tray/update_icon_state() return @@ -415,7 +419,7 @@ I.forceMove(dropspot) // If there is no table, dump the contents of the tray at our feet like we're doing the service equivilent of a micdrop. if(!found_table && isturf(dropspot)) - INVOKE_ASYNC(src, PROC_REF(scatter_tray_items), I) + INVOKE_ASYNC(src, PROC_REF(do_scatter), I) if(found_table) user.visible_message("[user] unloads [user.p_their()] serving tray.") diff --git a/code/game/objects/items/weapons/storage/belt.dm b/code/game/objects/items/weapons/storage/belt.dm index a3c57ce9dccf..d3a5f3d7f18b 100644 --- a/code/game/objects/items/weapons/storage/belt.dm +++ b/code/game/objects/items/weapons/storage/belt.dm @@ -835,7 +835,7 @@ /obj/item/storage/belt/bluespace name = "Belt of Holding" - desc = "The greatest in pants-supporting technology." + desc = "A bleeding-edge storage medium that incorporates principles developed for the Bag of Holding into belt form." icon_state = "holdingbelt" item_state = "holdingbelt" storage_slots = 14 diff --git a/code/game/objects/items/weapons/tanks/jetpack.dm b/code/game/objects/items/weapons/tanks/jetpack.dm index 3d8052094ceb..7808989a80e2 100644 --- a/code/game/objects/items/weapons/tanks/jetpack.dm +++ b/code/game/objects/items/weapons/tanks/jetpack.dm @@ -10,8 +10,37 @@ actions_types = list(/datum/action/item_action/set_internals, /datum/action/item_action/toggle_jetpack, /datum/action/item_action/jetpack_stabilization) var/gas_type = "oxygen" var/on = FALSE - var/stabilizers = FALSE var/volume_rate = 500 //Needed for borg jetpack transfer + var/stabilize = FALSE + var/thrust_callback + +/obj/item/tank/jetpack/Initialize(mapload) + . = ..() + thrust_callback = CALLBACK(src, PROC_REF(allow_thrust), 0.01) + configure_jetpack(stabilize) + +/obj/item/tank/jetpack/Destroy() + thrust_callback = null + return ..() + +/** + * configures/re-configures the jetpack component + * + * Arguments + * stabilize - Should this jetpack be stabalized + */ +/obj/item/tank/jetpack/proc/configure_jetpack(stabilize) + src.stabilize = stabilize + + AddComponent( \ + /datum/component/jetpack, \ + src.stabilize, \ + COMSIG_JETPACK_ACTIVATED, \ + COMSIG_JETPACK_DEACTIVATED, \ + JETPACK_ACTIVATION_FAILED, \ + thrust_callback, \ + /datum/effect_system/trail_follow/ion \ + ) /obj/item/tank/jetpack/populate_gas() if(gas_type) @@ -37,8 +66,8 @@ /obj/item/tank/jetpack/proc/toggle_stabilization(mob/user) if(on) - stabilizers = !stabilizers - to_chat(user, "You turn [src]'s stabilization [stabilizers ? "on" : "off"].") + configure_jetpack(!stabilize) + to_chat(user, "You turn [src]'s stabilization [stabilize ? "on" : "off"].") /obj/item/tank/jetpack/proc/cycle(mob/user) if(user.incapacitated()) @@ -54,31 +83,40 @@ var/datum/action/A = X A.UpdateButtons() - /obj/item/tank/jetpack/proc/turn_on(mob/user) + if(SEND_SIGNAL(src, COMSIG_JETPACK_ACTIVATED, user) & JETPACK_ACTIVATION_FAILED) + return FALSE + on = TRUE icon_state = "[initial(icon_state)]-on" /obj/item/tank/jetpack/proc/turn_off(mob/user) + SEND_SIGNAL(src, COMSIG_JETPACK_DEACTIVATED, user) on = FALSE - stabilizers = FALSE icon_state = initial(icon_state) -/obj/item/tank/jetpack/proc/allow_thrust(num, mob/living/user) - if(!on) - return 0 +/obj/item/tank/jetpack/dropped(mob/user, silent) + . = ..() + if(on) + turn_off(user) + +/obj/item/tank/jetpack/proc/allow_thrust(num) + if(!ismob(loc)) + return FALSE + var/mob/user = loc + if((num < 0.005 || air_contents.total_moles() < num)) turn_off(user) - return 0 + return FALSE var/datum/gas_mixture/removed = air_contents.remove(num) if(removed.total_moles() < 0.005) turn_off(user) - return 0 + return FALSE var/turf/T = get_turf(user) T.blind_release_air(removed) - return 1 + return TRUE /obj/item/tank/jetpack/improvised name = "improvised jetpack" diff --git a/code/game/objects/structures.dm b/code/game/objects/structures.dm index 35f8be4f3017..e1ac0156b718 100644 --- a/code/game/objects/structures.dm +++ b/code/game/objects/structures.dm @@ -43,7 +43,7 @@ REMOVE_TRAIT(loc, TRAIT_TURF_COVERED, UNIQUE_TRAIT_SOURCE(src)) return ..() -/obj/structure/Move() +/obj/structure/Move(atom/newloc, direct = 0, glide_size_override = 0, update_dir = TRUE) var/atom/old = loc if(!..()) return FALSE diff --git a/code/game/objects/structures/crates_lockers/closets.dm b/code/game/objects/structures/crates_lockers/closets.dm index a1e0b163ebf3..a628356606bc 100644 --- a/code/game/objects/structures/crates_lockers/closets.dm +++ b/code/game/objects/structures/crates_lockers/closets.dm @@ -510,7 +510,7 @@ /obj/structure/closet/bluespace name = "bluespace closet" - desc = "A storage unit that moves and stores through the fourth dimension." + desc = "An experimental storage unit which defies several conventional laws of physics. It appears to only tenuously exist on this plane of reality, allowing it to phase through anything less solid than a wall." density = FALSE icon_state = "bluespace" storage_capacity = 60 diff --git a/code/game/objects/structures/crates_lockers/crates.dm b/code/game/objects/structures/crates_lockers/crates.dm index 128209bca78a..777a06ebea4e 100644 --- a/code/game/objects/structures/crates_lockers/crates.dm +++ b/code/game/objects/structures/crates_lockers/crates.dm @@ -37,7 +37,7 @@ if(by_hand) for(var/obj/O in src) if(O.density) - var/response = tgui_alert(usr, "This crate has been packed with bluespace compression, an item inside won't fit back inside. Are you sure you want to open it?", "Bluespace Compression Warning", list("Yes", "No")) + var/response = tgui_alert(usr, "This crate has been packed extremely tightly, an item inside won't fit back inside. Are you sure you want to open it?", "Compressed Materials Warning", list("Yes", "No")) if(response != "Yes" || !Adjacent(usr)) return FALSE break diff --git a/code/game/objects/structures/lattice.dm b/code/game/objects/structures/lattice.dm index 5ba070de0e83..0aa3230c94ef 100644 --- a/code/game/objects/structures/lattice.dm +++ b/code/game/objects/structures/lattice.dm @@ -40,7 +40,7 @@ else // hand this off to the turf instead (for building plating, catwalks, etc) var/turf/T = get_turf(src) - return T.attack_by(C, user, params) + return T.item_interaction(user, C, params) /obj/structure/lattice/deconstruct(disassembled = TRUE) if(!(flags & NODECONSTRUCT)) diff --git a/code/game/objects/structures/morgue.dm b/code/game/objects/structures/morgue.dm index 12403792f164..ee9d664cff92 100644 --- a/code/game/objects/structures/morgue.dm +++ b/code/game/objects/structures/morgue.dm @@ -311,7 +311,7 @@ if(pass_info.is_movable) . = . || pass_info.pass_flags & PASSTABLE -/obj/structure/m_tray/Process_Spacemove(movement_dir) +/obj/structure/m_tray/Process_Spacemove(movement_dir = 0, continuous_move = FALSE) return TRUE /* @@ -582,7 +582,7 @@ GLOBAL_LIST_EMPTY(crematoriums) connected = null return ..() -/obj/structure/c_tray/Process_Spacemove(movement_dir) +/obj/structure/c_tray/Process_Spacemove(movement_dir = 0, continuous_move = FALSE) return TRUE // Crematorium switch diff --git a/code/game/objects/structures/stool_bed_chair_nest/chairs.dm b/code/game/objects/structures/stool_bed_chair_nest/chairs.dm index f7fc087084b9..cf0d6be4cab6 100644 --- a/code/game/objects/structures/stool_bed_chair_nest/chairs.dm +++ b/code/game/objects/structures/stool_bed_chair_nest/chairs.dm @@ -32,7 +32,7 @@ W.setDir(dir) qdel(src) -/obj/structure/chair/Move(atom/newloc, direct) +/obj/structure/chair/Move(atom/newloc, direct = 0, glide_size_override = 0, update_dir = TRUE) . = ..() handle_rotation() diff --git a/code/game/objects/structures/stool_bed_chair_nest/wheelchair.dm b/code/game/objects/structures/stool_bed_chair_nest/wheelchair.dm index 067158533c98..20e24c5bf83f 100644 --- a/code/game/objects/structures/stool_bed_chair_nest/wheelchair.dm +++ b/code/game/objects/structures/stool_bed_chair_nest/wheelchair.dm @@ -73,8 +73,6 @@ if(!buckled_mob.Move(get_step(buckled_mob, direction), direction)) loc = buckled_mob.loc //we gotta go back last_move = buckled_mob.last_move - inertia_dir = last_move - buckled_mob.inertia_dir = last_move . = 0 else diff --git a/code/game/objects/structures/transit_tubes/transit_tube_pod.dm b/code/game/objects/structures/transit_tubes/transit_tube_pod.dm index cebaa4e5dc02..db2fdf551452 100644 --- a/code/game/objects/structures/transit_tubes/transit_tube_pod.dm +++ b/code/game/objects/structures/transit_tubes/transit_tube_pod.dm @@ -50,7 +50,7 @@ stop_following() return ..() -/obj/structure/transit_tube_pod/Process_Spacemove() +/obj/structure/transit_tube_pod/Process_Spacemove(movement_dir = 0, continuous_move = FALSE) if(moving) //No drifting while moving in the tubes return TRUE else return ..() diff --git a/code/game/turfs/simulated.dm b/code/game/turfs/simulated.dm index 9c85caa033f2..74bce5b10b0d 100644 --- a/code/game/turfs/simulated.dm +++ b/code/game/turfs/simulated.dm @@ -138,7 +138,6 @@ switch(src.wet) if(TURF_WET_WATER) if(!(M.slip("the wet floor", WATER_WEAKEN_TIME, tilesSlipped = 0, walkSafely = 1))) - M.inertia_dir = 0 return if(TURF_WET_LUBE) //lube @@ -147,7 +146,6 @@ if(TURF_WET_ICE) // Ice if(M.slip("the icy floor", 8 SECONDS, tilesSlipped = 0, walkSafely = 0)) - M.inertia_dir = 0 if(prob(5)) var/obj/item/organ/external/affected = M.get_organ("head") if(affected) @@ -158,6 +156,10 @@ if(TURF_WET_PERMAFROST) // Permafrost M.slip("the frosted floor", 10 SECONDS, tilesSlipped = 1, walkSafely = 0, slipAny = 1) +/turf/simulated/BeforeChange() + QDEL_NULL(wind_effect) + return ..() + /turf/simulated/ChangeTurf(path, defer_change = FALSE, keep_icon = TRUE, ignore_air = FALSE, copy_existing_baseturf = TRUE) . = ..() QUEUE_SMOOTH_NEIGHBORS(src) diff --git a/code/game/turfs/space/space_turf.dm b/code/game/turfs/space/space_turf.dm index 42d95de60614..d0caaaa58b46 100644 --- a/code/game/turfs/space/space_turf.dm +++ b/code/game/turfs/space/space_turf.dm @@ -122,7 +122,7 @@ if((!(A) || !(src in A.locs))) return - if(destination_z && destination_x && destination_y && !A.pulledby && !HAS_TRAIT(A, TRAIT_CURRENTLY_Z_MOVING)) + if(destination_z && destination_x && destination_y && !A.pulledby && !HAS_TRAIT(A, TRAIT_CURRENTLY_Z_MOVING) && !HAS_TRAIT(A, TRAIT_NO_EDGE_TRANSITIONS)) var/tx = destination_x var/ty = destination_y var/turf/DT = locate(tx, ty, destination_z) diff --git a/code/game/turfs/turf.dm b/code/game/turfs/turf.dm index 765a74fed915..b2c02b58364d 100644 --- a/code/game/turfs/turf.dm +++ b/code/game/turfs/turf.dm @@ -641,11 +641,11 @@ RETURN_TYPE(/datum/gas_mixture) // This is one of two intended places to call this otherwise-unsafe proc. var/datum/gas_mixture/bound_to_turf/air = private_unsafe_get_air() - if(air.lastread < SSair.times_fired) + if(air.lastread < SSair.milla_tick) var/list/milla_tile = new/list(MILLA_TILE_SIZE) get_tile_atmos(src, milla_tile) air.copy_from_milla(milla_tile) - air.lastread = SSair.times_fired + air.lastread = SSair.milla_tick air.readonly = null air.dirty = FALSE air.synchronized = FALSE @@ -678,7 +678,7 @@ return FALSE // If it's old, delete it. - if(active_hotspot.death_timer < SSair.times_fired) + if(active_hotspot.death_timer < SSair.milla_tick) QDEL_NULL(active_hotspot) return FALSE else @@ -687,7 +687,7 @@ if(isnull(active_hotspot)) active_hotspot = new(src) - active_hotspot.death_timer = SSair.times_fired + 4 + active_hotspot.death_timer = SSair.milla_tick + 4 if(air.hotspot_volume() > 0) active_hotspot.temperature = air.hotspot_temperature() active_hotspot.volume = air.hotspot_volume() * CELL_VOLUME @@ -699,7 +699,7 @@ return TRUE /turf/simulated/proc/update_wind() - if(wind_tick != SSair.times_fired) + if(wind_tick != SSair.milla_tick) QDEL_NULL(wind_effect) wind_tick = null return FALSE diff --git a/code/modules/admin/topic.dm b/code/modules/admin/topic.dm index 0ba880790919..5781dd6254ad 100644 --- a/code/modules/admin/topic.dm +++ b/code/modules/admin/topic.dm @@ -40,7 +40,7 @@ if(href_list["makeAntag"]) switch(href_list["makeAntag"]) if("1") - log_admin("[key_name(usr)] has spawned a traitor.") + log_admin("[key_name(usr)] has spawned traitors.") if(!makeTraitors()) to_chat(usr, "Unfortunately there weren't enough candidates available.") if("2") @@ -71,6 +71,10 @@ log_admin("[key_name(usr)] has spawned mindflayers.") if(!makeMindflayers()) to_chat(usr, "Unfortunately there weren't enough candidates available.") + if("9") + log_admin("[key_name(usr)] has spawned event characters.") + if(!makeEventCharacters()) + to_chat(usr, "Unfortunately there weren't enough candidates available.") else if(href_list["dbsearchckey"] || href_list["dbsearchadmin"] || href_list["dbsearchip"] || href_list["dbsearchcid"] || href_list["dbsearchbantype"]) var/adminckey = href_list["dbsearchadmin"] diff --git a/code/modules/admin/verbs/one_click_antag.dm b/code/modules/admin/verbs/one_click_antag.dm index 910795c0f22c..8fc523e97a40 100644 --- a/code/modules/admin/verbs/one_click_antag.dm +++ b/code/modules/admin/verbs/one_click_antag.dm @@ -21,8 +21,9 @@ Make Vampires
Make Abductor Team (Requires Ghosts)
Make Mindflayers
- Make Blood Brothers Team
- Make Vox Raiders
+ Make Event Characters
+ Make Blood Brothers Team
+ Make Vox Raiders
"} usr << browse(dat, "window=oneclickantag;size=400x400") @@ -314,6 +315,64 @@ qdel(temp) return TRUE +/datum/admins/proc/makeEventCharacters() + var/list/mob/living/carbon/human/candidates = list() + var/mob/living/carbon/human/H = null + + var/antnum = input(owner, "How many event characters you want to create? Enter 0 to cancel","Amount:", 0) as num + if(!antnum || antnum <= 0) + return FALSE + + var/datum/game_mode/traitor/temp = new() + var/no_mindshields = input(owner, "Avoid mindshielded characters?") in list("Yes", "No", "Cancel") + if(no_mindshields == "Cancel") + qdel(temp) + return FALSE + else if(no_mindshields == "Yes") + temp.restricted_jobs += temp.protected_jobs + + var/respect_traitor = input(owner, "Require traitor willingness?") in list("Yes", "No", "Cancel") + var/role = null + if(respect_traitor == "Cancel") + qdel(temp) + return FALSE + else if(respect_traitor == "Yes") + role = ROLE_TRAITOR + + var/give_objective = input(owner, "Give them a shared custom objective?") in list("Yes", "No", "Cancel") + var/objective = null + if(give_objective == "Cancel") + qdel(temp) + return FALSE + else if(give_objective == "Yes") + objective = sanitize(copytext_char(input("Custom objective:", "Objective", "") as text|null, 1, MAX_MESSAGE_LEN)) + if(!length(objective)) + qdel(temp) + return FALSE + + log_admin("[key_name(owner)] tried making [antnum] event characters with One-Click-Antag") + message_admins("[key_name_admin(owner)] tried making [antnum] event characters with One-Click-Antag") + + for(var/mob/living/carbon/human/applicant in GLOB.player_list) + if(CandCheck(role, applicant, temp)) + candidates += applicant + qdel(temp) + + if(length(candidates)) + var/num_event_chars = min(length(candidates), antnum) + + for(var/i in 1 to num_event_chars) + H = pick(candidates) + if(!isnull(objective)) + var/datum/objective/O = new() + O.explanation_text = objective + O.needs_target = FALSE + H.mind.add_mind_objective(O) + H.mind.add_antag_datum(/datum/antagonist/eventmisc) + candidates.Remove(H) + return TRUE + return FALSE + /datum/admins/proc/makeThunderdomeTeams() // Not strictly an antag, but this seemed to be the best place to put it. var/max_thunderdome_players = 10 var/team_to_assign_to = "Green" diff --git a/code/modules/antagonists/changeling/powers/summon_spiders.dm b/code/modules/antagonists/changeling/powers/summon_spiders.dm index e535b7319f1d..d693bfd37217 100644 --- a/code/modules/antagonists/changeling/powers/summon_spiders.dm +++ b/code/modules/antagonists/changeling/powers/summon_spiders.dm @@ -114,7 +114,7 @@ switch(current_order) if(IDLE_AGGRESSIVE) Find_Enemies(around) - walk(src, 0) + GLOB.move_manager.stop_looping(src) if(FOLLOW_AGGRESSIVE) Find_Enemies(around) for(var/mob/living/carbon/C in around) @@ -131,7 +131,7 @@ return TRUE Goto(C, 0.5 SECONDS, 1) if(IDLE_RETALIATE) - walk(src, 0) + GLOB.move_manager.stop_looping(src) for(var/mob/living/simple_animal/hostile/poison/giant_spider/hunter/infestation_spider/H in around) if(faction_check_mob(H) && !attack_same && !H.attack_same) diff --git a/code/modules/antagonists/vampire/vampire_powers/hemomancer_powers.dm b/code/modules/antagonists/vampire/vampire_powers/hemomancer_powers.dm index 1f08f7b4289f..dd05286e2fc9 100644 --- a/code/modules/antagonists/vampire/vampire_powers/hemomancer_powers.dm +++ b/code/modules/antagonists/vampire/vampire_powers/hemomancer_powers.dm @@ -126,7 +126,7 @@ /datum/spell/vampire/blood_tendrils name = "Blood Tendrils (10)" - desc = "You summon blood tendrils from bluespace after a delay to ensnare people in an area, slowing them down." + desc = "You summon a small field of horrific blood tendrils after a delay to ensnare people in an area, slowing them down." gain_desc = "You have gained the ability to summon blood tendrils to slow people down in an area that you target." required_blood = 10 @@ -135,7 +135,7 @@ sound = 'sound/misc/enter_blood.ogg' var/area_of_affect = 1 - selection_activated_message = "You channel blood magics to weaken the bluespace veil. Left-click to cast at a target area!" + selection_activated_message = "You prepare to summon a set of blood tendrils. Left-click to cast at a target area!" selection_deactivated_message = "Your magics subside." /datum/spell/vampire/blood_tendrils/create_new_targeting() diff --git a/code/modules/arcade/claw_game.dm b/code/modules/arcade/claw_game.dm index ccd8d1e40cd9..8a6106da2cb4 100644 --- a/code/modules/arcade/claw_game.dm +++ b/code/modules/arcade/claw_game.dm @@ -78,3 +78,7 @@ GLOBAL_VAR(claw_game_html) close_game() if(prize_won == "1") win() + +/obj/machinery/economy/arcade/claw/syndi + desc = "No longer one of the most infuriating ways to win a toy, thanks to the hacking device granting infinite credits." + freeplay = TRUE diff --git a/code/modules/assembly/infrared.dm b/code/modules/assembly/infrared.dm index 687e79881db1..c1ecfb423eed 100644 --- a/code/modules/assembly/infrared.dm +++ b/code/modules/assembly/infrared.dm @@ -234,7 +234,7 @@ /obj/effect/beam/i_beam/update_icon_state() transform = turn(matrix(), dir2angle(dir)) -/obj/effect/beam/i_beam/Process_Spacemove(movement_dir) +/obj/effect/beam/i_beam/Process_Spacemove(movement_dir = 0, continuous_move = FALSE) return TRUE /obj/effect/beam/i_beam/process() diff --git a/code/modules/atmospherics/environmental/LINDA_turf_tile.dm b/code/modules/atmospherics/environmental/LINDA_turf_tile.dm index 882772719295..a6d3b1aafe57 100644 --- a/code/modules/atmospherics/environmental/LINDA_turf_tile.dm +++ b/code/modules/atmospherics/environmental/LINDA_turf_tile.dm @@ -129,9 +129,9 @@ if(direction == 0) return - if(last_high_pressure_movement_time >= SSair.times_fired - 3) + if(last_high_pressure_movement_time >= SSair.milla_tick - 3) return - last_high_pressure_movement_time = SSair.times_fired + last_high_pressure_movement_time = SSair.milla_tick air_push(direction, (force - force_needed) / force_needed) @@ -171,7 +171,7 @@ #define INDEX_SOUTH 3 #define INDEX_WEST 4 -/turf/proc/Initialize_Atmos(times_fired) +/turf/proc/Initialize_Atmos(milla_tick) // This is one of two places expected to call this otherwise-unsafe method. var/list/connectivity = private_unsafe_recalculate_atmos_connectivity() var/list/air = list(oxygen, carbon_dioxide, nitrogen, toxins, sleeping_agent, agent_b, temperature) diff --git a/code/modules/atmospherics/gasmixtures/gas_mixture.dm b/code/modules/atmospherics/gasmixtures/gas_mixture.dm index e14706d7b269..510b981fceec 100644 --- a/code/modules/atmospherics/gasmixtures/gas_mixture.dm +++ b/code/modules/atmospherics/gasmixtures/gas_mixture.dm @@ -762,6 +762,7 @@ What are the archived variables for? #undef QUANTIZE /datum/gas_mixture/bound_to_turf + synchronized = FALSE var/dirty = FALSE var/lastread = 0 var/turf/bound_turf = null diff --git a/code/modules/atmospherics/machinery/components/unary_devices/heat_exchanger.dm b/code/modules/atmospherics/machinery/components/unary_devices/heat_exchanger.dm index 60a7a1187a79..6ed29994f369 100644 --- a/code/modules/atmospherics/machinery/components/unary_devices/heat_exchanger.dm +++ b/code/modules/atmospherics/machinery/components/unary_devices/heat_exchanger.dm @@ -32,11 +32,11 @@ if(!partner) return 0 - if(!SSair || SSair.times_fired <= update_cycle) + if(!SSair || SSair.milla_tick <= update_cycle) return 0 - update_cycle = SSair.times_fired - partner.update_cycle = SSair.times_fired + update_cycle = SSair.milla_tick + partner.update_cycle = SSair.milla_tick var/air_heat_capacity = air_contents.heat_capacity() var/other_air_heat_capacity = partner.air_contents.heat_capacity() diff --git a/code/modules/awaymissions/mission_code/ruins/abandoned_engi_sat.dm b/code/modules/awaymissions/mission_code/ruins/abandoned_engi_sat.dm index 2908f0b65f23..8581222b5186 100644 --- a/code/modules/awaymissions/mission_code/ruins/abandoned_engi_sat.dm +++ b/code/modules/awaymissions/mission_code/ruins/abandoned_engi_sat.dm @@ -1,12 +1,9 @@ /obj/structure/closet/secure_closet/engineering_personal/empty - locked = FALSE - opened = TRUE /obj/structure/closet/secure_closet/engineering_personal/empty/populate_contents() return /obj/structure/closet/wardrobe/atmospherics_yellow/empty - opened = TRUE /obj/structure/closet/wardrobe/atmospherics_yellow/populate_contents() return diff --git a/code/modules/awaymissions/mission_code/ruins/deepstorage.dm b/code/modules/awaymissions/mission_code/ruins/deepstorage.dm index cf4f2f059591..b9f8ee35ad64 100644 --- a/code/modules/awaymissions/mission_code/ruins/deepstorage.dm +++ b/code/modules/awaymissions/mission_code/ruins/deepstorage.dm @@ -175,7 +175,7 @@ if(target) playsound(loc, 'sound/voice/zombie_scream.ogg', 70, TRUE) -/mob/living/simple_animal/hostile/spaceinfected/Move(atom/newloc) +/mob/living/simple_animal/hostile/spaceinfected/Move(atom/newloc, direct = 0, glide_size_override = 0, update_dir = TRUE) if(ischasm(newloc)) // as this place filled with chasms, they shouldn't randomly fall in while wandering around return FALSE return ..() @@ -293,15 +293,6 @@ /obj/item/clothing/glasses/sunglasses/yeah ) -/obj/effect/spawner/random/deepstorage_reward/main - name = "warehouse main reward" - loot = list( - /obj/item/storage/belt/champion/wrestling, - /obj/item/storage/box/weaver_kit, - /obj/item/gun/medbeam, - /obj/item/storage/lockbox/experimental_weapon - ) - // paper stuff & lore /obj/item/paper/fluff/ruins/deepstorage/log1 diff --git a/code/modules/awaymissions/mission_code/ruins/oldstation.dm b/code/modules/awaymissions/mission_code/ruins/oldstation.dm index 8a7ad3c4deb4..7e8bb571a7dd 100644 --- a/code/modules/awaymissions/mission_code/ruins/oldstation.dm +++ b/code/modules/awaymissions/mission_code/ruins/oldstation.dm @@ -438,7 +438,7 @@ opacity = TRUE icon = 'icons/obj/2x2.dmi' icon_state = "large_engine" - desc = "A very large bluespace engine used to propel very large ships." + desc = "A very large sublight engine used to propel very large ships." bound_width = 64 bound_height = 64 appearance_flags = LONG_GLIDE diff --git a/code/modules/awaymissions/mission_code/ruins/telecomns.dm b/code/modules/awaymissions/mission_code/ruins/telecomns.dm index 834c8a6d592f..fdfc8029466f 100644 --- a/code/modules/awaymissions/mission_code/ruins/telecomns.dm +++ b/code/modules/awaymissions/mission_code/ruins/telecomns.dm @@ -388,7 +388,7 @@ GLOBAL_LIST_EMPTY(telecomms_trap_tank) /obj/item/remote_ai_upload // A 1 use AI upload. Potential D.V.O.R.A.K reward. name = "remote AI upload" - desc = "A mobile AI upload. The bluespace relay will likely overload after one use. Make it count." + desc = "A mobile AI upload. The transmitter is extremely powerful, but will burn out after one use. Make it count." icon = 'icons/obj/device.dmi' icon_state = "dvorak_upload" w_class = WEIGHT_CLASS_TINY diff --git a/code/modules/client/client_defines.dm b/code/modules/client/client_defines.dm index 82d1a6fab601..d1d5da742dcf 100644 --- a/code/modules/client/client_defines.dm +++ b/code/modules/client/client_defines.dm @@ -18,6 +18,8 @@ ///////// var/datum/preferences/prefs = null var/skip_antag = FALSE //TRUE when a player declines to be included for the selection process of game mode antagonists. + ///The visual delay to use for the current client.Move(), mostly used for making a client based move look like it came from some other slower source + var/visual_delay = 0 var/move_delay = 1 var/moving = null var/area = null diff --git a/code/modules/clothing/head/helmet.dm b/code/modules/clothing/head/helmet.dm index c676e14ed77e..da306356d125 100644 --- a/code/modules/clothing/head/helmet.dm +++ b/code/modules/clothing/head/helmet.dm @@ -1,6 +1,6 @@ /obj/item/clothing/head/helmet name = "helmet" - desc = "Standard Security gear. Protects the head from impacts." + desc = "A standard-issue protective helmet used by Nanotrasen corporate security. Provides light protection against most sources of damage." icon_state = "helmetmaterials" w_class = WEIGHT_CLASS_NORMAL flags = HEADBANGPROTECT @@ -80,7 +80,7 @@ /obj/item/clothing/head/helmet/alt name = "bulletproof helmet" - desc = "A bulletproof helmet that excels in protecting the wearer against traditional projectile weaponry and explosives to a minor extent." + desc = "A durable combat helmet reinforced with strike plates and cushioning to protect against high-velocity kinetic impacts and the concussive force of explosions. Does little to stop energy weapons or melee hits." icon_state = "bulletproof" item_state = "bulletproof" armor = list(MELEE = 10, BULLET = 50, LASER = 5, ENERGY = 5, BOMB = 45, RAD = 0, FIRE = 50, ACID = 50) @@ -88,7 +88,7 @@ /obj/item/clothing/head/helmet/riot name = "riot helmet" - desc = "It's a helmet specifically designed to protect against close range attacks." + desc = "A large, bulky helmet reinforced with impact plates and shock-absorbing gel to protect against melee attacks. The helmet is treated with a fire and acid-resistant surface coating, and the attached plexiglass visor should prevent things from jumping on your face." icon_state = "riot" item_state = "helmet" armor = list(MELEE = 50, BULLET = 5, LASER = 5, ENERGY = 5, BOMB = 0, RAD = 0, FIRE = 200, ACID = 200) @@ -99,7 +99,7 @@ /obj/item/clothing/head/helmet/riot/knight name = "medieval helmet" - desc = "A classic metal helmet." + desc = "A majestic knightly helm made of steel. Protects well against melee attacks, but don't try taking a bullet with it." icon_state = "knight_green" item_state = "knight_green" flags = BLOCKHAIR @@ -108,10 +108,10 @@ /obj/item/clothing/head/helmet/justice name = "helmet of justice" - desc = "WEEEEOOO. WEEEEEOOO. WEEEEOOOO." + desc = "A standard Security helmet with a pair of police lights crudely screwed to the sides. Any hearing loss caused by this contraption is not service related." icon_state = "justice" - toggle_message = "You turn off the lights on" - alt_toggle_message = "You turn on the lights on" + toggle_message = "You turn off the lights" + alt_toggle_message = "You turn on the lights" actions_types = list(/datum/action/item_action/toggle_helmet_light) can_toggle = 1 toggle_cooldown = 20 @@ -122,13 +122,13 @@ name = "alarm helmet" desc = "WEEEEOOO. WEEEEEOOO. STOP THAT MONKEY. WEEEOOOO." icon_state = "justice2" - toggle_message = "You turn off the light on" - alt_toggle_message = "You turn on the light on" + toggle_message = "You turn off the light" + alt_toggle_message = "You turn on the light" /obj/item/clothing/head/helmet/swat name = "\improper SWAT helmet" - desc = "They're often used by highly trained Swat Members." + desc = "A menacing black combat helmet used by police assault units. Provides moderate protection against all threats." icon_state = "swat" item_state = "swat" @@ -165,8 +165,8 @@ dog_fashion = null /obj/item/clothing/head/helmet/roman - name = "roman helmet" - desc = "An ancient helmet made of bronze and leather." + name = "legionnaire helmet" + desc = "A lovingly-crafted helmet based off examples used by Roman legionnaires. Provides light protection against melee and laser impacts. It's also completely fireproof!" flags = null armor = list(MELEE = 15, BULLET = 0, LASER = 15, ENERGY = 5, BOMB = 5, RAD = 0, FIRE = INFINITY, ACID = 50) resistance_flags = FIRE_PROOF @@ -176,17 +176,17 @@ dog_fashion = /datum/dog_fashion/head/roman /obj/item/clothing/head/helmet/roman/fake - desc = "An ancient helmet made of plastic and leather." + desc = "A shoddily-crafted cosplay helmet made of plastic. Protects against jack and shit, if you're lucky." armor = list(MELEE = 0, BULLET = 0, LASER = 0, ENERGY = 0, BOMB = 0, RAD = 0, FIRE = 0, ACID = 0) /obj/item/clothing/head/helmet/roman/legionaire - name = "roman legionaire helmet" - desc = "An ancient helmet made of bronze and leather. Has a red crest on top of it." + name = "centurion helmet" + desc = "A lovingly-crafted helmet based off those used by Roman centurions. Provides light protection against melee and laser impacts, is completely fireproof, and has a fancy crest on top!" icon_state = "roman_c" item_state = "roman_c" /obj/item/clothing/head/helmet/roman/legionaire/fake - desc = "An ancient helmet made of plastic and leather. Has a red crest on top of it." + desc = "A shoddily-crafted cosplay helmet made of plastic. This particular specimen has what appears to be the head of a broom crudely taped to the top." armor = list(MELEE = 0, BULLET = 0, LASER = 0, ENERGY = 0, BOMB = 0, RAD = 0, FIRE = 0, ACID = 0) /obj/item/clothing/head/helmet/gladiator @@ -252,7 +252,7 @@ /obj/item/clothing/head/helmet/riot/knight/templar name = "crusader helmet" - desc = "Deus Vult." + desc = "A cheap metal helmet that looks straight out of a poorly-funded documentary about the crusades. Might stop a crude melee weapon. The asbestos-lined padding does provide great protection from fire and acid, however..." icon_state = "knight_templar" item_state = "knight_templar" armor = list(MELEE = 10, BULLET = 5, LASER = 5, ENERGY = 5, BOMB = 5, RAD = 0, FIRE = 200, ACID = 200) diff --git a/code/modules/clothing/suits/armor_suits.dm b/code/modules/clothing/suits/armor_suits.dm index a23f6c83fb6b..db8fb8e25717 100644 --- a/code/modules/clothing/suits/armor_suits.dm +++ b/code/modules/clothing/suits/armor_suits.dm @@ -16,8 +16,8 @@ w_class = WEIGHT_CLASS_NORMAL /obj/item/clothing/suit/armor/vest - name = "armor" - desc = "An armored vest that protects against some damage." + name = "perfectly generic armor vest" + desc = "A perfectly generic armored vest. Every aspect of it is exceptionally boring. If you see this, make an issue report on GitHub." sprite_sheets = list( "Grey" = 'icons/mob/clothing/species/grey/suit.dmi', "Vox" = 'icons/mob/clothing/species/vox/suit.dmi' @@ -29,21 +29,21 @@ /obj/item/clothing/suit/armor/vest/jacket name = "military jacket" - desc = "An old military jacket, it has armoring." + desc = "An old Federal Army surplus jacket. Armor panels sewn into the sides provide some protection against impacts and laser fire." icon_state = "militaryjacket" item_state = "militaryjacket" body_parts_covered = UPPER_TORSO|LOWER_TORSO|ARMS /obj/item/clothing/suit/armor/vest/combat name = "combat vest" - desc = "An armored vest that protects against some damage." + desc = "A soft armor vest suitable for stopping minor impacts." icon_state = "armor-combat" item_state = "bulletproof" blood_overlay_type = "armor" /obj/item/clothing/suit/armor/vest/security name = "security armor" - desc = "An armored vest that protects against some damage. This one has a clip for a holobadge." + desc = "A Level II soft armor vest used by Nanotrasen corporate security. Offers light protection against kinetic impacts and lasers, and has a clip for a holobadge." sprite_sheets = list( "Grey" = 'icons/mob/clothing/species/grey/suit.dmi', "Vox" = 'icons/mob/clothing/species/vox/suit.dmi' @@ -62,7 +62,7 @@ A.Grant(user) icon_state = "armorsec" user.update_inv_wear_suit() - desc = "An armored vest that protects against some damage. This one has [attached_badge] attached to it." + desc = "A Level II soft armor vest used by Nanotrasen corporate security, offering light protection against kinetic impacts and lasers. This one has [attached_badge] attached to it." to_chat(user, "You attach [attached_badge] to [src].") return ..() @@ -76,7 +76,7 @@ icon_state = "armor" user.update_inv_wear_suit() - desc = "An armored vest that protects against some damage. This one has a clip for a holobadge." + desc = "A Level II soft armor vest used by Nanotrasen corporate security. Offers light protection against kinetic impacts and lasers, and has a clip for a holobadge." to_chat(user, "You remove [attached_badge] from [src].") attached_badge = null @@ -85,7 +85,7 @@ /obj/item/clothing/suit/armor/vest/street_judge name = "judge's security armor" - desc = "Perfect for when you're looking to send a message rather than performing your actual duties." + desc = "A standard Nanotrasen security vest with some decidedly non-standard decorations attached. Being made of cheap plastic, these decorations do not improve armor performance." icon_state = "streetjudgearmor" sprite_sheets = list( @@ -96,7 +96,7 @@ /obj/item/clothing/suit/armor/vest/blueshield name = "blueshield's security armor" - desc = "An armored vest with the badge of a Blueshield." + desc = "A Level II soft armor vest used by Nanotrasen's Blueshield bodyguard corps. Provides identical protection to standard Security soft vests." sprite_sheets = list( "Grey" = 'icons/mob/clothing/species/grey/suit.dmi', "Vox" = 'icons/mob/clothing/species/vox/suit.dmi' @@ -106,14 +106,14 @@ /obj/item/clothing/suit/armor/vest/bloody name = "bloodied security armor" - desc = "A vest drenched in the blood of Greytide. It has seen better days." + desc = "An old, gore-covered security vest with a face crudely drawn on the chest. Where the hell did they even find this?" icon_state = "bloody_armor" item_state = "bloody_armor" sprite_sheets = null /obj/item/clothing/suit/armor/secjacket name = "security jacket" - desc = "A sturdy black jacket with reinforced fabric. Bears insignia of NT corporate security." + desc = "A stylish black jacket used by Nanotrasen corporate security. Basic kevlar weave offers minor protection, but far less than a typical Security vest." icon_state = "secjacket_open" item_state = "hos" body_parts_covered = UPPER_TORSO|LOWER_TORSO|ARMS @@ -132,7 +132,7 @@ /obj/item/clothing/suit/armor/secponcho name = "security poncho" - desc = "A stylish black and red poncho made with reinforced fabric." + desc = "A stylish black and red poncho used by Nanotrasen corporate security. Basic kevlar weave provides minor protection against most sources of damage." icon_state = "security_poncho" item_state = "security_poncho" body_parts_covered = UPPER_TORSO|LOWER_TORSO|ARMS @@ -148,7 +148,7 @@ /obj/item/clothing/suit/armor/hos name = "armored coat" - desc = "A trench coat enhanced with a special alloy for some protection and style." + desc = "An intimidating black greatcoat reinforced with Level II plate inserts for moderate protection." icon_state = "hos" item_state = "hos" body_parts_covered = UPPER_TORSO|LOWER_TORSO|ARMS|LEGS @@ -165,7 +165,7 @@ /obj/item/clothing/suit/armor/hos/alt name = "armored trenchcoat" - desc = "A trenchcoat enhanced with a special lightweight kevlar. The epitome of tactical plainclothes." + desc = "A a stylish black trenchcoat fitted with Level II armored inserts for moderate protection without sacrificing aesthetics." icon_state = "hostrench_open" item_state = "hostrench_open" flags_inv = 0 @@ -184,7 +184,7 @@ /obj/item/clothing/suit/armor/vest/warden name = "warden's armored jacket" - desc = "An armored jacket with silver rank pips and livery." + desc = "A comfortable armored jacket fitted with Level II plate inserts for moderate protection. This one has silver livery on the shoulders to denote rank." icon_state = "warden_jacket" item_state = "armor" body_parts_covered = UPPER_TORSO|LOWER_TORSO|ARMS @@ -201,13 +201,13 @@ /obj/item/clothing/suit/armor/vest/warden/alt name = "warden's jacket" - desc = "A navy-blue armored jacket with blue shoulder designations and '/Warden/' stitched into one of the chest pockets." + desc = "A large navy-blue jacket fitted with Level II armored inserts. There are silver rank insignia on the shoulders." icon_state = "warden_jacket_alt" //Captain /obj/item/clothing/suit/armor/vest/capcarapace name = "captain's carapace" - desc = "An armored vest reinforced with ceramic plates and pauldrons to provide additional protection whilst still offering maximum mobility and flexibility. Issued only to the station's finest, although it does chafe your nipples." + desc = "A fancy blue & gold dragonscale armor vest fitted with Level III and IV armor panelling. Offers excellent protection against melee attacks, kinetic impacts, and laser discharges. " icon_state = "captain_carapace" item_state = "armor" body_parts_covered = UPPER_TORSO|LOWER_TORSO @@ -225,26 +225,26 @@ /obj/item/clothing/suit/armor/vest/capcarapace/jacket name = "captain's jacket" - desc = "A less formal jacket for everyday captain use." + desc = "A comfy semiformal jacket for the Captain on the move. Embedded kevlar weave and Level II armor panels provide moderate protection without sacrificing class." icon_state = "captain_jacket" body_parts_covered = UPPER_TORSO|LOWER_TORSO|ARMS armor = list(MELEE = 40, BULLET = 20, LASER = 25, ENERGY = 5, BOMB = 15, RAD = 0, FIRE = INFINITY, ACID = 450) /obj/item/clothing/suit/armor/vest/capcarapace/jacket/tunic name = "captain's tunic" - desc = "Worn by a Captain to show their class." + desc = "A snappy blue dress tunic for Captains of class. Kevlar weave and sewn-in Level II armor plates provide moderate protection in all areas." icon_state = "captain_tunic" /obj/item/clothing/suit/armor/vest/capcarapace/coat name = "captain's formal coat" - desc = "For when an armored vest isn't fashionable enough." + desc = "A large, fancy, and exquisately tailored dress coat for the most image-conscious of Nanotrasen Captains. Level II armor plates and impact gel panels sewn into the fabric provide light protection against most damage types." icon_state = "captain_formal" armor = list(MELEE = 35, BULLET = 15, LASER = 20, ENERGY = 5, BOMB = 10, RAD = 0, FIRE = INFINITY, ACID = 450) body_parts_covered = UPPER_TORSO|LOWER_TORSO|LEGS|ARMS /obj/item/clothing/suit/armor/vest/capcarapace/coat/white name = "captain's long white tunic" - desc = "An old style captain tunic. Makes you look and feel like you're wearing a cardboard box with arm holes cut in it but looks like it would be great for a wedding... or a funeral." + desc = "A beautiful dress white tunic for Captains of demanding taste. A mix of kevlar weave and Level II armor inserts provide basic protection against most threats." icon_state = "captain_white" // Drask look fine in the regular human version @@ -256,7 +256,7 @@ /obj/item/clothing/suit/armor/riot name = "riot suit" - desc = "A suit of armor with heavy padding to protect against melee attacks. Looks like it might impair movement." + desc = "A bulky, full-body suit of layered armor and impact cushions that provides outstanding protection against blunt trauma, fire, and corrosive substances. Much less effective against all other forms of damage, however." icon_state = "riot" item_state = "swat_suit" body_parts_covered = UPPER_TORSO|LOWER_TORSO|LEGS|FEET|ARMS|HANDS @@ -273,13 +273,13 @@ /obj/item/clothing/suit/armor/riot/sec name = "security riot suit" - desc = "A suit of armor with heavy padding to protect against melee attacks. Looks like it might impair movement. This one has security markings on it." + desc = "A full-body suit of riot gear that provides excellent protection against blunt force trauma, fire, and corrosive substances, but little protection otherwise. This suit is covered in red Security stripes." icon_state = "riot-sec" item_state = "swat_suit" /obj/item/clothing/suit/armor/riot/knight name = "plate armour" - desc = "A classic suit of plate armour, highly effective at stopping melee attacks." + desc = "A full suit of steel plate armor, it looks like it came right out of a documentary about the Middle Ages. The plating offers excellent protection against melee, and the asbestos-lined padding provides excellent protection against fire and corrosive substances, but it won't be stopping any weapon designed in the last half-millennium." icon_state = "knight_green" item_state = "knight_green" slowdown = 1 @@ -300,7 +300,7 @@ /obj/item/clothing/suit/armor/riot/knight/templar name = "crusader armour" - desc = "God wills it!" + desc = "A heavy suit of cosplay-grade armor that vaguely resembles something from a low-quality documentary about the crusades. Whilst the plating provides mediocre protection against melee attacks and little else, the asbestos-lined padding does hold up quite well to fire and corrosive substances." icon_state = "knight_templar" item_state = "knight_templar" allowed = list(/obj/item/nullrod/claymore, /obj/item/storage/bible) @@ -308,7 +308,7 @@ /obj/item/clothing/suit/armor/vest/durathread name = "durathread vest" - desc = "A vest made of durathread with strips of leather acting as trauma plates." + desc = "A comfortable and low-profile vest made of durathread, reinforced with panels of tanned leather. Offers decent protection against laser discharges, but won't be stopping a bullet any time soon." icon_state = "durathread" item_state = "durathread" strip_delay = 60 @@ -317,8 +317,8 @@ armor = list(MELEE = 10, BULLET = 5, LASER = 20, ENERGY = 5, BOMB = 10, RAD = 0, FIRE = 35, ACID = 50) /obj/item/clothing/suit/armor/bulletproof - name = "bulletproof vest" - desc = "A bulletproof vest that excels in protecting the wearer against traditional projectile weaponry and explosives to a minor extent." + name = "bulletproof armor" + desc = "A full-body suit of armor fitted with Level IV ballistic armor inserts and panelling across the body. Will stop most low-caliber kinetic projectiles and help resist the concussive force of explosions, but it does little against melee and energy attacks." icon_state = "bulletproof" item_state = "armor" blood_overlay_type = "armor" @@ -335,15 +335,15 @@ /obj/item/clothing/suit/armor/bulletproof/sec - name = "security bulletproof vest" - desc = "A bulletproof vest that excels in protecting the wearer against traditional projectile weaponry and explosives to a minor extent. This one has security markings on it." + name = "security bulletproof armor" + desc = "A full-body suit of armor fitted with Level IV ballistic inserts and panelling. Will stop most low-caliber kinetic rounds and resist the concussive force of explosions somewhat, but it does little against melee and energy attacks. This suit is covered in red Security stripes." icon_state = "bulletproof-sec" item_state = "armor" blood_overlay_type = "armor" /obj/item/clothing/suit/armor/swat name = "SWAT armor" - desc = "Tactical SWAT armor." + desc = "A large, bulky suit of tactical armor commonly used by specialized police units. Offers moderate protection in all areas. It has a surface coating that completely resists harm from fire and corrosive attacks." icon_state = "heavy" item_state = "swat_suit" body_parts_covered = UPPER_TORSO | LOWER_TORSO | LEGS | FEET | ARMS | HANDS @@ -358,7 +358,8 @@ /obj/item/clothing/suit/armor/laserproof name = "ablative armor vest" - desc = "A vest that excels in protecting the wearer against energy projectiles. Projects an energy field around the user, allowing a chance of energy projectile deflection no matter where on the user it would hit." + desc = "A high-tech armor vest specializing against energy attacks. A miniaturized energy shielding system deflects incoming shots on a short cooldown, while a reflective outer shell and \ + specialized heat dissipation materials protect against direct energy impacts. Unfortunately, it offers little in the way of defense against solid projectiles or melee weapons." icon_state = "armor_reflec" item_state = "armor_reflec" blood_overlay_type = "armor" @@ -394,7 +395,7 @@ //Reactive armor /obj/item/clothing/suit/armor/reactive name = "reactive armor" - desc = "Doesn't seem to do much for some reason." + desc = "A massive, complex, and currently entirely worthless vest that forms the basis of a reactive armor system. Requires an anomaly core to actually work." /// Is the armor turned on? var/active = FALSE /// Is the armor disabled, and prevented from reactivating temporarly? @@ -430,11 +431,11 @@ /obj/item/clothing/suit/armor/reactive/examine_more(mob/user) . = ..() - . += "Reactive armours are one of the uses that Nanotasen has found for the anomaly cores that can be recovered from the bluespace phenomina that occur in the space in orbit of Lavaland. \ - The effects of these armours can be unpredictable or undesirable in certain situations, so Nanotrasen advises only activating them when the user is in danger." + . += "Reactive armor systems are one of the uses that Nanotasen has found for the anomaly cores that can be recovered from the anomalous phenomena that occur in the area of space near Lavaland. \ + The effects of these armor units can be unpredictable or undesirable in certain situations, so Nanotrasen advises only activating them when the user is in danger." . += "" - . += "Outside of the strange effects caused by the anomaly core, the armour provides no protection against conventional attacks. \ - Nanotrasen cannot be held liable for injury and/or death due to misuse or proper operation of the reactive armour." + . += "Outside of the strange effects caused by the anomaly core, the armor provides no protection against conventional attacks. \ + Nanotrasen cannot be held liable for injury and/or death due to misuse or proper operation of the reactive armor." /obj/item/clothing/suit/armor/reactive/attack_self__legacy__attackchain(mob/user) active = !(active) @@ -506,8 +507,8 @@ //When the wearer gets hit, this armor will teleport the user a short distance away (to safety or to more danger, no one knows. That's the fun of it!) /obj/item/clothing/suit/armor/reactive/teleport - name = "reactive teleport armor" - desc = "Someone separated our Research Director from his own head!" + name = "reactive teleportation armor" + desc = "A reactive armor vest fitted with a bluespace anomaly core, allowing it to teleport its wearer away from danger. Looking directly at the core fills you with a sense of vertigo." energy_cost = 200 var/tele_range = 6 @@ -524,7 +525,7 @@ /obj/item/clothing/suit/armor/reactive/fire name = "reactive incendiary armor" - desc = "This armor uses the power of a pyro anomaly core to shoot protective jets of fire, in addition to absorbing all damage from fire." + desc = "A reactive armor vest fitted with a pyroclastic anomaly core, which sprays jets of flame when its wearer is threatened, as well as protecting the wearer from extreme heat. A gentle warmth emanates from the core." heat_protection = UPPER_TORSO | LOWER_TORSO | LEGS | FEET | ARMS | HANDS | HEAD max_heat_protection_temperature = FIRE_IMMUNITY_MAX_TEMP_PROTECT @@ -553,7 +554,7 @@ /obj/item/clothing/suit/armor/reactive/cryo name = "reactive gelidic armor" //is "gelidic" a word? probably not, but it sounds cool - desc = "This armor harnesses a cryogenic anomaly core to defend its user from the cold and attacks alike. Its unstable thermal regulation system occasionally vents gasses." + desc = "A reactive armor vest fitted with a cryogenic anomaly core, which vents supercooled gasses at threats to its wearer. A faint wind can be heard near the core." /obj/item/clothing/suit/armor/reactive/cryo/equipped(mob/user, slot) ..() @@ -602,7 +603,7 @@ /obj/item/clothing/suit/armor/reactive/stealth name = "reactive stealth armor" - desc = "This armor uses an anomaly core combined with holographic projectors to make the user invisible temporarly, and make a fake image of the user." + desc = "A reactive armor vest fitted with a vortex anomaly core, which can turns its wearer invisible at the first sign of danger. The air around the core seems to shimmer and shift." energy_cost = 200 /obj/item/clothing/suit/armor/reactive/stealth/hit_reaction(mob/living/carbon/human/owner, atom/movable/hitby, attack_text = "the attack", final_block_chance = 0, damage = 0, attack_type = MELEE_ATTACK) @@ -621,7 +622,7 @@ /obj/item/clothing/suit/armor/reactive/tesla name = "reactive tesla armor" - desc = "This armor uses the power of a flux anomaly core to protect the user in shocking ways." + desc = "A reactive armor vest fitted with an electrical anomaly core, which fires lethal bolts of electricty at threats to its wearer. The air around the core smells of ozone." /obj/item/clothing/suit/armor/reactive/tesla/hit_reaction(mob/living/carbon/human/owner, atom/movable/hitby, attack_text = "the attack", final_block_chance = 0, damage = 0, attack_type = MELEE_ATTACK) if(!active) @@ -640,7 +641,7 @@ /obj/item/clothing/suit/armor/reactive/repulse name = "reactive repulse armor" - desc = "An experimental suit of armor that violently throws back attackers with the power of a gravitational anomaly core." + desc = "A reactive armor vest fitted with a gravitational anomaly core, which violently repels threats to its wearer. The core pulses with light, akin to a heartbeat." ///How strong the reactive armor is for throwing var/repulse_power = 3 /// How far away are we finding things to throw @@ -714,7 +715,7 @@ /obj/item/clothing/suit/armor/heavy name = "heavy armor" - desc = "A heavily armored suit that protects against moderate damage." + desc = "A generic suit of heavy armor. Protects against damage, to the surprise of none." icon_state = "heavy" item_state = "swat_suit" armor = list(MELEE = 200, BULLET = 200, LASER = 50, ENERGY = 50, BOMB = INFINITY, RAD = INFINITY, FIRE = 450, ACID = 450) diff --git a/code/modules/clothing/suits/misc_suits.dm b/code/modules/clothing/suits/misc_suits.dm index c08071b58812..2aa30cefbea0 100644 --- a/code/modules/clothing/suits/misc_suits.dm +++ b/code/modules/clothing/suits/misc_suits.dm @@ -308,28 +308,13 @@ user.faction -= "carp" to_chat(user, "A sudden calm fills the gnashing void of your mind- you're alone now.") -/mob/living/carbon/human/Process_Spacemove(movement_dir = 0) - if(..()) - return TRUE - +/mob/living/carbon/human/Process_Spacemove(movement_dir = 0, continuous_move = FALSE) if(istype(wear_suit, /obj/item/clothing/suit/hooded/carp_costume/dragon)) return TRUE - //Do we have a working jetpack? - var/obj/item/tank/jetpack/thrust - if(istype(back, /obj/item/tank/jetpack)) - thrust = back - else if(istype(wear_suit, /obj/item/clothing/suit/space/hardsuit)) - var/obj/item/clothing/suit/space/hardsuit/C = wear_suit - thrust = C.jetpack - else if(ismodcontrol(back)) - var/obj/item/mod/control/C = back - thrust = locate(/obj/item/mod/module/jetpack) in C - if(thrust) - if((movement_dir || thrust.stabilizers) && thrust.allow_thrust(0.01, src)) - return TRUE if(dna.species.spec_Process_Spacemove(src)) return TRUE - return FALSE + + return ..() /obj/item/clothing/head/hooded/carp_hood/dragon name = "space carp hood" @@ -641,7 +626,7 @@ /obj/item/clothing/head/hooded/ablative name = "ablative hood" - desc = "Hood hopefully belonging to an ablative trenchcoat. Includes a flash proof visor." + desc = "A high-tech ablative hood attached to an ablative trenchcoat. Dissipates energy attacks with ease, and has an integrated flashproof visor. Entirely ineffecitve against kinetic attacks." icon_state = "ablativehood" flash_protect = FLASH_PROTECTION_FLASH flags = BLOCKHAIR @@ -652,7 +637,8 @@ /obj/item/clothing/suit/hooded/ablative name = "ablative trenchcoat" - desc = "Experimental trenchcoat specially crafted to reflect and absorb laser and disabler shots. Don't expect it to do all that much against an axe or a shotgun, however." + desc = "A cutting-edge ablative armor system developed by Nanotrasen. Miniaturized shielding systems deflect incoming energy projectiles, while prototype heatsinks and dissipation materials blunt any energy weapon that makes impact. \ + Unfortunately, if offers little to no protection against solid impacts." icon_state = "ablativecoat" w_class = WEIGHT_CLASS_NORMAL item_state = "ablativecoat" diff --git a/code/modules/events/blob/blob_mobs.dm b/code/modules/events/blob/blob_mobs.dm index 14c3cc9db61e..dac32472ac74 100644 --- a/code/modules/events/blob/blob_mobs.dm +++ b/code/modules/events/blob/blob_mobs.dm @@ -44,7 +44,7 @@ H.color = COLOR_BLACK adjustHealth(-maxHealth * 0.0125) -/mob/living/simple_animal/hostile/blob/Process_Spacemove(movement_dir = 0) +/mob/living/simple_animal/hostile/blob/Process_Spacemove(movement_dir = 0, continuous_move = FALSE) // Use any nearby blob structures to allow space moves. for(var/obj/structure/blob/B in range(1, src)) return TRUE diff --git a/code/modules/events/dust.dm b/code/modules/events/dust.dm index f4f83edc12f5..58c3f61be91e 100644 --- a/code/modules/events/dust.dm +++ b/code/modules/events/dust.dm @@ -32,41 +32,17 @@ strength = 1 life = 40 -/obj/effect/space_dust/New() +/obj/effect/space_dust/Initialize(mapload) . = ..() - var/startx = 0 - var/starty = 0 - var/endy = 0 - var/endx = 0 + ADD_TRAIT(src, TRAIT_NO_EDGE_TRANSITIONS, ROUNDSTART_TRAIT) + var/startside = pick(GLOB.cardinal) GLOB.meteor_list += src - switch(startside) - if(NORTH) - starty = world.maxy-(TRANSITIONEDGE+1) - startx = rand((TRANSITIONEDGE+1), world.maxx-(TRANSITIONEDGE+1)) - endy = TRANSITIONEDGE - endx = rand(TRANSITIONEDGE, world.maxx-TRANSITIONEDGE) - if(EAST) - starty = rand((TRANSITIONEDGE+1),world.maxy-(TRANSITIONEDGE+1)) - startx = world.maxx-(TRANSITIONEDGE+1) - endy = rand(TRANSITIONEDGE, world.maxy-TRANSITIONEDGE) - endx = TRANSITIONEDGE - if(SOUTH) - starty = (TRANSITIONEDGE+1) - startx = rand((TRANSITIONEDGE+1), world.maxx-(TRANSITIONEDGE+1)) - endy = world.maxy-TRANSITIONEDGE - endx = rand(TRANSITIONEDGE, world.maxx-TRANSITIONEDGE) - if(WEST) - starty = rand((TRANSITIONEDGE+1), world.maxy-(TRANSITIONEDGE+1)) - startx = (TRANSITIONEDGE+1) - endy = rand(TRANSITIONEDGE,world.maxy-TRANSITIONEDGE) - endx = world.maxx-TRANSITIONEDGE - goal = locate(endx, endy, 1) - src.x = startx - src.y = starty - src.z = level_name_to_num(MAIN_STATION) - walk_towards(src, goal, 1) + var/turf/start = pick_edge_loc(startside, level_name_to_num(MAIN_STATION)) + forceMove(start) + goal = pick_edge_loc(REVERSE_DIR(startside), level_name_to_num(MAIN_STATION)) + GLOB.move_manager.home_onto(src, goal, 1) /obj/effect/space_dust/Bump(atom/A) if(QDELETED(src)) @@ -88,7 +64,7 @@ life-- if(life <= 0) - walk(src, 0) + GLOB.move_manager.stop_looping(src) on_shatter(where) qdel(src) diff --git a/code/modules/events/immovable_rod.dm b/code/modules/events/immovable_rod.dm index 9bc6779e62dd..8017f6853640 100644 --- a/code/modules/events/immovable_rod.dm +++ b/code/modules/events/immovable_rod.dm @@ -15,8 +15,8 @@ In my current plan for it, 'solid' will be defined as anything with density == 1 /datum/event/immovable_rod/start() var/startside = pick(GLOB.cardinal) - var/turf/startT = spaceDebrisStartLoc(startside, level_name_to_num(MAIN_STATION)) - var/turf/endT = spaceDebrisFinishLoc(startside, level_name_to_num(MAIN_STATION)) + var/turf/startT = pick_edge_loc(startside, level_name_to_num(MAIN_STATION)) + var/turf/endT = pick_edge_loc(REVERSE_DIR(startside), level_name_to_num(MAIN_STATION)) new /obj/effect/immovablerod/event(startT, endT) /obj/effect/immovablerod diff --git a/code/modules/events/meaty_ores.dm b/code/modules/events/meaty_ores.dm index c4431b23da03..16624b38ca9d 100644 --- a/code/modules/events/meaty_ores.dm +++ b/code/modules/events/meaty_ores.dm @@ -37,3 +37,6 @@ explosion(where, 0, pick(0,1), pick(2,3), 0) else new /mob/living/simple_animal/cow(where) + +/obj/effect/space_dust/meaty/Process_Spacemove(movement_dir = 0, continuous_move = FALSE) + return TRUE diff --git a/code/modules/hallucinations/hallucinations.dm b/code/modules/hallucinations/hallucinations.dm index 9e705cc63207..9849594fbeff 100644 --- a/code/modules/hallucinations/hallucinations.dm +++ b/code/modules/hallucinations/hallucinations.dm @@ -4,7 +4,6 @@ GLOBAL_LIST_INIT(hallucinations, list( /obj/effect/hallucination/fake_danger = 10, /obj/effect/hallucination/fake_health = 15, /obj/effect/hallucination/speech = 15, - /obj/effect/hallucination/audio = 25, /obj/effect/hallucination/audio/localized = 25, /obj/effect/hallucination/trait_applier/medical_machinery = 25, /obj/effect/hallucination/examine_hallucination = 25, @@ -14,24 +13,19 @@ GLOBAL_LIST_INIT(hallucinations, list( /obj/effect/hallucination/fake_grenade/flashbang = 5, /obj/effect/hallucination/self_delusion = 5, /obj/effect/hallucination/bolts/moderate = 10, - /obj/effect/hallucination/chasms = 10, /obj/effect/hallucination/fake_alert = 10, /obj/effect/hallucination/fake_grenade = 10, /obj/effect/hallucination/gunfire = 10, /obj/effect/hallucination/plasma_flood = 10, /obj/effect/hallucination/stunprodding = 10, /obj/effect/hallucination/doppelganger = 10, - /obj/effect/hallucination/delamination_alarm = 15, - /obj/effect/hallucination/fake_item = 15, /obj/effect/hallucination/fake_weapon = 15, - /obj/effect/hallucination/husks = 15, /obj/effect/hallucination/ventpeek = 15, ), HALLUCINATE_MAJOR = list( /obj/effect/hallucination/abduction = 10, /obj/effect/hallucination/assault = 10, /obj/effect/hallucination/fake_grenade/spawner = 10, - /obj/effect/hallucination/terror_infestation = 10, /obj/effect/hallucination/loose_energy_ball = 10, /datum/hallucination_manager/blind_rush = 1, /datum/hallucination_manager/xeno_pounce = 10, diff --git a/code/modules/input/keybindings_procs.dm b/code/modules/input/keybindings_procs.dm index b5e95307f01d..f370a883e7fa 100644 --- a/code/modules/input/keybindings_procs.dm +++ b/code/modules/input/keybindings_procs.dm @@ -21,3 +21,9 @@ active_keybindings[linked_bind.binded_to] += list(linked_bind) return active_keybindings + +/client/proc/calculate_move_dir() + . = NONE + for(var/held_key in input_data.keys_held) + if(held_key in movement_kb_dirs) + . |= movement_kb_dirs[held_key] diff --git a/code/modules/mining/equipment/wormhole_jaunter.dm b/code/modules/mining/equipment/wormhole_jaunter.dm index 5195a1fdb39f..a835cc797ff4 100644 --- a/code/modules/mining/equipment/wormhole_jaunter.dm +++ b/code/modules/mining/equipment/wormhole_jaunter.dm @@ -4,7 +4,8 @@ GLOBAL_LIST_EMPTY(wormhole_effect) /**********************Jaunter**********************/ /obj/item/wormhole_jaunter name = "wormhole jaunter" - desc = "A single use device harnessing outdated wormhole technology, Nanotrasen has since turned its eyes to bluespace for more accurate teleportation. The wormholes it creates are unpleasant to travel through, to say the least.\nThanks to modifications provided by the Free Golems, this jaunter can be worn on the belt to provide protection from chasms." + desc = "A single use device harnessing outdated wormhole technology, Nanotrasen has since turned its eyes to bluespace for more accurate teleportation. \ + The wormholes it creates are unpleasant to travel through, to say the least. If attached to your belt, it'll automatically activate should you fall into a chasm." icon_state = "Jaunter" item_state = "electronic" throwforce = 0 diff --git a/code/modules/mob/dead/observer/observer_base.dm b/code/modules/mob/dead/observer/observer_base.dm index d7d10ee753df..20eb899bb9b2 100644 --- a/code/modules/mob/dead/observer/observer_base.dm +++ b/code/modules/mob/dead/observer/observer_base.dm @@ -290,7 +290,7 @@ This is the proc mobs get to turn into a ghost. Forked from ghostize due to comp return // Ghosts have no momentum, being massless ectoplasm -/mob/dead/observer/Process_Spacemove(movement_dir) +/mob/dead/observer/Process_Spacemove(movement_dir = 0, continuous_move = FALSE) return 1 /mob/dead/observer/Move(NewLoc, direct) diff --git a/code/modules/mob/dead/observer/spells.dm b/code/modules/mob/dead/observer/observer_spells.dm similarity index 100% rename from code/modules/mob/dead/observer/spells.dm rename to code/modules/mob/dead/observer/observer_spells.dm diff --git a/code/modules/mob/living/carbon/alien/humanoid/humanoid.dm b/code/modules/mob/living/carbon/alien/humanoid/humanoid.dm index 6a43c6e32487..1177124863f9 100644 --- a/code/modules/mob/living/carbon/alien/humanoid/humanoid.dm +++ b/code/modules/mob/living/carbon/alien/humanoid/humanoid.dm @@ -35,7 +35,7 @@ GLOBAL_LIST_INIT(strippable_alien_humanoid_items, create_strippable_list(list( AddComponent(/datum/component/footstep, FOOTSTEP_MOB_CLAW, 0.5, -11) AddElement(/datum/element/strippable, GLOB.strippable_alien_humanoid_items) -/mob/living/carbon/alien/humanoid/Process_Spacemove(check_drift = 0) +/mob/living/carbon/alien/humanoid/Process_Spacemove(movement_dir = 0, continuous_move = FALSE) if(..()) return TRUE return FALSE diff --git a/code/modules/mob/living/carbon/human/human_defense.dm b/code/modules/mob/living/carbon/human/human_defense.dm index f50496e4ff57..cf4816db066f 100644 --- a/code/modules/mob/living/carbon/human/human_defense.dm +++ b/code/modules/mob/living/carbon/human/human_defense.dm @@ -532,7 +532,7 @@ emp_act bloody = TRUE var/turf/location = loc if(issimulatedturf(location)) - add_splatter_floor(location, emittor_intertia = inertia_next_move > world.time ? last_movement_dir : null) + add_splatter_floor(location, emittor_intertia = last_movement_dir) if(ishuman(user)) var/mob/living/carbon/human/H = user if(get_dist(H, src) <= 1) //people with TK won't get smeared with blood diff --git a/code/modules/mob/living/carbon/human/human_mob.dm b/code/modules/mob/living/carbon/human/human_mob.dm index 3fddf689100e..a06771ff779d 100644 --- a/code/modules/mob/living/carbon/human/human_mob.dm +++ b/code/modules/mob/living/carbon/human/human_mob.dm @@ -929,7 +929,7 @@ H.UpdateAppearance() //Replacing lost organs with the species default. - temp_holder = new /mob/living/carbon/human() + temp_holder = new /mob/living/carbon/human/fake() var/list/species_organs = H.dna.species.has_organ.Copy() //Compile a list of species organs and tack on the mutantears afterward. if(H.dna.species.mutantears) species_organs["ears"] = H.dna.species.mutantears diff --git a/code/modules/mob/living/living.dm b/code/modules/mob/living/living.dm index eff680b8862c..61aa7959a246 100644 --- a/code/modules/mob/living/living.dm +++ b/code/modules/mob/living/living.dm @@ -213,8 +213,8 @@ var/current_dir if(isliving(AM)) current_dir = AM.dir - if(step(AM, t)) - step(src, t) + if(AM.Move(get_step(AM.loc, t), t, glide_size)) + Move(get_step(loc, t), t) if(current_dir) AM.setDir(current_dir) now_pushing = FALSE @@ -598,7 +598,7 @@ return return ..() -/mob/living/Move(atom/newloc, direct, movetime) +/mob/living/Move(atom/newloc, direct = 0, glide_size_override = 0, update_dir = TRUE) if(buckled && buckled.loc != newloc) //not updating position if(!buckled.anchored) return buckled.Move(newloc, direct) @@ -618,12 +618,12 @@ . = ..() if(.) step_count++ - pull_pulled(old_loc, pullee, movetime) + pull_pulled(old_loc, pullee, glide_size_override) if(s_active && !(s_active in contents) && get_turf(s_active) != get_turf(src)) //check !( s_active in contents) first so we hopefully don't have to call get_turf() so much. s_active.close(src) -/mob/living/proc/pull_pulled(turf/dest, atom/movable/pullee, movetime) +/mob/living/proc/pull_pulled(turf/dest, atom/movable/pullee, glide_size_override) if(pulling && pulling == pullee) // we were pulling a thing and didn't lose it during our move. if(pulling.anchored) stop_pulling() @@ -635,7 +635,7 @@ var/mob/living/M = pulling if(IS_HORIZONTAL(M) && !M.buckled && (prob(M.getBruteLoss() * 200 / M.maxHealth))) // So once you reach 50 brute damage you hit 100% chance to leave a blood trail for every tile you're pulled M.makeTrail(dest) - pulling.Move(dest, get_dir(pulling, dest), movetime) // the pullee tries to reach our previous position + pulling.Move(dest, get_dir(pulling, dest), glide_size_override) // the pullee tries to reach our previous position if(pulling && get_dist(src, pulling) > 1) // the pullee couldn't keep up stop_pulling() @@ -1173,10 +1173,10 @@ return return ..() -/mob/living/Moved(OldLoc, Dir, Forced = FALSE) +/mob/living/Moved(atom/old_loc, movement_dir, forced, list/old_locs, momentum_change = TRUE) . = ..() for(var/obj/O in src) - O.on_mob_move(Dir, src) + O.on_mob_move(movement_dir, src) /// Can a mob interact with the apc remotely like a pulse demon, cyborg, or AI? /mob/living/proc/can_remote_apc_interface(obj/machinery/power/apc/ourapc) diff --git a/code/modules/mob/living/silicon/robot/robot_movement.dm b/code/modules/mob/living/silicon/robot/robot_movement.dm index 4f5a17da5088..96486d798949 100644 --- a/code/modules/mob/living/silicon/robot/robot_movement.dm +++ b/code/modules/mob/living/silicon/robot/robot_movement.dm @@ -1,4 +1,4 @@ -/mob/living/silicon/robot/Process_Spacemove(movement_dir = 0) +/mob/living/silicon/robot/Process_Spacemove(movement_dir = 0, continuous_move = FALSE) if(ionpulse()) return TRUE if(..()) diff --git a/code/modules/mob/living/simple_animal/bot/bot.dm b/code/modules/mob/living/simple_animal/bot/bot.dm index f110db49ec45..2285c0fecc21 100644 --- a/code/modules/mob/living/simple_animal/bot/bot.dm +++ b/code/modules/mob/living/simple_animal/bot/bot.dm @@ -163,13 +163,13 @@ lost_target = FALSE last_target_location = get_turf(target) var/dist = get_dist(src, target) - walk_to(src, target, 1, 4) + GLOB.move_manager.move_to(src, target, 1, 4) if(get_dist(src, target) >= dist) frustration++ return if(!lost_target) - walk_to(src, 0) + GLOB.move_manager.stop_looping(src) lost_target = TRUE frustration = 0 diff --git a/code/modules/mob/living/simple_animal/bot/ed209bot.dm b/code/modules/mob/living/simple_animal/bot/ed209bot.dm index 7c3d29e71bb9..e3a63cf9dd92 100644 --- a/code/modules/mob/living/simple_animal/bot/ed209bot.dm +++ b/code/modules/mob/living/simple_animal/bot/ed209bot.dm @@ -97,7 +97,7 @@ oldtarget_name = null anchored = FALSE currently_cuffing = FALSE - walk_to(src,0) + GLOB.move_manager.stop_looping(src) set_path(null) last_found = world.time set_weapon() @@ -216,7 +216,7 @@ if(lasertag_check) icon_state = "[lasercolor]ed2090" disabled = TRUE - walk_to(src, 0) + GLOB.move_manager.stop_looping(src) target = null addtimer(CALLBACK(src, PROC_REF(unset_disabled)), 10 SECONDS) return TRUE @@ -260,7 +260,7 @@ switch(mode) if(BOT_IDLE) // idle - walk_to(src,0) + GLOB.move_manager.stop_looping(src) set_path(null) if(!lasercolor) //lasertag bots don't want to arrest anyone if(find_new_target()) @@ -271,7 +271,7 @@ if(BOT_HUNT) // hunting for perp // if can't reach perp for long enough, go idle if(frustration >= 8) - walk_to(src, 0) + GLOB.move_manager.stop_looping(src) set_path(null) back_to_idle() return @@ -395,7 +395,7 @@ return 0 /mob/living/simple_animal/bot/ed209/explode() - walk_to(src,0) + GLOB.move_manager.stop_looping(src) visible_message("[src] blows apart!") var/turf/Tsec = get_turf(src) diff --git a/code/modules/mob/living/simple_animal/bot/griefsky.dm b/code/modules/mob/living/simple_animal/bot/griefsky.dm index 7f2ce26fd65d..380840b7e1ce 100644 --- a/code/modules/mob/living/simple_animal/bot/griefsky.dm +++ b/code/modules/mob/living/simple_animal/bot/griefsky.dm @@ -110,7 +110,7 @@ switch(mode) if(BOT_IDLE) // idle icon_state = "griefsky1" - walk_to(src,0) + GLOB.move_manager.stop_looping(src) set_path(null) if(find_new_target()) return // see if any criminals are in range @@ -120,7 +120,7 @@ icon_state = spin_icon playsound(loc,'sound/effects/spinsabre.ogg',50, TRUE,-1) if(frustration >= frustration_number) // general beepsky doesn't give up so easily, jedi scum - walk_to(src,0) + GLOB.move_manager.stop_looping(src) set_path(null) back_to_idle() return @@ -182,7 +182,7 @@ return FALSE /mob/living/simple_animal/bot/secbot/griefsky/explode() - walk_to(src,0) + GLOB.move_manager.stop_looping(src) visible_message("[src] lets out a huge cough as it blows apart!") var/turf/Tsec = get_turf(src) new /obj/item/assembly/prox_sensor(Tsec) diff --git a/code/modules/mob/living/simple_animal/bot/honkbot.dm b/code/modules/mob/living/simple_animal/bot/honkbot.dm index 9c243922bed3..c3476bc8ff6b 100644 --- a/code/modules/mob/living/simple_animal/bot/honkbot.dm +++ b/code/modules/mob/living/simple_animal/bot/honkbot.dm @@ -61,7 +61,7 @@ target = null oldtarget_name = null anchored = FALSE - walk_to(src, 0) + GLOB.move_manager.stop_looping(src) last_found = world.time spam_flag = FALSE @@ -266,7 +266,7 @@ return switch(mode) if(BOT_IDLE) // idle - walk_to(src, 0) + GLOB.move_manager.stop_looping(src) if(find_new_target()) return if(!mode && auto_patrol) @@ -274,7 +274,7 @@ if(BOT_HUNT) // if can't reach perp for long enough, go idle if(frustration >= 5) //gives up easier than beepsky - walk_to(src, 0) + GLOB.move_manager.stop_looping(src) playsound(loc, 'sound/misc/sadtrombone.ogg', 25, TRUE, -1) back_to_idle() return @@ -358,7 +358,7 @@ return FALSE /mob/living/simple_animal/bot/honkbot/explode() //doesn't drop cardboard nor its assembly, since its a very frail material. - walk_to(src, 0) + GLOB.move_manager.stop_looping(src) visible_message("[src] blows apart!") var/turf/Tsec = get_turf(src) new /obj/item/bikehorn(Tsec) diff --git a/code/modules/mob/living/simple_animal/bot/secbot.dm b/code/modules/mob/living/simple_animal/bot/secbot.dm index c8909ba151ef..87b2aed467e7 100644 --- a/code/modules/mob/living/simple_animal/bot/secbot.dm +++ b/code/modules/mob/living/simple_animal/bot/secbot.dm @@ -120,7 +120,7 @@ target = null oldtarget_name = null anchored = FALSE - walk_to(src,0) + GLOB.move_manager.stop_looping(src) set_path(null) last_found = world.time @@ -315,7 +315,7 @@ switch(mode) if(BOT_IDLE) // idle - walk_to(src, 0) + GLOB.move_manager.stop_looping(src) set_path(null) if(find_new_target()) // see if any criminals are in range return @@ -326,7 +326,7 @@ // if can't reach perp for long enough, go idle if(frustration >= 8) playsound(loc, 'sound/machines/buzz-two.ogg', 25, FALSE) - walk_to(src, 0) + GLOB.move_manager.stop_looping(src) set_path(null) back_to_idle() return @@ -441,7 +441,7 @@ /mob/living/simple_animal/bot/secbot/explode() - walk_to(src,0) + GLOB.move_manager.stop_looping(src) visible_message("[src] blows apart!") var/turf/Tsec = get_turf(src) var/obj/item/secbot_assembly/Sa = new /obj/item/secbot_assembly(Tsec) diff --git a/code/modules/mob/living/simple_animal/bot/syndicate_bots.dm b/code/modules/mob/living/simple_animal/bot/syndicate_bots.dm index 291690dda330..ca2bdaa20458 100644 --- a/code/modules/mob/living/simple_animal/bot/syndicate_bots.dm +++ b/code/modules/mob/living/simple_animal/bot/syndicate_bots.dm @@ -89,7 +89,7 @@ saved_turf = current_turf switch(mode) if(BOT_IDLE) - walk_to(src,0) + GLOB.move_manager.stop_looping(src) set_path(null) if(find_new_target()) return @@ -98,7 +98,7 @@ if(BOT_HUNT) if(frustration >= 8) - walk_to(src,0) + GLOB.move_manager.stop_looping(src) set_path(null) back_to_idle() return @@ -165,7 +165,7 @@ if(!QDELETED(src)) if(depotarea) depotarea.list_remove(src, depotarea.guard_list) - walk_to(src,0) + GLOB.move_manager.stop_looping(src) visible_message("[src] blows apart!") do_sparks(3, 1, src) new /obj/effect/decal/cleanable/blood/oil(loc) @@ -195,7 +195,7 @@ /mob/living/simple_animal/bot/ed209/syndicate/speak() return -/mob/living/simple_animal/bot/ed209/syndicate/Process_Spacemove(movement_dir = 0) +/mob/living/simple_animal/bot/ed209/syndicate/Process_Spacemove(movement_dir = 0, continuous_move = FALSE) return 1 /mob/living/simple_animal/bot/ed209/syndicate/start_patrol() diff --git a/code/modules/mob/living/simple_animal/constructs.dm b/code/modules/mob/living/simple_animal/constructs.dm index dbe50369e6f4..32838493cf25 100644 --- a/code/modules/mob/living/simple_animal/constructs.dm +++ b/code/modules/mob/living/simple_animal/constructs.dm @@ -318,7 +318,7 @@ Bring those who still cling to this world of illusion back to the master so they may know Truth." -/mob/living/simple_animal/hostile/construct/harvester/Process_Spacemove(movement_dir = 0) +/mob/living/simple_animal/hostile/construct/harvester/Process_Spacemove(movement_dir = 0, continuous_move = FALSE) return TRUE diff --git a/code/modules/mob/living/simple_animal/friendly/cat.dm b/code/modules/mob/living/simple_animal/friendly/cat.dm index 430ce7d223d3..b4ce532e5bd6 100644 --- a/code/modules/mob/living/simple_animal/friendly/cat.dm +++ b/code/modules/mob/living/simple_animal/friendly/cat.dm @@ -157,7 +157,7 @@ turns_since_scan++ if(turns_since_scan > 5) - walk(src, 0) + GLOB.move_manager.stop_looping(src) turns_since_scan = 0 if((movement_target) && !(isturf(movement_target.loc) || ishuman(movement_target.loc))) movement_target = null @@ -172,7 +172,7 @@ break if(movement_target) stop_automated_movement = TRUE - walk(src, movement_target, 0, 3) + GLOB.move_manager.move_to(src, movement_target, 0, 3) /mob/living/simple_animal/pet/cat/proc_cat name = "Proc" diff --git a/code/modules/mob/living/simple_animal/friendly/dog.dm b/code/modules/mob/living/simple_animal/friendly/dog.dm index 6726f1193684..3abfbf56dc3f 100644 --- a/code/modules/mob/living/simple_animal/friendly/dog.dm +++ b/code/modules/mob/living/simple_animal/friendly/dog.dm @@ -534,7 +534,7 @@ minbodytemp = TCMB maxbodytemp = T0C + 40 -/mob/living/simple_animal/pet/dog/corgi/puppy/void/Process_Spacemove(movement_dir = 0) +/mob/living/simple_animal/pet/dog/corgi/puppy/void/Process_Spacemove(movement_dir = 0, continuous_move = FALSE) return 1 //Void puppies can navigate space. //LISA! SQUEEEEEEEEE~ diff --git a/code/modules/mob/living/simple_animal/hostile/bat.dm b/code/modules/mob/living/simple_animal/hostile/bat.dm index b51af42343dd..ce9e955292ca 100644 --- a/code/modules/mob/living/simple_animal/hostile/bat.dm +++ b/code/modules/mob/living/simple_animal/hostile/bat.dm @@ -41,7 +41,7 @@ if(istype(L)) faction += "\ref[L]" -/mob/living/simple_animal/hostile/scarybat/Process_Spacemove(check_drift = 0) +/mob/living/simple_animal/hostile/scarybat/Process_Spacemove(movement_dir = 0, continuous_move = FALSE) return ..() //No drifting in space for space carp! //original comments do not steal /mob/living/simple_animal/hostile/scarybat/AttackingTarget() diff --git a/code/modules/mob/living/simple_animal/hostile/bear.dm b/code/modules/mob/living/simple_animal/hostile/bear.dm index f87d7b54b5c2..82ddad0a60f0 100644 --- a/code/modules/mob/living/simple_animal/hostile/bear.dm +++ b/code/modules/mob/living/simple_animal/hostile/bear.dm @@ -36,7 +36,7 @@ gold_core_spawnable = HOSTILE_SPAWN footstep_type = FOOTSTEP_MOB_CLAW -/mob/living/simple_animal/hostile/bear/Process_Spacemove(movement_dir = 0) +/mob/living/simple_animal/hostile/bear/Process_Spacemove(movement_dir = 0, continuous_move = FALSE) return TRUE //No drifting in space for space bears! /mob/living/simple_animal/hostile/bear/black diff --git a/code/modules/mob/living/simple_animal/hostile/bees.dm b/code/modules/mob/living/simple_animal/hostile/bees.dm index db719c53f01b..a9f90f65648a 100644 --- a/code/modules/mob/living/simple_animal/hostile/bees.dm +++ b/code/modules/mob/living/simple_animal/hostile/bees.dm @@ -56,7 +56,7 @@ var/static/beehometypecache = typecacheof(/obj/structure/beebox) var/static/hydroponicstypecache = typecacheof(/obj/machinery/hydroponics) -/mob/living/simple_animal/hostile/poison/bees/Process_Spacemove(movement_dir = 0) +/mob/living/simple_animal/hostile/poison/bees/Process_Spacemove(movement_dir = 0, continuous_move = FALSE) return TRUE /mob/living/simple_animal/hostile/poison/bees/Initialize(mapload) diff --git a/code/modules/mob/living/simple_animal/hostile/carp.dm b/code/modules/mob/living/simple_animal/hostile/carp.dm index a4ddaf327b03..849db0310eaa 100644 --- a/code/modules/mob/living/simple_animal/hostile/carp.dm +++ b/code/modules/mob/living/simple_animal/hostile/carp.dm @@ -92,7 +92,7 @@ base_dead_overlay.appearance_flags = RESET_COLOR add_overlay(base_dead_overlay) -/mob/living/simple_animal/hostile/carp/Process_Spacemove(movement_dir = 0) +/mob/living/simple_animal/hostile/carp/Process_Spacemove(movement_dir = 0, continuous_move = FALSE) return TRUE //No drifting in space for space carp! //original comments do not steal /mob/living/simple_animal/hostile/carp/AttackingTarget() diff --git a/code/modules/mob/living/simple_animal/hostile/deathsquid.dm b/code/modules/mob/living/simple_animal/hostile/deathsquid.dm index f791a681b720..8366cd050716 100644 --- a/code/modules/mob/living/simple_animal/hostile/deathsquid.dm +++ b/code/modules/mob/living/simple_animal/hostile/deathsquid.dm @@ -34,7 +34,7 @@ -/mob/living/simple_animal/hostile/deathsquid/Process_Spacemove(movement_dir = 0) +/mob/living/simple_animal/hostile/deathsquid/Process_Spacemove(movement_dir = 0, continuous_move = FALSE) return 1 //copypasta from carp code /mob/living/simple_animal/hostile/deathsquid/ex_act(severity) diff --git a/code/modules/mob/living/simple_animal/hostile/drakehound.dm b/code/modules/mob/living/simple_animal/hostile/drakehound.dm index 61c8a2778c59..8d948385462e 100644 --- a/code/modules/mob/living/simple_animal/hostile/drakehound.dm +++ b/code/modules/mob/living/simple_animal/hostile/drakehound.dm @@ -45,7 +45,7 @@ /obj/effect/gibspawner/generic, /obj/effect/gibspawner/generic) -/mob/living/simple_animal/hostile/drakehound_breacher/Process_Spacemove(movement_dir = 0) +/mob/living/simple_animal/hostile/drakehound_breacher/Process_Spacemove(movement_dir = 0, continuous_move = FALSE) return TRUE /mob/living/simple_animal/hostile/drakehound_breacher/ListTargetsLazy() diff --git a/code/modules/mob/living/simple_animal/hostile/faithless.dm b/code/modules/mob/living/simple_animal/hostile/faithless.dm index d34557ef7199..22f4b014e19e 100644 --- a/code/modules/mob/living/simple_animal/hostile/faithless.dm +++ b/code/modules/mob/living/simple_animal/hostile/faithless.dm @@ -30,5 +30,5 @@ gold_core_spawnable = HOSTILE_SPAWN footstep_type = FOOTSTEP_MOB_SHOE -/mob/living/simple_animal/hostile/faithless/Process_Spacemove(movement_dir = 0) +/mob/living/simple_animal/hostile/faithless/Process_Spacemove(movement_dir = 0, continuous_move = FALSE) return 1 diff --git a/code/modules/mob/living/simple_animal/hostile/hellhound.dm b/code/modules/mob/living/simple_animal/hostile/hellhound.dm index d87fbc58aa05..ea7efce6bb6e 100644 --- a/code/modules/mob/living/simple_animal/hostile/hellhound.dm +++ b/code/modules/mob/living/simple_animal/hostile/hellhound.dm @@ -101,7 +101,7 @@ /mob/living/simple_animal/hostile/hellhound/greater name = "greater hellhound" - desc = "A demonic-looking black canine monster with glowing red eyes and sharp teeth. Greater hounds are far stronger than their lesser kin, and typically employed by powerful bluespace entities." + desc = "A demonic-looking black canine monster with glowing red eyes and sharp teeth. Greater hounds are far stronger than their lesser kin, and should be engaged with extreme caution." icon_state = "hellhoundgreater" icon_living = "hellhoundgreater" icon_resting = "hellhoundgreater_sit" diff --git a/code/modules/mob/living/simple_animal/hostile/megafauna/drake.dm b/code/modules/mob/living/simple_animal/hostile/megafauna/drake.dm index ef5abf4224e9..d002d09a0933 100644 --- a/code/modules/mob/living/simple_animal/hostile/megafauna/drake.dm +++ b/code/modules/mob/living/simple_animal/hostile/megafauna/drake.dm @@ -422,7 +422,7 @@ Difficulty: Medium if(!swooping) ..() -/mob/living/simple_animal/hostile/megafauna/dragon/Process_Spacemove(movement_dir = 0) +/mob/living/simple_animal/hostile/megafauna/dragon/Process_Spacemove(movement_dir = 0, continuous_move = FALSE) return 1 /obj/effect/temp_visual/lava_warning diff --git a/code/modules/mob/living/simple_animal/hostile/megafauna/legion.dm b/code/modules/mob/living/simple_animal/hostile/megafauna/legion.dm index 94e47e3e4392..809dc5eddc7e 100644 --- a/code/modules/mob/living/simple_animal/hostile/megafauna/legion.dm +++ b/code/modules/mob/living/simple_animal/hostile/megafauna/legion.dm @@ -188,7 +188,7 @@ Difficulty: Medium var/armor = M.run_armor_check(limb_to_hit, LASER) M.apply_damage(70 - ((health / maxHealth) * 20), BURN, limb_to_hit, armor) -/mob/living/simple_animal/hostile/megafauna/legion/Process_Spacemove(movement_dir = 0) +/mob/living/simple_animal/hostile/megafauna/legion/Process_Spacemove(movement_dir = 0, continuous_move = FALSE) return 1 /mob/living/simple_animal/hostile/megafauna/legion/adjustHealth(amount, updating_health = TRUE) diff --git a/code/modules/mob/living/simple_animal/hostile/pirate.dm b/code/modules/mob/living/simple_animal/hostile/pirate.dm index 3e61c8e6a03e..8ac5a8f6b401 100644 --- a/code/modules/mob/living/simple_animal/hostile/pirate.dm +++ b/code/modules/mob/living/simple_animal/hostile/pirate.dm @@ -49,7 +49,7 @@ /obj/effect/gibspawner/generic, /obj/effect/gibspawner/generic) -/mob/living/simple_animal/hostile/pirate/Process_Spacemove(movement_dir = 0) +/mob/living/simple_animal/hostile/pirate/Process_Spacemove(movement_dir = 0, continuous_move = FALSE) return TRUE /mob/living/simple_animal/hostile/pirate/ListTargetsLazy() diff --git a/code/modules/mob/living/simple_animal/hostile/retaliate/combat_drone.dm b/code/modules/mob/living/simple_animal/hostile/retaliate/combat_drone.dm index bc0df94d6242..aeb57abcae34 100644 --- a/code/modules/mob/living/simple_animal/hostile/retaliate/combat_drone.dm +++ b/code/modules/mob/living/simple_animal/hostile/retaliate/combat_drone.dm @@ -43,7 +43,7 @@ if(!has_gravity(T)) new /obj/effect/particle_effect/ion_trails(T, _dir) -/mob/living/simple_animal/hostile/malf_drone/Process_Spacemove(check_drift = 0) +/mob/living/simple_animal/hostile/malf_drone/Process_Spacemove(movement_dir = 0, continuous_move = FALSE) return 1 /mob/living/simple_animal/hostile/malf_drone/ListTargets() diff --git a/code/modules/mob/living/simple_animal/hostile/retaliate/fish.dm b/code/modules/mob/living/simple_animal/hostile/retaliate/fish.dm index c9696fd08792..edda4355d666 100644 --- a/code/modules/mob/living/simple_animal/hostile/retaliate/fish.dm +++ b/code/modules/mob/living/simple_animal/hostile/retaliate/fish.dm @@ -85,7 +85,7 @@ icon_living = "koi[koinum]" icon_dead = "koi[koinum]-dead" -/mob/living/simple_animal/hostile/retaliate/carp/koi/Process_Spacemove(movement_dir) +/mob/living/simple_animal/hostile/retaliate/carp/koi/Process_Spacemove(movement_dir = 0, continuous_move = FALSE) return TRUE /mob/living/simple_animal/hostile/retaliate/carp/koi/honk diff --git a/code/modules/mob/living/simple_animal/hostile/retaliate/undead.dm b/code/modules/mob/living/simple_animal/hostile/retaliate/undead.dm index da8df5e98d74..f67d27cdd211 100644 --- a/code/modules/mob/living/simple_animal/hostile/retaliate/undead.dm +++ b/code/modules/mob/living/simple_animal/hostile/retaliate/undead.dm @@ -37,7 +37,7 @@ initial_traits = list(TRAIT_FLYING) -/mob/living/simple_animal/hostile/retaliate/ghost/Process_Spacemove(check_drift = 0) +/mob/living/simple_animal/hostile/retaliate/ghost/Process_Spacemove(movement_dir = 0, continuous_move = FALSE) return 1 /mob/living/simple_animal/hostile/retaliate/ghost/Life(seconds, times_fired) @@ -92,7 +92,7 @@ deathmessage = null gold_core_spawnable = NO_SPAWN -/mob/living/simple_animal/hostile/retaliate/skeleton/warden/Process_Spacemove(movement_dir) +/mob/living/simple_animal/hostile/retaliate/skeleton/warden/Process_Spacemove(movement_dir = 0, continuous_move = FALSE) return TRUE /mob/living/simple_animal/hostile/skeleton/angered_warden @@ -113,7 +113,7 @@ loot = list(/obj/effect/decal/remains/human, /obj/item/clothing/head/warden, /obj/item/card/sec_shuttle_ruin) gold_core_spawnable = NO_SPAWN -/mob/living/simple_animal/hostile/skeleton/angered_warden/Process_Spacemove(movement_dir) +/mob/living/simple_animal/hostile/skeleton/angered_warden/Process_Spacemove(movement_dir = 0, continuous_move = FALSE) return TRUE /mob/living/simple_animal/hostile/retaliate/zombie diff --git a/code/modules/mob/living/simple_animal/hostile/syndicate_mobs.dm b/code/modules/mob/living/simple_animal/hostile/syndicate_mobs.dm index bef98567bab7..21233ac89e42 100644 --- a/code/modules/mob/living/simple_animal/hostile/syndicate_mobs.dm +++ b/code/modules/mob/living/simple_animal/hostile/syndicate_mobs.dm @@ -283,7 +283,7 @@ alert_on_shield_breach = TRUE loot = list(/obj/effect/mob_spawn/human/corpse/syndicatequartermaster, /obj/effect/decal/cleanable/blood/innards, /obj/effect/decal/cleanable/blood, /obj/effect/gibspawner/generic, /obj/effect/gibspawner/generic) -/mob/living/simple_animal/hostile/syndicate/melee/autogib/depot/armory/Process_Spacemove(movement_dir = 0) +/mob/living/simple_animal/hostile/syndicate/melee/autogib/depot/armory/Process_Spacemove(movement_dir = 0, continuous_move = FALSE) return TRUE // he should be able to chase us in space /mob/living/simple_animal/hostile/syndicate/melee/autogib/depot/armory/Initialize(mapload) @@ -334,7 +334,7 @@ alert_on_timeout = FALSE // So random fauna doesn't make depot explode. loot = list() // Explodes, doesn't drop loot. -/mob/living/simple_animal/hostile/syndicate/melee/autogib/depot/space/Process_Spacemove(movement_dir = 0) +/mob/living/simple_animal/hostile/syndicate/melee/autogib/depot/space/Process_Spacemove(movement_dir = 0, continuous_move = FALSE) return TRUE /mob/living/simple_animal/hostile/syndicate/melee/autogib/depot/space/death() @@ -357,7 +357,7 @@ /obj/effect/gibspawner/generic, /obj/effect/gibspawner/generic) -/mob/living/simple_animal/hostile/syndicate/melee/space/Process_Spacemove(movement_dir = 0) +/mob/living/simple_animal/hostile/syndicate/melee/space/Process_Spacemove(movement_dir = 0, continuous_move = FALSE) return TRUE /mob/living/simple_animal/hostile/syndicate/ranged @@ -384,7 +384,7 @@ /obj/effect/gibspawner/generic) -/mob/living/simple_animal/hostile/syndicate/ranged/space/Process_Spacemove(movement_dir = 0) +/mob/living/simple_animal/hostile/syndicate/ranged/space/Process_Spacemove(movement_dir = 0, continuous_move = FALSE) return TRUE /mob/living/simple_animal/hostile/syndicate/ranged/space/autogib diff --git a/code/modules/mob/living/simple_animal/hostile/terror_spiders/actions.dm b/code/modules/mob/living/simple_animal/hostile/terror_spiders/actions.dm index 9f0bf777ef63..0eb0e4b3ad81 100644 --- a/code/modules/mob/living/simple_animal/hostile/terror_spiders/actions.dm +++ b/code/modules/mob/living/simple_animal/hostile/terror_spiders/actions.dm @@ -257,7 +257,7 @@ busy = SPINNING_COCOON visible_message("[src] begins to secrete a sticky substance around [cocoon_target].") stop_automated_movement = TRUE - walk(src,0) + GLOB.move_manager.stop_looping(src) if(do_after(src, 40, target = cocoon_target.loc)) if(busy == SPINNING_COCOON) if(cocoon_target && isturf(cocoon_target.loc) && get_dist(src,cocoon_target) <= 1) diff --git a/code/modules/mob/living/simple_animal/hostile/terror_spiders/reproduction.dm b/code/modules/mob/living/simple_animal/hostile/terror_spiders/reproduction.dm index a5474f7f6e1a..c242175fc0d0 100644 --- a/code/modules/mob/living/simple_animal/hostile/terror_spiders/reproduction.dm +++ b/code/modules/mob/living/simple_animal/hostile/terror_spiders/reproduction.dm @@ -150,7 +150,7 @@ new_area.Entered(src) else frustration++ - walk_to(src, entry_vent, 1) + GLOB.move_manager.move_to(src, entry_vent, 1) if(frustration > 2) entry_vent = null else if(prob(33)) @@ -165,7 +165,7 @@ for(var/obj/machinery/atmospherics/unary/vent_pump/v in view(7,src)) if(!v.welded) entry_vent = v - walk_to(src, entry_vent, 1) + GLOB.move_manager.move_to(src, entry_vent, 1) break diff --git a/code/modules/mob/living/simple_animal/hostile/terror_spiders/white.dm b/code/modules/mob/living/simple_animal/hostile/terror_spiders/white.dm index 5b55bdf28eb4..fcb808b41685 100644 --- a/code/modules/mob/living/simple_animal/hostile/terror_spiders/white.dm +++ b/code/modules/mob/living/simple_animal/hostile/terror_spiders/white.dm @@ -48,7 +48,7 @@ new /obj/item/organ/internal/body_egg/terror_eggs(L) if(!ckey) LoseTarget() - walk_away(src,L,2,1) + GLOB.move_manager.move_away(src,L,2,1) /proc/IsTSInfected(mob/living/carbon/C) // Terror AI requires this if(C.get_int_organ(/obj/item/organ/internal/body_egg)) diff --git a/code/modules/mob/living/simple_animal/shade.dm b/code/modules/mob/living/simple_animal/shade.dm index 260c85782487..89e82885dd5d 100644 --- a/code/modules/mob/living/simple_animal/shade.dm +++ b/code/modules/mob/living/simple_animal/shade.dm @@ -40,7 +40,7 @@ else ..() -/mob/living/simple_animal/shade/Process_Spacemove() +/mob/living/simple_animal/shade/Process_Spacemove(movement_dir = 0, continuous_move = FALSE) return TRUE /mob/living/simple_animal/shade/holy diff --git a/code/modules/mob/living/simple_animal/simple_animal.dm b/code/modules/mob/living/simple_animal/simple_animal.dm index 77f3a594b590..076f4c8ea7aa 100644 --- a/code/modules/mob/living/simple_animal/simple_animal.dm +++ b/code/modules/mob/living/simple_animal/simple_animal.dm @@ -167,7 +167,7 @@ /mob/living/simple_animal/Destroy() /// We need to clear the reference to where we're walking to properly GC - walk_to(src, 0) + GLOB.move_manager.stop_looping(src) QDEL_NULL(pcollar) for(var/datum/action/innate/hide/hide in actions) hide.Remove(src) @@ -627,7 +627,7 @@ /mob/living/simple_animal/Login() ..() - walk(src, 0) // if mob is moving under ai control, then stop AI movement + GLOB.move_manager.stop_looping(src) // if mob is moving under ai control, then stop AI movement /mob/living/simple_animal/proc/npc_safe(mob/user) return FALSE diff --git a/code/modules/mob/living/simple_animal/slime/slime_mob.dm b/code/modules/mob/living/simple_animal/slime/slime_mob.dm index 9ca33b23d694..a8d58bc31919 100644 --- a/code/modules/mob/living/simple_animal/slime/slime_mob.dm +++ b/code/modules/mob/living/simple_animal/slime/slime_mob.dm @@ -223,7 +223,7 @@ Atkcool = TRUE addtimer(VARSET_CALLBACK(src, Atkcool, FALSE), 4.5 SECONDS) -/mob/living/simple_animal/slime/Process_Spacemove(movement_dir = 0) +/mob/living/simple_animal/slime/Process_Spacemove(movement_dir = 0, continuous_move = FALSE) return 2 /mob/living/simple_animal/slime/get_status_tab_items() diff --git a/code/modules/mob/mob.dm b/code/modules/mob/mob.dm index 72be8b5800bb..0d33bcfa9d6a 100644 --- a/code/modules/mob/mob.dm +++ b/code/modules/mob/mob.dm @@ -793,10 +793,10 @@ GLOBAL_LIST_INIT(slot_equipment_priority, list( \ /mob/proc/print_flavor_text(shrink = TRUE) if(flavor_text && flavor_text != "") var/msg = dna?.flavor_text ? replacetext(dna.flavor_text, "\n", " ") : replacetext(flavor_text, "\n", " ") - if(length(msg) <= 40 || !shrink) + if(length(msg) <= MAX_FLAVORTEXT_PRINT || !shrink) return "[msg]" // There is already encoded by tgui_input else - return "[copytext_preserve_html(msg, 1, 37)]... More..." + return "[copytext_preserve_html(msg, 1, MAX_FLAVORTEXT_PRINT - 3)]... More..." /mob/proc/is_dead() return stat == DEAD diff --git a/code/modules/mob/mob_grab.dm b/code/modules/mob/mob_grab.dm index 99cf29d37794..31632e82cf61 100644 --- a/code/modules/mob/mob_grab.dm +++ b/code/modules/mob/mob_grab.dm @@ -47,6 +47,7 @@ affecting.grabbed_by += src RegisterSignal(affecting, COMSIG_MOVABLE_MOVED, PROC_REF(grab_moved)) RegisterSignal(assailant, COMSIG_MOVABLE_MOVED, PROC_REF(pull_grabbed)) + RegisterSignal(assailant, COMSIG_MOVABLE_UPDATE_GLIDE_SIZE, PROC_REF(on_update_glide_size)) hud = new /atom/movable/screen/grab(src) hud.icon_state = "reinforce" @@ -74,13 +75,21 @@ affecting.grabbed_by -= src affecting = null if(assailant) - UnregisterSignal(assailant, COMSIG_MOVABLE_MOVED) + UnregisterSignal(assailant, list( + COMSIG_MOVABLE_MOVED, + COMSIG_MOVABLE_UPDATE_GLIDE_SIZE, + )) if(assailant.client) assailant.client.screen -= hud assailant = null + QDEL_NULL(hud) return ..() +/obj/item/grab/proc/on_update_glide_size(mob/living/grabber, new_size) + if(affecting && grabber == assailant && affecting != assailant) + affecting.set_glide_size(new_size) + /obj/item/grab/proc/pull_grabbed(mob/user, turf/old_turf, direct, forced) SIGNAL_HANDLER if(assailant.moving_diagonally == FIRST_DIAG_STEP) //we dont want to do anything in the middle of diagonal step @@ -88,11 +97,8 @@ if(!assailant.Adjacent(old_turf)) qdel(src) return - var/list/grab_states_not_moving = list(GRAB_KILL, GRAB_NECK) //states of grab when we dont need affecting to be moved by himself - var/assailant_glide_speed = TICKS2DS(world.icon_size / assailant.glide_size) - if(state in grab_states_not_moving) - affecting.glide_for(assailant_glide_speed) - else if(get_turf(affecting) != old_turf) + + if(get_turf(affecting) != old_turf) var/possible_dest = list() var/list/mobs_do_not_move = list() // those are mobs we shouldnt move while we're going to new position var/list/dest_1_sort = list() // just better dest to be picked first @@ -131,7 +137,7 @@ if(get_turf(affecting) == dest) success_move = TRUE continue - if(affecting.Move(dest, get_dir(affecting, dest), assailant_glide_speed)) + if(affecting.Move(dest, get_dir(affecting, dest), glide_size)) success_move = TRUE break continue diff --git a/code/modules/mob/mob_movement.dm b/code/modules/mob/mob_movement.dm index 80254530dca2..2f625649540c 100644 --- a/code/modules/mob/mob_movement.dm +++ b/code/modules/mob/mob_movement.dm @@ -47,7 +47,7 @@ #define CONFUSION_MAX 80 SECONDS -/client/Move(n, direct) +/client/Move(new_loc, direct) if(world.time < move_delay) return @@ -59,7 +59,7 @@ if(!mob || !mob.loc) return 0 - if(!n || !direct) // why did we never check this before? + if(!new_loc || !direct) // why did we never check this before? return FALSE if(mob.notransform) @@ -72,7 +72,7 @@ return Move_object(direct) if(!isliving(mob)) - return mob.Move(n, direct) + return mob.Move(new_loc, direct) if(mob.stat == DEAD) mob.ghostize() @@ -91,7 +91,7 @@ if(mob.remote_control) //we're controlling something, our movement is relayed to it return mob.remote_control.relaymove(mob, direct) - if(is_ai(mob)) + if(is_ai(mob)) var/mob/living/silicon/ai/ai = mob var/mob/camera/eye/ai/eye = ai.eyeobj if(istype(eye) && !istype(ai.remote_control)) @@ -122,6 +122,9 @@ if(!mob.Process_Spacemove(direct)) return 0 + if(SEND_SIGNAL(mob, COMSIG_MOB_CLIENT_PRE_MOVE, args) & COMSIG_MOB_CLIENT_BLOCK_PRE_MOVE) + return FALSE + if(mob.restrained()) // Why being pulled while cuffed prevents you from moving for(var/mob/M in orange(1, mob)) if(M.pulling == mob) @@ -132,20 +135,28 @@ else M.stop_pulling() + // We are now going to move + var/add_delay = mob.movement_delay() + + if(locate(/obj/item/grab, mob)) + if(!isalienhunter(mob)) // i hate grab code + add_delay += 7 + + var/new_glide_size = DELAY_TO_GLIDE_SIZE(add_delay * ((NSCOMPONENT(direct) && EWCOMPONENT(direct)) ? sqrt(2) : 1)) + mob.set_glide_size(new_glide_size) // set it now in case of pulled objects - var/delay = mob.movement_delay() + //If the move was recent, count using old_move_delay + //We want fractional behavior and all if(old_move_delay + world.tick_lag > world.time) + //Yes this makes smooth movement stutter if add_delay is too fractional + //Yes this is better then the alternative move_delay = old_move_delay else move_delay = world.time - mob.last_movement = world.time - delay = TICKS2DS(-round(-(DS2TICKS(delay)))) //Rounded to the next tick in equivalent ds - - - if(locate(/obj/item/grab, mob)) - if(!isalienhunter(mob)) // i hate grab code - delay += 7 + //Basically an optional override for our glide size + //Sometimes you want to look like you're moving with a delay you don't actually have yet + visual_delay = 0 if(istype(living_mob)) var/newdir = NONE @@ -158,7 +169,7 @@ newdir = angle2dir(dir2angle(direct) + pick(45, -45)) if(newdir) direct = newdir - n = get_step(mob, direct) + new_loc = get_step(mob, direct) mob.last_movement_dir = direct @@ -166,18 +177,26 @@ if(mob.pulling) prev_pulling_loc = mob.pulling.loc - if(!(direct & (direct - 1))) // cardinal direction - . = mob.SelfMove(n, direct, delay) - else // diagonal movements take longer - var/diag_delay = delay * SQRT_2 - . = mob.SelfMove(n, direct, diag_delay) - if(mob.loc == n) + . = ..() + + if(mob.loc == new_loc) + mob.last_movement = world.time + if(IS_DIR_DIAGONAL(direct)) // only incur the extra delay if the move was *actually* diagonal // There would be a bit of visual jank if we try to walk diagonally next to a wall // and the move ends up being cardinal, rather than diagonal, // but that's better than it being jank on every *successful* diagonal move. - delay = diag_delay - move_delay += delay + add_delay *= sqrt(2) + + var/after_glide = 0 + if(visual_delay) + after_glide = visual_delay + else + after_glide = DELAY_TO_GLIDE_SIZE(add_delay) + + mob.set_glide_size(after_glide) + + move_delay += add_delay if(mob.pulledby) mob.pulledby.stop_pulling() @@ -193,9 +212,6 @@ #undef CONFUSION_MAX -/mob/proc/SelfMove(turf/n, direct, movetime) - return Move(n, direct, movetime) - ///Process_Grab() ///Called by client/Move() ///Checks to see if you are being grabbed and if so attemps to break it @@ -303,46 +319,76 @@ return TRUE -///Process_Spacemove -///Called by /client/Move() -///For moving in space -///Return 1 for movement 0 for none -/mob/Process_Spacemove(movement_dir = 0) +/** + * Handles mob/living movement in space (or no gravity) + * + * Called by /client/Move() + * + * return TRUE for movement or FALSE for none + */ +/mob/Process_Spacemove(movement_dir = 0, continuous_move = FALSE) if(..()) - return 1 - var/atom/movable/backup = get_spacemove_backup(movement_dir) - if(backup) - if(istype(backup) && movement_dir && !backup.anchored) - var/opposite_dir = turn(movement_dir, 180) - if(backup.newtonian_move(opposite_dir)) //You're pushing off something movable, so it moves - to_chat(src, "You push off of [backup] to propel yourself.") - return 1 - return 0 + return TRUE + + // TODO: if(buckled) may belong here -/mob/get_spacemove_backup(movement_dir) - for(var/A in orange(1, get_turf(src))) - if(isarea(A)) + var/atom/movable/backup = get_spacemove_backup(movement_dir, continuous_move) + if(!backup) + return FALSE + + if(continuous_move || !istype(backup) || !movement_dir || backup.anchored) + return TRUE + + var/opposite_dir = turn(movement_dir, 180) + if(backup.newtonian_move(opposite_dir)) //You're pushing off something movable, so it moves + to_chat(src, "You push off of [backup] to propel yourself.") + return TRUE + +/** + * Finds a target near a mob that is viable for pushing off when moving. + * Takes the intended movement direction as input, alongside if the context is checking if we're allowed to continue drifting + */ +/mob/get_spacemove_backup(moving_direction, continuous_move) + for(var/atom/pushover as anything in range(1, get_turf(src))) + if(pushover == src) continue - else if(isturf(A)) - var/turf/turf = A + if(isarea(pushover)) + continue + if(isturf(pushover)) + var/turf/turf = pushover if(isspaceturf(turf)) continue if(!turf.density && !mob_negates_gravity()) continue - return A - else - var/atom/movable/AM = A - if(AM == buckled) //Kind of unnecessary but let's just be sure + return pushover + + var/atom/movable/rebound = pushover + if(rebound == buckled) + continue + if(ismob(rebound)) + var/mob/lover = rebound + if(lover.buckled) continue - if(!AM.CanPass(src) || AM.density) - if(AM.anchored) - return AM - if(pulling == AM) - continue - if(get_turf(AM) == get_step(get_turf(src), movement_dir)) // No pushing off objects in front of you, while simultaneously pushing them fowards to go faster in space. - continue - . = AM + var/pass_allowed = rebound.CanPass(src, get_dir(rebound, src)) + if(!rebound.density && pass_allowed) + continue + //Sometime this tick, this pushed off something. Doesn't count as a valid pushoff target + if(rebound.last_pushoff == world.time) + continue + if(continuous_move && !pass_allowed) + var/datum/move_loop/move/rebound_engine = GLOB.move_manager.processing_on(rebound, SSspacedrift) + // If you're moving toward it and you're both going the same direction, stop + if(moving_direction == get_dir(src, pushover) && rebound_engine && moving_direction == rebound_engine.direction) + continue + else if(!pass_allowed) + if(moving_direction == get_dir(src, pushover)) // Can't push "off" of something that you're walking into + continue + if(rebound.anchored) + return rebound + if(pulling == rebound) + continue + return rebound /mob/proc/mob_has_gravity(turf/T) return has_gravity(src, T) @@ -350,35 +396,51 @@ /mob/proc/mob_negates_gravity() return 0 -/mob/proc/Move_Pulled(atom/A) - if(HAS_TRAIT(src, TRAIT_CANNOT_PULL) || restrained() || !pulling) - return - if(pulling.anchored || pulling.move_resist > move_force || !pulling.Adjacent(src)) +/atom/movable/proc/Move_Pulled(atom/moving_atom) + if(!pulling) + return FALSE + if(pulling.anchored || pulling.move_resist > move_force || !pulling.Adjacent(src, src, pulling)) stop_pulling() - return + return FALSE if(isliving(pulling)) - var/mob/living/L = pulling - if(L.buckled && L.buckled.buckle_prevents_pull) //if they're buckled to something that disallows pulling, prevent it + var/mob/living/pulling_mob = pulling + if(pulling_mob.buckled && pulling_mob.buckled.buckle_prevents_pull) //if they're buckled to something that disallows pulling, prevent it stop_pulling() - return - if(A == loc && pulling.density) + return FALSE + if(moving_atom == loc && pulling.density) + return FALSE + var/move_dir = get_dir(pulling.loc, moving_atom) + if(!Process_Spacemove(move_dir)) + return FALSE + if(!move_dir) + return FALSE + pulling.Move(get_step(pulling.loc, move_dir), move_dir, glide_size) + return TRUE + +/mob/living/Move_Pulled(atom/moving_atom) + . = ..() + if(!. || !isliving(moving_atom)) return - if(!Process_Spacemove(get_dir(pulling.loc, A))) + if(!Process_Spacemove(get_dir(pulling.loc, moving_atom))) return if(src in pulling.contents) return - var/target_turf = get_step(pulling, get_dir(pulling.loc, A)) + var/target_turf = get_step(pulling, get_dir(pulling.loc, moving_atom)) if(get_dist(target_turf, loc) > 1) // Make sure the turf we are trying to pull to is adjacent to the user. return // We do not use Adjacent() here because it checks if there are dense objects in the way, making it impossible to move an object to the side if we're blocked on both sides. + var/move_dir = get_dir(pulling.loc, moving_atom) if(ismob(pulling)) var/mob/M = pulling var/atom/movable/t = M.pulling M.stop_pulling() - . = step(pulling, get_dir(pulling.loc, A)) // we set the return value to step here, if we don't having someone buckled in to a chair and being pulled won't let them be unbuckeled + + // we set the return value to step here, if we don't having someone + // buckled in to a chair and being pulled won't let them be unbuckeled + . = pulling.Move(get_step(pulling.loc, moving_atom), move_dir, glide_size) if(M) M.start_pulling(t) else - . = step(pulling, get_dir(pulling.loc, A)) + . = pulling.Move(get_step(pulling.loc, moving_atom), move_dir, glide_size) /mob/proc/update_gravity(has_gravity) return diff --git a/code/modules/mod/mod_control.dm b/code/modules/mod/mod_control.dm index 58d274876255..2b12e936bd31 100644 --- a/code/modules/mod/mod_control.dm +++ b/code/modules/mod/mod_control.dm @@ -87,8 +87,6 @@ var/emp_proof = FALSE /// List of overlays the mod has. Needs to be cut onremoval / module deactivation var/list/mod_overlays = list() - /// Is the jetpack on so we should make ion effects? - var/jetpack_active = FALSE /// Cham option for when the cham module is installed. var/datum/action/item_action/chameleon_change/modsuit/chameleon_action /// Is the control unit disquised? @@ -241,13 +239,6 @@ if(slot == ITEM_SLOT_BACK) return TRUE -/obj/item/mod/control/on_mob_move(direction, mob/user) - if(!jetpack_active || !isturf(user.loc)) - return - var/turf/T = get_step(src, REVERSE_DIR(direction)) - if(!has_gravity(T)) - new /obj/effect/particle_effect/ion_trails(T, direction) - /obj/item/mod/control/Moved(atom/old_loc, movement_dir, forced, list/old_locs, momentum_change = TRUE) . = ..() if(!wearer || old_loc != wearer || loc == wearer) diff --git a/code/modules/mod/mod_theme.dm b/code/modules/mod/mod_theme.dm index a78287e26c02..69c37d19dfa7 100644 --- a/code/modules/mod/mod_theme.dm +++ b/code/modules/mod/mod_theme.dm @@ -553,7 +553,7 @@ ) /obj/item/mod/armor/mod_theme_rescue - armor = list(MELEE = 20, BULLET = 20, LASER = 5, ENERGY = 5, BOMB = 10, RAD = 50, FIRE = 150, ACID = 150) //Extra melee / bullet armor for if they get caught in a fight. Of course, no laser armor. + armor = list(MELEE = 20, BULLET = 20, LASER = 5, ENERGY = 5, BOMB = 10, RAD = 250, FIRE = 150, ACID = 150) //Extra melee / bullet armor for if they get caught in a fight. Of course, no laser armor. /datum/mod_theme/research name = "'Minerva' research" diff --git a/code/modules/mod/modules/_modules.dm b/code/modules/mod/modules/_modules.dm index 845c719aaa0d..7c2e568591ca 100644 --- a/code/modules/mod/modules/_modules.dm +++ b/code/modules/mod/modules/_modules.dm @@ -106,7 +106,7 @@ if(!mod.active || mod.activating || !mod.get_charge()) to_chat(mod.wearer, "Module is unpowered!") return FALSE - if(SEND_SIGNAL(src, COMSIG_MODULE_TRIGGERED) & MOD_ABORT_USE) + if(SEND_SIGNAL(src, COMSIG_MODULE_TRIGGERED, mod.wearer) & MOD_ABORT_USE) return FALSE if(module_type == MODULE_ACTIVE) if(mod.selected_module && !mod.selected_module.on_deactivation(display_message = FALSE)) @@ -157,7 +157,7 @@ else if(display_message) to_chat(mod.wearer, "[src] deactivated.") //mod.wearer.update_clothing(mod.slot_flags) - SEND_SIGNAL(src, COMSIG_MODULE_DEACTIVATED) + SEND_SIGNAL(src, COMSIG_MODULE_DEACTIVATED, mod.wearer) mod.update_mod_overlays() return TRUE @@ -169,7 +169,7 @@ if(!check_power(use_power_cost)) to_chat(mod.wearer, "Module costs too much power to use!") return FALSE - if(SEND_SIGNAL(src, COMSIG_MODULE_TRIGGERED) & MOD_ABORT_USE) + if(SEND_SIGNAL(src, COMSIG_MODULE_TRIGGERED, mod.wearer) & MOD_ABORT_USE) return FALSE COOLDOWN_START(src, cooldown_timer, cooldown_time) //addtimer(CALLBACK(mod.wearer, TYPE_PROC_REF(/mob, update_clothing), mod.slot_flags), cooldown_time+1) //need to run it a bit after the cooldown starts to avoid conflicts diff --git a/code/modules/mod/modules/modules_general.dm b/code/modules/mod/modules/modules_general.dm index 3ef82f70ca50..dcc96abce8bf 100644 --- a/code/modules/mod/modules/modules_general.dm +++ b/code/modules/mod/modules/modules_general.dm @@ -128,40 +128,51 @@ overlay_state_inactive = "module_jetpack" overlay_state_active = "module_jetpack_on" /// Do we stop the wearer from gliding in space. - var/stabilizers = FALSE + var/stabilize = FALSE + var/thrust_callback -/obj/item/mod/module/jetpack/proc/set_stabilizers(new_stabilizers) - if(stabilizers == new_stabilizers) - return - stabilizers = new_stabilizers +/obj/item/mod/module/jetpack/Initialize(mapload) + . = ..() + thrust_callback = CALLBACK(src, PROC_REF(allow_thrust)) + configure_jetpack(stabilize) + +/obj/item/mod/module/jetpack/Destroy() + thrust_callback = null + return ..() + +/** + * configures/re-configures the jetpack component + * + * Arguments + * stabilize - Should this jetpack be stabalized + */ +/obj/item/mod/module/jetpack/proc/configure_jetpack(stabilize) + src.stabilize = stabilize + + AddComponent( \ + /datum/component/jetpack, \ + src.stabilize, \ + COMSIG_MODULE_TRIGGERED, \ + COMSIG_MODULE_DEACTIVATED, \ + MOD_ABORT_USE, \ + thrust_callback, \ + /datum/effect_system/trail_follow/ion/grav_allowed \ + ) /obj/item/mod/module/jetpack/get_configuration() . = ..() - .["stabilizers"] = add_ui_configuration("Stabilizers", "bool", stabilizers) + .["stabilizers"] = add_ui_configuration("Stabilizers", "bool", stabilize) /obj/item/mod/module/jetpack/configure_edit(key, value) switch(key) if("stabilizers") - set_stabilizers(value) + configure_jetpack(value) /obj/item/mod/module/jetpack/proc/allow_thrust() - if(!active) - return if(!drain_power(use_power_cost)) return FALSE return TRUE -/obj/item/mod/module/jetpack/proc/get_user() - return mod.wearer - -/obj/item/mod/module/jetpack/on_activation() - . = ..() - mod.jetpack_active = TRUE - -/obj/item/mod/module/jetpack/on_deactivation(display_message, deleting) - . = ..() - mod.jetpack_active = FALSE - /obj/item/mod/module/jetpack/advanced name = "MOD advanced ion jetpack module" desc = "An improvement on the previous model of electric thrusters. This one achieves better efficency through \ diff --git a/code/modules/power/engines/singularity/singularity.dm b/code/modules/power/engines/singularity/singularity.dm index 1d51905da0a8..a5931a20ae3f 100644 --- a/code/modules/power/engines/singularity/singularity.dm +++ b/code/modules/power/engines/singularity/singularity.dm @@ -107,7 +107,7 @@ GLOBAL_VAR_INIT(global_singulo_id, 1) B.remove(C) qdel(B) -/obj/singularity/Process_Spacemove() //The singularity stops drifting for no man! +/obj/singularity/Process_Spacemove(movement_dir = 0, continuous_move = FALSE) //The singularity stops drifting for no man! return 0 /obj/singularity/blob_act(obj/structure/blob/B) diff --git a/code/modules/power/engines/tesla/energy_ball.dm b/code/modules/power/engines/tesla/energy_ball.dm index b7a012e9c8aa..e5d0c22bc8c4 100644 --- a/code/modules/power/engines/tesla/energy_ball.dm +++ b/code/modules/power/engines/tesla/energy_ball.dm @@ -137,7 +137,7 @@ // MORE POWER movement_beam(move_target, 1 SECONDS) sleep(0.5 SECONDS) - walk_towards(src, move_target, 0, 10) + GLOB.move_manager.home_onto(src, move_target, 0, 10) /obj/singularity/energy_ball/proc/on_atom_entered(datum/source, atom/movable/entered) var/mob/living/living_entered = entered diff --git a/code/modules/projectiles/ammunition/magazines.dm b/code/modules/projectiles/ammunition/magazines.dm index 1a02c79f3552..be5694f1bf67 100644 --- a/code/modules/projectiles/ammunition/magazines.dm +++ b/code/modules/projectiles/ammunition/magazines.dm @@ -580,7 +580,8 @@ /// Used by red ERT. Keeps the size for them /obj/item/ammo_box/magazine/laser/ert name = "compact laser carbine projector magazine" - desc = "By use of bluespace technology, the ammo casings are stored in a pocket dimension, saving on space and making them EMP proof." + desc = "An ultra-compact magazine incorporating experimental bluespace technology to hold 20 rounds in a mag the size of a cigarette lighter, while keeping them safe from EMPs. Each magazine costs as much as 5 of the carbines that use it, \ + but nobody's accused NT budget allocation of being practical before." w_class = WEIGHT_CLASS_TINY /obj/item/ammo_box/magazine/laser/ert/emp_act(severity) diff --git a/code/modules/projectiles/guns/energy/telegun.dm b/code/modules/projectiles/guns/energy/telegun.dm index e0f6359abfd5..042ed7036b61 100644 --- a/code/modules/projectiles/guns/energy/telegun.dm +++ b/code/modules/projectiles/guns/energy/telegun.dm @@ -2,7 +2,7 @@ /obj/item/gun/energy/telegun name = "teleporter gun" - desc = "An extremely high-tech bluespace energy gun capable of teleporting targets to Bluespace Beacons." + desc = "An extremely high-tech energy gun that utilizes jury-rigged bluespace technology to teleport away living targets." icon_state = "telegun" item_state = "telegun" origin_tech = "combat=6;materials=7;powerstorage=5;bluespace=5;syndicate=4" diff --git a/code/modules/projectiles/projectile/special_projectiles.dm b/code/modules/projectiles/projectile/special_projectiles.dm index 4e2aa0d68876..a33f148c00ec 100644 --- a/code/modules/projectiles/projectile/special_projectiles.dm +++ b/code/modules/projectiles/projectile/special_projectiles.dm @@ -181,7 +181,7 @@ qdel(src) /obj/item/projectile/beam/wormhole - name = "bluespace beam" + name = "wormhole beam" icon_state = "spark" hitsound = "sparks" damage = 0 @@ -190,7 +190,7 @@ nodamage = TRUE /obj/item/projectile/beam/wormhole/orange - name = "orange bluespace beam" + name = "orange wormhole beam" color = "#FF6600" /obj/item/projectile/beam/wormhole/New(obj/item/ammo_casing/energy/wormhole/casing) diff --git a/code/modules/projectiles/projectile_base.dm b/code/modules/projectiles/projectile_base.dm index 8d8603f0dccf..57d2a23083ea 100644 --- a/code/modules/projectiles/projectile_base.dm +++ b/code/modules/projectiles/projectile_base.dm @@ -326,7 +326,7 @@ picked_mob.bullet_act(src, def_zone) qdel(src) -/obj/item/projectile/Process_Spacemove(movement_dir = 0) +/obj/item/projectile/Process_Spacemove(movement_dir = 0, continuous_move = FALSE) return 1 //Bullets don't drift in space /obj/item/projectile/process() diff --git a/code/modules/reagents/chemistry/reagents/alcohol.dm b/code/modules/reagents/chemistry/reagents/alcohol.dm index aaa372576e5f..061e0a82471e 100644 --- a/code/modules/reagents/chemistry/reagents/alcohol.dm +++ b/code/modules/reagents/chemistry/reagents/alcohol.dm @@ -822,14 +822,14 @@ /datum/reagent/consumable/ethanol/singulo name = "Singulo" id = "singulo" - description = "A bluespace beverage!" + description = "The edge of eternity, contained in a glass." reagent_state = LIQUID color = "#2E6671" // rgb: 46, 102, 113 dizzy_adj = 30 SECONDS alcohol_perc = 0.7 drink_icon = "singulo" drink_name = "Singulo" - drink_desc = "A bluespace beverage." + drink_desc = "The edge of eternity, contained in a glass." taste_description = "infinity" goal_difficulty = REAGENT_GOAL_NORMAL diff --git a/code/modules/reagents/reagent_containers/glass_containers.dm b/code/modules/reagents/reagent_containers/glass_containers.dm index 41feae4ddfe5..300fc2ee4112 100644 --- a/code/modules/reagents/reagent_containers/glass_containers.dm +++ b/code/modules/reagents/reagent_containers/glass_containers.dm @@ -270,7 +270,7 @@ /obj/item/reagent_containers/glass/beaker/bluespace name = "bluespace beaker" - desc = "A bluespace beaker, powered by experimental bluespace technology and Element Cuban combined with the Compound Pete." + desc = "A bleeding-edge beaker that uses experimental bluespace technology to store massive quantities of liquid." icon_state = "beakerbluespace" materials = list(MAT_GLASS=3000) volume = 300 diff --git a/code/modules/reagents/reagent_containers/spray.dm b/code/modules/reagents/reagent_containers/spray.dm index b639acd9ad15..9ca16326b7fe 100644 --- a/code/modules/reagents/reagent_containers/spray.dm +++ b/code/modules/reagents/reagent_containers/spray.dm @@ -77,23 +77,14 @@ /obj/item/reagent_containers/spray/proc/spray(atom/A) - var/obj/effect/decal/chempuff/D = new /obj/effect/decal/chempuff(get_turf(src)) - D.create_reagents(amount_per_transfer_from_this) - reagents.trans_to(D, amount_per_transfer_from_this, 1/spray_currentrange) - D.icon += mix_color_from_reagents(D.reagents.reagent_list) - - for(var/i in 1 to spray_currentrange) - if(!step_towards(D, A) && i != 1) - qdel(D) - return - D.reagents.reaction(get_turf(D)) - for(var/atom/T in get_turf(D)) - D.reagents.reaction(T) - sleep(3) - if(QDELETED(D)) - return - qdel(D) - + var/obj/effect/decal/chempuff/chem_puff = new /obj/effect/decal/chempuff(get_turf(src)) + chem_puff.create_reagents(amount_per_transfer_from_this) + reagents.trans_to(chem_puff, amount_per_transfer_from_this, 1/spray_currentrange) + chem_puff.icon += mix_color_from_reagents(chem_puff.reagents.reagent_list) + + var/datum/move_loop/our_loop = GLOB.move_manager.move_towards_legacy(chem_puff, A, 3 DECISECONDS, timeout = spray_currentrange * 3 DECISECONDS, flags = MOVEMENT_LOOP_START_FAST, priority = MOVEMENT_ABOVE_SPACE_PRIORITY) + chem_puff.RegisterSignal(our_loop, COMSIG_PARENT_QDELETING, TYPE_PROC_REF(/obj/effect/decal/chempuff, loop_ended)) + chem_puff.RegisterSignal(our_loop, COMSIG_MOVELOOP_POSTPROCESS, TYPE_PROC_REF(/obj/effect/decal/chempuff, check_move)) /obj/item/reagent_containers/spray/attack_self__legacy__attackchain(mob/user) diff --git a/code/modules/recycling/belt-placer.dm b/code/modules/recycling/belt-placer.dm index 739ff0274d54..dbc357bea316 100644 --- a/code/modules/recycling/belt-placer.dm +++ b/code/modules/recycling/belt-placer.dm @@ -17,7 +17,7 @@ /obj/item/storage/conveyor/bluespace name = "bluespace conveyor belt placer" - desc = "This device facilitates the rapid deployment of conveyor belts. It utilises bluespace in order to hold many more belts than its regular counterpart." + desc = "This device facilitates the rapid deployment of conveyor belts via the incorporation of experimental Bluespace technology." icon_state = "bluespace_belt_placer" item_state = "bluespace_belt_placer" w_class = WEIGHT_CLASS_NORMAL diff --git a/code/modules/research/designs/autolathe_designs.dm b/code/modules/research/designs/autolathe_designs.dm index f01a8d1c1a02..41e9955e16e6 100644 --- a/code/modules/research/designs/autolathe_designs.dm +++ b/code/modules/research/designs/autolathe_designs.dm @@ -963,6 +963,7 @@ materials = list(MAT_METAL = 40000) build_path = /obj/item/golem_shell category = list("Imported") + requires_whitelist = TRUE /datum/design/desk_bell name = "Desk Bell" diff --git a/code/modules/research/designs/bluespace_designs.dm b/code/modules/research/designs/bluespace_designs.dm index 6c54e8cb5838..23b1b88ada94 100644 --- a/code/modules/research/designs/bluespace_designs.dm +++ b/code/modules/research/designs/bluespace_designs.dm @@ -23,7 +23,7 @@ /datum/design/bluespace_belt name = "Belt of Holding" - desc = "An astonishingly complex belt popularized by a rich bluespace technology magnate." + desc = "A bleeding-edge storage medium that brings the principles first used in the Bag of Holding to belt form." id = "bluespace_belt" req_tech = list("bluespace" = 7, "materials" = 5, "engineering" = 6, "plasmatech" = 6) build_type = PROTOLATHE @@ -53,7 +53,7 @@ /datum/design/bluespace_belt_holder name = "Bluespace Conveyor Belt Placer" - desc = "This device facilitates the rapid deployment of conveyor belts. This one is powered by bluespace." + desc = "This device facilitates the rapid deployment of conveyor belts via the incorporation of experimental Bluespace technology." id = "bluespace_belt_holder" req_tech = list("materials" = 1, "engineering" = 3, "bluespace" = 3) build_type = PROTOLATHE diff --git a/code/modules/research/designs/janitorial_designs.dm b/code/modules/research/designs/janitorial_designs.dm index f744f2d02b34..3b32f4dad3c7 100644 --- a/code/modules/research/designs/janitorial_designs.dm +++ b/code/modules/research/designs/janitorial_designs.dm @@ -13,7 +13,7 @@ /datum/design/blutrash name = "Trash Bag of Holding" - desc = "An advanced trash bag with bluespace properties; capable of holding a plethora of garbage." + desc = "An advanced trash bag that uses experimental Bluespace technology to send stored trash to a specialized pocket dimension." id = "blutrash" req_tech = list("materials" = 5, "bluespace" = 4, "engineering" = 4, "plasmatech" = 3) build_type = PROTOLATHE diff --git a/code/modules/research/designs/stock_parts_designs.dm b/code/modules/research/designs/stock_parts_designs.dm index 892f821b1165..2c76444b9897 100644 --- a/code/modules/research/designs/stock_parts_designs.dm +++ b/code/modules/research/designs/stock_parts_designs.dm @@ -242,7 +242,7 @@ /datum/design/bs_rped name = "Bluespace RPED" - desc = "Powered by bluespace technology, this RPED variant can upgrade buildings from a distance, without needing to remove the panel first." + desc = "Incorporating experimental bluespace technology, this RPED variant can upgrade buildings from a distance, without needing to remove the panel first." id = "bs_rped" req_tech = list("engineering" = 4, "bluespace" = 3) build_type = PROTOLATHE diff --git a/code/modules/station_goals/shield.dm b/code/modules/station_goals/shield.dm index 9e224a97640f..5165a186b387 100644 --- a/code/modules/station_goals/shield.dm +++ b/code/modules/station_goals/shield.dm @@ -110,12 +110,13 @@ data["satellites"] = list() for(var/obj/machinery/satellite/S in GLOB.machines) + var/turf/T = get_turf(S) data["satellites"] += list(list( "id" = S.id, "active" = S.active, "mode" = S.mode, - "x" = S.x, - "y" = S.y + "x" = T.x, + "y" = T.y )) update_notice() data["notice"] = notice @@ -276,8 +277,9 @@ continue if(get_dist(M, src) > kill_range) continue - if(!emagged && space_los(M)) - if(!istype(M, /obj/effect/meteor/fake)) + var/is_fake = istype(M, /obj/effect/meteor/fake) + if((!emagged || is_fake) && space_los(M)) + if(!is_fake) Beam(get_turf(M), icon_state = "sat_beam", time = 5, maxdistance = kill_range) if(istype(M, /obj/effect/space_dust/meaty)) new /obj/item/food/meatsteak(get_turf(M)) diff --git a/code/modules/surgery/organs/augments_arms.dm b/code/modules/surgery/organs/augments_arms.dm index d3a4834906dd..fea781e8ccff 100644 --- a/code/modules/surgery/organs/augments_arms.dm +++ b/code/modules/surgery/organs/augments_arms.dm @@ -892,7 +892,7 @@ name = "'Naginata' mantis blade" icon_state = "syndie_mantis" item_state = "syndie_mantis" - force = 20 + force = 15 armour_penetration_percentage = 30 /obj/item/melee/mantis_blade/syndicate/Initialize(mapload) @@ -903,7 +903,7 @@ name = "'Scylla' mantis blade" icon_state = "mantis" item_state = "mantis" - force = 18 + force = 12 /obj/item/melee/mantis_blade/nt/Initialize(mapload) . = ..() diff --git a/code/modules/surgery/organs/blood.dm b/code/modules/surgery/organs/blood.dm index e8983586475d..26c3f1fb32a7 100644 --- a/code/modules/surgery/organs/blood.dm +++ b/code/modules/surgery/organs/blood.dm @@ -87,9 +87,9 @@ blood_volume = max(blood_volume - amt, 0) if(isturf(loc)) //Blood loss still happens in locker, floor stays clean if(amt >= 10) - add_splatter_floor(loc, emittor_intertia = inertia_next_move > world.time ? last_movement_dir : null) + add_splatter_floor(loc) else - add_splatter_floor(loc, 1, emittor_intertia = inertia_next_move > world.time ? last_movement_dir : null) + add_splatter_floor(loc, 1) /mob/living/carbon/human/bleed(amt) amt *= physiology.bleed_mod @@ -108,7 +108,7 @@ blood_volume = max(blood_volume - amt, 0) if(prob(10 * amt)) // +5% chance per internal bleeding site that we'll cough up blood on a given tick. custom_emote(EMOTE_VISIBLE, "coughs up blood!") - add_splatter_floor(loc, 1, emittor_intertia = inertia_next_move > world.time ? last_movement_dir : null) + add_splatter_floor(loc, 1) return 1 else if(amt >= 1 && prob(5 * amt)) // +2.5% chance per internal bleeding site that we'll cough up blood on a given tick. Must be bleeding internally in more than one place to have a chance at this. vomit(0, 1) @@ -256,7 +256,7 @@ . += list("O-", "O+") //to add a splatter of blood or other mob liquid. -/mob/living/proc/add_splatter_floor(turf/T, small_drip, shift_x, shift_y, emittor_intertia) +/mob/living/proc/add_splatter_floor(turf/T, small_drip, shift_x, shift_y) if((get_blood_id() != "blood") && (get_blood_id() != "slimejelly"))//is it blood or welding fuel? return if(!T) @@ -264,13 +264,14 @@ var/list/temp_blood_DNA var/list/b_data = get_blood_data(get_blood_id()) + var/datum/move_loop/move/move_loop = GLOB.move_manager.processing_on(src, SSspacedrift) if(small_drip) // Only a certain number of drips (or one large splatter) can be on a given turf. var/obj/effect/decal/cleanable/blood/drip/drop = locate() in T if(drop) - if(emittor_intertia) - drop.newtonian_move(emittor_intertia) + if(move_loop) + drop.newtonian_move(move_loop.direction, instant = TRUE) if(drop.drips < 5) drop.drips++ var/image/I = image(drop.icon, drop.random_icon_states) @@ -295,8 +296,8 @@ else drop.basecolor = "#A10808" drop.update_icon() - if(emittor_intertia) - drop.newtonian_move(emittor_intertia) + if(move_loop) + drop.newtonian_move(move_loop.direction, instant = TRUE) return // Find a blood decal or create a new one. @@ -318,8 +319,8 @@ if(shift_x || shift_y) B.off_floor = TRUE B.layer = BELOW_MOB_LAYER //So the blood lands ontop of things like posters, windows, etc. - if(emittor_intertia) - B.newtonian_move(emittor_intertia) + if(move_loop) + B.newtonian_move(move_loop.direction, instant = TRUE) /mob/living/carbon/human/add_splatter_floor(turf/T, small_drip, shift_x, shift_y, emittor_intertia) if(!(NO_BLOOD in dna.species.species_traits)) diff --git a/code/modules/surgery/organs/organ_internal.dm b/code/modules/surgery/organs/organ_internal.dm index e6cf100cf1f2..7bb1293a8d51 100644 --- a/code/modules/surgery/organs/organ_internal.dm +++ b/code/modules/surgery/organs/organ_internal.dm @@ -320,10 +320,10 @@ if(isobj(H.shoes)) var/thingy = H.shoes if(H.drop_item_to_ground(H.shoes)) - walk_away(thingy,H,15,2) + GLOB.move_manager.move_away(thingy, H, 15, 2) spawn(20) if(thingy) - walk(thingy,0) + GLOB.move_manager.stop_looping(thingy) /obj/item/organ/internal/honktumor/cursed unremovable = TRUE diff --git a/code/modules/vehicle/speedbike.dm b/code/modules/vehicle/speedbike.dm index 6de2b58d99ac..19a4582f79f6 100644 --- a/code/modules/vehicle/speedbike.dm +++ b/code/modules/vehicle/speedbike.dm @@ -1,50 +1,38 @@ -/obj/vehicle/space/speedbike +/obj/tgvehicle/speedbike name = "Speedbike" icon = 'icons/obj/bike.dmi' icon_state = "speedbike_blue" - layer = MOB_LAYER - 0.1 - vehicle_move_delay = 0 - var/overlay_state = "cover_blue" - var/mutable_appearance/overlay + layer = LYING_MOB_LAYER + var/cover_iconstate = "cover_blue" -/obj/vehicle/space/speedbike/Initialize(mapload) +/obj/tgvehicle/speedbike/Initialize(mapload) . = ..() - overlay = mutable_appearance(icon, overlay_state, ABOVE_MOB_LAYER) - add_overlay(overlay) + add_overlay(image(icon, cover_iconstate, ABOVE_MOB_LAYER)) + AddElement(/datum/element/ridable, /datum/component/riding/vehicle/speedbike) -/obj/vehicle/space/speedbike/Move(newloc,move_dir) +/obj/tgvehicle/speedbike/Move(newloc,move_dir) if(has_buckled_mobs()) new /obj/effect/temp_visual/dir_setting/speedbike_trail(loc) . = ..() -/obj/vehicle/space/speedbike/handle_vehicle_layer() - switch(dir) - if(NORTH,SOUTH) - pixel_x = -16 - pixel_y = -16 - if(EAST,WEST) - pixel_x = -18 - pixel_y = 0 +/obj/tgvehicle/speedbike/red + icon_state = "speedbike_red" + cover_iconstate = "cover_red" -/obj/vehicle/space/speedbike/handle_vehicle_offsets() - if(has_buckled_mobs()) - for(var/m in buckled_mobs) - var/mob/living/buckled_mob = m - buckled_mob.setDir(dir) - switch(dir) - if(NORTH) - buckled_mob.pixel_x = 0 - buckled_mob.pixel_y = -8 - if(SOUTH) - buckled_mob.pixel_x = 0 - buckled_mob.pixel_y = 4 - if(EAST) - buckled_mob.pixel_x = -10 - buckled_mob.pixel_y = 5 - if(WEST) - buckled_mob.pixel_x = 10 - buckled_mob.pixel_y = 5 +/datum/component/riding/vehicle/speedbike + vehicle_move_delay = 1 + override_allow_spacemove = TRUE + ride_check_flags = RIDER_NEEDS_LEGS | RIDER_NEEDS_ARMS | UNBUCKLE_DISABLED_RIDER -/obj/vehicle/space/speedbike/red - icon_state = "speedbike_red" - overlay_state = "cover_red" +/datum/component/riding/vehicle/speedbike/handle_specials() + . = ..() + set_vehicle_dir_layer(SOUTH, OBJ_LAYER) + set_vehicle_dir_layer(NORTH, ABOVE_MOB_LAYER) + set_vehicle_dir_layer(EAST, OBJ_LAYER) + set_vehicle_dir_layer(WEST, OBJ_LAYER) + + set_riding_offsets(RIDING_OFFSET_ALL, list(TEXT_NORTH = list(0, -8), TEXT_SOUTH = list(0, 4), TEXT_EAST = list(-10, 5), TEXT_WEST = list(10, 5))) + set_vehicle_dir_offsets(NORTH, -16, -16) + set_vehicle_dir_offsets(SOUTH, -16, -16) + set_vehicle_dir_offsets(EAST, -18, 0) + set_vehicle_dir_offsets(WEST, -18, 0) diff --git a/code/modules/vehicle/vehicle.dm b/code/modules/vehicle/vehicle.dm index 396683813b16..e1e37ccaf046 100644 --- a/code/modules/vehicle/vehicle.dm +++ b/code/modules/vehicle/vehicle.dm @@ -229,7 +229,7 @@ return //write specifics for different vehicles -/obj/vehicle/Process_Spacemove(direction) +/obj/vehicle/Process_Spacemove(movement_dir = 0, continuous_move = FALSE) if(has_gravity(src)) return TRUE @@ -245,7 +245,7 @@ pressure_resistance = INFINITY spaceworthy = TRUE -/obj/vehicle/space/Process_Spacemove(direction) +/obj/vehicle/space/Process_Spacemove(movement_dir = 0, continuous_move = FALSE) return TRUE /obj/vehicle/zap_act(power, zap_flags) diff --git a/icons/effects/random_spawners.dmi b/icons/effects/random_spawners.dmi index 4cccc5ddfadf..360c77e14d5f 100644 Binary files a/icons/effects/random_spawners.dmi and b/icons/effects/random_spawners.dmi differ diff --git a/modular_ss220/_defines220/code/signals_mob/signals_mob_main.dm b/modular_ss220/_defines220/code/signals_mob/signals_mob_main.dm index 1908d846992d..783b4f91496e 100644 --- a/modular_ss220/_defines220/code/signals_mob/signals_mob_main.dm +++ b/modular_ss220/_defines220/code/signals_mob/signals_mob_main.dm @@ -1,5 +1,5 @@ // Signals for /mob -/// from mob/living/Process_Spacemove(): (movement_dir) +/// from mob/living/Process_Spacemove(): (movement_dir, continuous_move) #define COMSIG_LIVING_PROCESS_SPACEMOVE "mob_client_pre_living_move" #define COMPONENT_BLOCK_SPACEMOVE (1<<0) diff --git a/modular_ss220/_signals220/code/signals_mob/signals_mob_living.dm b/modular_ss220/_signals220/code/signals_mob/signals_mob_living.dm index 3156950bf60a..ad9e9989ead9 100644 --- a/modular_ss220/_signals220/code/signals_mob/signals_mob_living.dm +++ b/modular_ss220/_signals220/code/signals_mob/signals_mob_living.dm @@ -22,7 +22,7 @@ . = ..() // Да, костыльно, но модульно по другому не вижу как - PIXEL_SHIFT -/mob/living/Process_Spacemove(movement_dir) +/mob/living/Process_Spacemove(movement_dir, continuous_move = FALSE) if(SEND_SIGNAL(src, COMSIG_LIVING_PROCESS_SPACEMOVE, movement_dir) & COMPONENT_BLOCK_SPACEMOVE) return FALSE . = ..() diff --git a/modular_ss220/antagonists/code/guns/biogun.dm b/modular_ss220/antagonists/code/guns/biogun.dm index 1521d515338b..579586e89b24 100644 --- a/modular_ss220/antagonists/code/guns/biogun.dm +++ b/modular_ss220/antagonists/code/guns/biogun.dm @@ -74,7 +74,7 @@ melee_damage_lower = 10 melee_damage_upper = 15 -/mob/living/simple_animal/hostile/viscerator/vox/Process_Spacemove(movement_dir) +/mob/living/simple_animal/hostile/viscerator/vox/Process_Spacemove(movement_dir, continuous_move = FALSE) return TRUE /mob/living/simple_animal/hostile/viscerator/vox/stamina diff --git a/modular_ss220/antagonists/code/mind/memory_edit.dm b/modular_ss220/antagonists/code/mind/memory_edit.dm index 124fa1b5509b..ee99bc0d107f 100644 --- a/modular_ss220/antagonists/code/mind/memory_edit.dm +++ b/modular_ss220/antagonists/code/mind/memory_edit.dm @@ -61,11 +61,11 @@ . = ..() if(href_list["makeAntag"]) switch(href_list["makeAntag"]) - if("9") + if("10") log_admin("[key_name(usr)] has spawned a blood brothers.") if(!makeBloodBrothersTeam()) to_chat(usr, "К сожалению, недостаточно кандидатов.") - if("10") + if("11") log_admin("[key_name(usr)] has spawned a vox raiders.") if(!makeVoxRaidersTeam()) to_chat(usr, "К сожалению, недостаточно кандидатов.") diff --git a/modular_ss220/maps220/code/mobs.dm b/modular_ss220/maps220/code/mobs.dm index 4256ac1593c1..9d18485aa523 100644 --- a/modular_ss220/maps220/code/mobs.dm +++ b/modular_ss220/maps220/code/mobs.dm @@ -1341,6 +1341,9 @@ icon_state = "drone" syndi_mob = /mob/living/simple_animal/hostile/malf_drone/spacebattle +/obj/effect/spawner/random/pool/spaceloot/modsuit_syndie/spacebattle + loot = list(/mob/living/simple_animal/hostile/syndicate/ranged/space/autogib/spacebattle) + //Enemies /mob/living/simple_animal/hostile/syndicate //Обычный лут, дропается со всех @@ -1477,7 +1480,6 @@ /mob/living/simple_animal/hostile/syndicate/ranged/space/autogib/spacebattle/Initialize(mapload) . = ..() loot = list(/obj/effect/decal/cleanable/ash, SynMobDrop, SynRange, SynSpace) - return . /mob/living/simple_animal/hostile/malf_drone/spacebattle icon = 'modular_ss220/maps220/icons/spacebattle.dmi' diff --git a/modular_ss220/mobs/code/simple_animal/friendly/snail.dm b/modular_ss220/mobs/code/simple_animal/friendly/snail.dm index e887ff0bfe0d..4c12a8fa87e7 100644 --- a/modular_ss220/mobs/code/simple_animal/friendly/snail.dm +++ b/modular_ss220/mobs/code/simple_animal/friendly/snail.dm @@ -30,7 +30,7 @@ reagents = new() holder_type = /obj/item/holder/snail -/mob/living/simple_animal/snail/Process_Spacemove(movement_dir = 0) +/mob/living/simple_animal/snail/Process_Spacemove(movement_dir = 0, continuous_move = FALSE) return 1 /mob/living/simple_animal/snail/Move(atom/newloc, direct, movetime) diff --git a/modular_ss220/objects/code/key.dm b/modular_ss220/objects/code/key.dm index 16637d80d6ed..a96359a7a363 100644 --- a/modular_ss220/objects/code/key.dm +++ b/modular_ss220/objects/code/key.dm @@ -8,13 +8,11 @@ /// How fast does the key open an airlock. var/hack_speed = 1 SECONDS -/obj/item/door_remote/key/attack_self__legacy__attackchain(mob/user) - return - -/obj/item/door_remote/key/afterattack__legacy__attackchain(obj/machinery/door/airlock/attacked_airlock, mob/user, proximity) - if(!proximity) - return +/obj/item/door_remote/key/activate_self(mob/user) + ..() +/obj/item/door_remote/key/interact_with_atom(atom/target, mob/living/user, list/modifiers) + var/obj/machinery/door/airlock/attacked_airlock = target if(!istype(attacked_airlock)) return @@ -22,10 +20,6 @@ to_chat(user, span_danger("[src] не вставляется в панель доступа [attacked_airlock], тут повсюду слизь!")) return - if(attacked_airlock.is_special) - to_chat(user, span_danger("[src] не помещается в панель доступа [attacked_airlock]!")) - return - if(!attacked_airlock.arePowerSystemsOn()) to_chat(user, span_danger("[attacked_airlock] без питания!")) return @@ -52,6 +46,9 @@ return attacked_airlock.open() +/obj/item/door_remote/key/ranged_interact_with_atom(atom/target, mob/living/user, list/modifiers) + return ITEM_INTERACT_COMPLETE + /obj/item/door_remote/key/engineer name = "\proper ключ от инженерного отдела" icon_state = "eng" diff --git a/modular_ss220/shuttles/code/lance_shuttle.dm b/modular_ss220/shuttles/code/lance_shuttle.dm index 27a4c97cfae6..a4b61886e877 100644 --- a/modular_ss220/shuttles/code/lance_shuttle.dm +++ b/modular_ss220/shuttles/code/lance_shuttle.dm @@ -3,7 +3,7 @@ var/obj/docking_port/stationary/CCport CCport = SSshuttle.getDock("emergency_away") CCport.setDir(4) - CCport.forceMove(locate(117, 80, 1)) + CCport.forceMove(locate(117, 83, 1)) CCport.height = 50 CCport.dheight = 0 CCport.width = 19 @@ -11,7 +11,7 @@ var/obj/docking_port/stationary/CCtransit CCtransit = SSshuttle.getDock("emergency_transit") CCtransit.setDir(2) - CCtransit.forceMove(locate(179, 166, 1)) + CCtransit.forceMove(locate(179, 169, 1)) CCtransit.height = 50 CCtransit.dheight = 0 CCtransit.width = 19 diff --git a/paradise.dme b/paradise.dme index e98f464ac85f..dc24365e61ef 100644 --- a/paradise.dme +++ b/paradise.dme @@ -95,7 +95,7 @@ #include "code\__DEFINES\mob_defines.dm" #include "code\__DEFINES\mod.dm" #include "code\__DEFINES\move_force.dm" -#include "code\__DEFINES\movement_info.dm" +#include "code\__DEFINES\movement_defines.dm" #include "code\__DEFINES\muzzle_flash.dm" #include "code\__DEFINES\newscaster_defines.dm" #include "code\__DEFINES\particle_defines.dm" @@ -160,6 +160,7 @@ #include "code\__DEFINES\dcs\machinery_signals.dm" #include "code\__DEFINES\dcs\mob_signals.dm" #include "code\__DEFINES\dcs\movable_signals.dm" +#include "code\__DEFINES\dcs\moveloop_signals.dm" #include "code\__DEFINES\dcs\obj_signals.dm" #include "code\__DEFINES\modular_ss220\_ss220.dm" #include "code\__DEFINES\modular_ss220\pronouns.dm" @@ -338,7 +339,6 @@ #include "code\controllers\subsystem\SSrunechat.dm" #include "code\controllers\subsystem\SSsecurity_level.dm" #include "code\controllers\subsystem\SSshuttles.dm" -#include "code\controllers\subsystem\SSspacedrift.dm" #include "code\controllers\subsystem\SSstatpanel.dm" #include "code\controllers\subsystem\SSsun.dm" #include "code\controllers\subsystem\SStgui.dm" @@ -349,6 +349,9 @@ #include "code\controllers\subsystem\SSverb_manager.dm" #include "code\controllers\subsystem\SSvote.dm" #include "code\controllers\subsystem\SSweather.dm" +#include "code\controllers\subsystem\movement\movement_types.dm" +#include "code\controllers\subsystem\movement\SSmovement.dm" +#include "code\controllers\subsystem\movement\SSspacedrift.dm" #include "code\controllers\subsystem\non_firing\SSassets.dm" #include "code\controllers\subsystem\non_firing\SSatoms.dm" #include "code\controllers\subsystem\non_firing\SSchangelog.dm" @@ -404,6 +407,7 @@ #include "code\datums\logging.dm" #include "code\datums\mind.dm" #include "code\datums\mixed.dm" +#include "code\datums\move_manager.dm" #include "code\datums\movement_detector.dm" #include "code\datums\mutable_appearance.dm" #include "code\datums\ores.dm" @@ -420,7 +424,6 @@ #include "code\datums\ruins.dm" #include "code\datums\shuttles.dm" #include "code\datums\spawners_menu.dm" -#include "code\datums\spell.dm" #include "code\datums\station_state.dm" #include "code\datums\tgs_event_handler.dm" #include "code\datums\verb_callbacks.dm" @@ -445,12 +448,14 @@ #include "code\datums\components\deadchat_control.dm" #include "code\datums\components\debris.dm" #include "code\datums\components\defibrillator.dm" +#include "code\datums\components\drift.dm" #include "code\datums\components\ducttape.dm" #include "code\datums\components\edit_complainer.dm" #include "code\datums\components\emissive_blocker.dm" #include "code\datums\components\footstep.dm" #include "code\datums\components\forces_doors_open.dm" #include "code\datums\components\fullauto.dm" +#include "code\datums\components\jetpack_component.dm" #include "code\datums\components\ghost_direct_control.dm" #include "code\datums\components\label.dm" #include "code\datums\components\largeobjecttransparency.dm" @@ -596,6 +601,7 @@ #include "code\datums\spell_targeting\aoe.dm" #include "code\datums\spell_targeting\click_spell_targeting.dm" #include "code\datums\spell_targeting\clicked_atom.dm" +#include "code\datums\spell_targeting\cone.dm" #include "code\datums\spell_targeting\matter_eater_targeting.dm" #include "code\datums\spell_targeting\reachable_turfs.dm" #include "code\datums\spell_targeting\remoteview_targeting.dm" @@ -638,6 +644,7 @@ #include "code\datums\spells\sentient_sword_lunge.dm" #include "code\datums\spells\shapeshift.dm" #include "code\datums\spells\spacetime_dist.dm" +#include "code\datums\spells\spell_base.dm" #include "code\datums\spells\summon_supermatter.dm" #include "code\datums\spells\summonitem.dm" #include "code\datums\spells\touch_attacks.dm" @@ -656,6 +663,7 @@ #include "code\datums\spells\alien_spells\tail_lash.dm" #include "code\datums\spells\alien_spells\transfer_plasma.dm" #include "code\datums\spells\alien_spells\whisper.dm" +#include "code\datums\spells\cones\cone_spell.dm" #include "code\datums\station_traits\_station_trait.dm" #include "code\datums\station_traits\admin_panel.dm" #include "code\datums\station_traits\negative_traits.dm" @@ -1069,6 +1077,7 @@ #include "code\game\objects\effects\spawners\random\toy_spawners.dm" #include "code\game\objects\effects\spawners\random\trash_spawners.dm" #include "code\game\objects\effects\spawners\random\pool\pool_spawner.dm" +#include "code\game\objects\effects\spawners\random\pool\space_loot.dm" #include "code\game\objects\effects\spawners\random\pool\spawn_pool.dm" #include "code\game\objects\effects\spawners\random\pool\spawn_pool_manager.dm" #include "code\game\objects\effects\spawners\random\traders\trader_department_spawners.dm" @@ -2232,8 +2241,8 @@ #include "code\modules\mob\dead\observer\observer_login.dm" #include "code\modules\mob\dead\observer\observer_logout.dm" #include "code\modules\mob\dead\observer\observer_say.dm" +#include "code\modules\mob\dead\observer\observer_spells.dm" #include "code\modules\mob\dead\observer\orbit.dm" -#include "code\modules\mob\dead\observer\spells.dm" #include "code\modules\mob\living\autohiss.dm" #include "code\modules\mob\living\damage_procs.dm" #include "code\modules\mob\living\death.dm" diff --git a/rustlibs.dll b/rustlibs.dll index 195a8ab83301..85c67349f2df 100644 Binary files a/rustlibs.dll and b/rustlibs.dll differ diff --git a/rustlibs_prod.dll b/rustlibs_prod.dll index 018a6878f0f7..fb16983a6a7f 100644 Binary files a/rustlibs_prod.dll and b/rustlibs_prod.dll differ diff --git a/tools/UpdatePaths/Scripts/27698_vehicle_paths.txt b/tools/UpdatePaths/Scripts/27698_vehicle_paths.txt new file mode 100644 index 000000000000..df3277271e7d --- /dev/null +++ b/tools/UpdatePaths/Scripts/27698_vehicle_paths.txt @@ -0,0 +1 @@ +/obj/vehicle/space/speedbike/@SUBTYPES : /obj/tgvehicle/speedbike/@SUBTYPE diff --git a/tools/UpdatePaths/Scripts/27954_spaceloot_pool.txt b/tools/UpdatePaths/Scripts/27954_spaceloot_pool.txt new file mode 100644 index 000000000000..2471ffb14f1c --- /dev/null +++ b/tools/UpdatePaths/Scripts/27954_spaceloot_pool.txt @@ -0,0 +1,5 @@ +/obj/effect/spawner/random/syndicate/loot/stetchkin : /obj/effect/spawner/random/syndicate/stetchkin +/obj/effect/spawner/random/syndicate/loot/@SUBTYPES : /obj/effect/spawner/random/pool/spaceloot/syndicate/@SUBTYPES/depot +/mob/living/simple_animal/hostile/syndicate/ranged/space/autogib : /obj/effect/spawner/random/pool/spaceloot/modsuit_syndie +/mob/living/simple_animal/hostile/syndicate/ranged/space/autogib/@SUBTYPES : /obj/effect/spawner/random/pool/spaceloot/modsuit_syndie/@SUBTYPES +/obj/effect/spawner/random/deepstorage_reward/main : /obj/effect/spawner/random/pool/spaceloot/deepstorage/main diff --git a/tools/UpdatePaths/__main__.py b/tools/UpdatePaths/__main__.py index 0f0eb75488c3..238011692c99 100644 --- a/tools/UpdatePaths/__main__.py +++ b/tools/UpdatePaths/__main__.py @@ -111,11 +111,14 @@ def replace_def(match): if verbose: print("Deleting match : {0}".format(match.group(0))) return [None] - elif new_path.endswith("/@SUBTYPES"): - path_start = new_path[:-len("/@SUBTYPES")] - out = path_start + match.group('subtype') else: - out = new_path + replacement_pos = new_path.find("/@SUBTYPES") + if replacement_pos >= 0: + path_start = new_path[:replacement_pos] + path_end = new_path[replacement_pos + len("/@SUBTYPES"):] + out = path_start + match.group('subtype') + path_end + else: + out = new_path out_props = dict() for prop_name, prop_text in new_props.items(): diff --git a/tools/ci/librustlibs_ci.so b/tools/ci/librustlibs_ci.so index 6a4af0af6a81..875778ed0529 100644 Binary files a/tools/ci/librustlibs_ci.so and b/tools/ci/librustlibs_ci.so differ