mirror of
https://github.com/Bubberstation/Bubberstation.git
synced 2026-08-24 05:30:05 +01:00
Merge branch 'master' of https://github.com/tgstation/tgstation into upstream-sync
This commit is contained in:
@@ -1601,8 +1601,8 @@
|
||||
/obj/structure/rack,
|
||||
/obj/effect/decal/cleanable/dirt,
|
||||
/obj/item/storage/toolbox/mechanical,
|
||||
/obj/item/ammo_box/c38,
|
||||
/obj/item/ammo_box/c38,
|
||||
/obj/item/ammo_box/speedloader/c38,
|
||||
/obj/item/ammo_box/speedloader/c38,
|
||||
/obj/effect/turf_decal/tile/yellow/anticorner/contrasted{
|
||||
dir = 1
|
||||
},
|
||||
@@ -3661,7 +3661,7 @@
|
||||
/obj/structure/window/reinforced/spawner/directional/south,
|
||||
/obj/effect/spawner/random/contraband/permabrig_weapon,
|
||||
/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2,
|
||||
/obj/item/ammo_box/c38,
|
||||
/obj/item/ammo_box/speedloader/c38,
|
||||
/obj/effect/turf_decal/tile/dark_red/anticorner,
|
||||
/turf/open/floor/iron/dark,
|
||||
/area/ruin/space/has_grav/dangerous_research)
|
||||
|
||||
@@ -28,7 +28,7 @@
|
||||
/obj/item/clothing/shoes/workboots/mining,
|
||||
/obj/item/clothing/gloves/color/black,
|
||||
/obj/effect/mob_spawn/corpse/human/charredskeleton,
|
||||
/obj/item/borg/sight/meson,
|
||||
/obj/item/clothing/glasses/meson,
|
||||
/obj/item/pickaxe/improvised,
|
||||
/turf/open/misc/asteroid/basalt/airless,
|
||||
/area/ruin/unpowered/no_grav)
|
||||
|
||||
@@ -5093,8 +5093,8 @@
|
||||
/obj/item/spess_knife,
|
||||
/obj/item/clothing/suit/armor/vest/old,
|
||||
/obj/item/gun/ballistic/rifle/boltaction,
|
||||
/obj/item/ammo_box/strilka310,
|
||||
/obj/item/ammo_box/strilka310,
|
||||
/obj/item/ammo_box/speedloader/strilka310,
|
||||
/obj/item/ammo_box/speedloader/strilka310,
|
||||
/turf/open/floor/plating,
|
||||
/area/ruin/space/ancientstation/delta/hall)
|
||||
"Cc" = (
|
||||
|
||||
+118
-98
@@ -103,7 +103,7 @@
|
||||
/obj/effect/decal/cleanable/dirt/dust,
|
||||
/obj/effect/decal/cleanable/cobweb,
|
||||
/turf/open/floor/iron/white/small,
|
||||
/area/awaymission/museum)
|
||||
/area/awaymission/museum/cafeteria)
|
||||
"aR" = (
|
||||
/obj/effect/turf_decal/tile/neutral/opposingcorners,
|
||||
/obj/effect/turf_decal/siding/dark_blue{
|
||||
@@ -264,7 +264,7 @@
|
||||
/obj/effect/turf_decal/tile/neutral/opposingcorners,
|
||||
/obj/effect/decal/cleanable/dirt/dust,
|
||||
/turf/open/floor/iron/dark,
|
||||
/area/awaymission/museum)
|
||||
/area/awaymission/museum/cafeteria)
|
||||
"cm" = (
|
||||
/obj/machinery/door/airlock/grunge,
|
||||
/obj/structure/barricade/wooden/crude,
|
||||
@@ -815,7 +815,7 @@
|
||||
"gE" = (
|
||||
/obj/item/clothing/suit/caution,
|
||||
/turf/open/floor/iron/white/small,
|
||||
/area/awaymission/museum)
|
||||
/area/awaymission/museum/cafeteria)
|
||||
"gG" = (
|
||||
/obj/effect/turf_decal/siding/dark_blue/corner{
|
||||
dir = 4
|
||||
@@ -952,7 +952,7 @@
|
||||
dir = 5
|
||||
},
|
||||
/turf/open/floor/iron/dark,
|
||||
/area/awaymission/museum)
|
||||
/area/awaymission/museum/cafeteria)
|
||||
"hT" = (
|
||||
/mob/living/basic/statue/mannequin{
|
||||
name = "Dale Knox";
|
||||
@@ -983,6 +983,9 @@
|
||||
},
|
||||
/turf/open/floor/engine,
|
||||
/area/awaymission/museum)
|
||||
"ia" = (
|
||||
/turf/open/floor/iron/white/small,
|
||||
/area/awaymission/museum/cafeteria)
|
||||
"il" = (
|
||||
/obj/structure/table/wood,
|
||||
/obj/item/clothing/suit/costume/judgerobe,
|
||||
@@ -1160,7 +1163,7 @@
|
||||
name = "Restrooms"
|
||||
},
|
||||
/turf/open/floor/iron/dark,
|
||||
/area/awaymission/museum)
|
||||
/area/awaymission/museum/cafeteria)
|
||||
"jy" = (
|
||||
/mob/living/basic/statue/mannequin{
|
||||
name = "Dale Knox";
|
||||
@@ -1183,7 +1186,7 @@
|
||||
queue_id = "museum_right_wing"
|
||||
},
|
||||
/turf/closed/indestructible/reinforced,
|
||||
/area/awaymission/museum)
|
||||
/area/awaymission/museum/cafeteria)
|
||||
"jF" = (
|
||||
/obj/machinery/suit_storage_unit/open,
|
||||
/obj/effect/turf_decal/box,
|
||||
@@ -1315,7 +1318,7 @@
|
||||
name = "Restrooms"
|
||||
},
|
||||
/turf/open/floor/iron,
|
||||
/area/awaymission/museum)
|
||||
/area/awaymission/museum/cafeteria)
|
||||
"kA" = (
|
||||
/obj/machinery/conveyor{
|
||||
dir = 1
|
||||
@@ -1332,7 +1335,7 @@
|
||||
id = "museum_cafeteria"
|
||||
},
|
||||
/turf/open/floor/iron,
|
||||
/area/awaymission/museum)
|
||||
/area/awaymission/museum/cafeteria)
|
||||
"kO" = (
|
||||
/obj/structure/railing{
|
||||
dir = 8
|
||||
@@ -1740,7 +1743,7 @@
|
||||
"nY" = (
|
||||
/obj/structure/sign/poster/official/no_erp/directional/north,
|
||||
/turf/open/floor/iron/white/small,
|
||||
/area/awaymission/museum)
|
||||
/area/awaymission/museum/cafeteria)
|
||||
"nZ" = (
|
||||
/obj/structure/chair/sofa/bench/left{
|
||||
dir = 1
|
||||
@@ -1831,7 +1834,7 @@
|
||||
queue_id = "museum_cafeteria"
|
||||
},
|
||||
/turf/closed/indestructible/reinforced,
|
||||
/area/awaymission/museum)
|
||||
/area/awaymission/museum/cafeteria)
|
||||
"oQ" = (
|
||||
/turf/open/floor/holofloor/beach/coast{
|
||||
dir = 1
|
||||
@@ -1914,7 +1917,7 @@
|
||||
id = "museum_cafeteria"
|
||||
},
|
||||
/turf/open/floor/iron,
|
||||
/area/awaymission/museum)
|
||||
/area/awaymission/museum/cafeteria)
|
||||
"pD" = (
|
||||
/obj/structure/broken_flooring/corner/always_floorplane/directional/west,
|
||||
/obj/effect/decal/cleanable/dirt/dust,
|
||||
@@ -1954,7 +1957,7 @@
|
||||
dir = 4
|
||||
},
|
||||
/turf/open/floor/iron/dark,
|
||||
/area/awaymission/museum)
|
||||
/area/awaymission/museum/cafeteria)
|
||||
"pX" = (
|
||||
/obj/structure/rack,
|
||||
/obj/effect/spawner/random/maintenance/two,
|
||||
@@ -2317,6 +2320,13 @@
|
||||
/obj/effect/decal/cleanable/dirt/dust,
|
||||
/turf/open/floor/engine,
|
||||
/area/awaymission/museum)
|
||||
"sR" = (
|
||||
/obj/effect/turf_decal/tile/neutral/opposingcorners,
|
||||
/obj/effect/turf_decal/siding/dark_blue{
|
||||
dir = 10
|
||||
},
|
||||
/turf/open/floor/iron/dark,
|
||||
/area/awaymission/museum/cafeteria)
|
||||
"sX" = (
|
||||
/obj/effect/turf_decal/tile/neutral/opposingcorners,
|
||||
/obj/effect/turf_decal/siding/dark_blue{
|
||||
@@ -2522,7 +2532,7 @@
|
||||
/obj/structure/tank_holder/extinguisher/anti,
|
||||
/obj/effect/decal/cleanable/dirt/dust,
|
||||
/turf/open/floor/iron/white/small,
|
||||
/area/awaymission/museum)
|
||||
/area/awaymission/museum/cafeteria)
|
||||
"up" = (
|
||||
/obj/effect/turf_decal/siding/wood{
|
||||
dir = 4
|
||||
@@ -2538,7 +2548,7 @@
|
||||
id_tag = "museum_toilet2"
|
||||
},
|
||||
/turf/open/floor/iron,
|
||||
/area/awaymission/museum)
|
||||
/area/awaymission/museum/cafeteria)
|
||||
"ut" = (
|
||||
/obj/machinery/light/very_dim/directional/north,
|
||||
/obj/effect/decal/cleanable/dirt/dust,
|
||||
@@ -2546,7 +2556,7 @@
|
||||
/obj/structure/mop_bucket,
|
||||
/obj/effect/decal/cleanable/cobweb/cobweb2,
|
||||
/turf/open/floor/iron/white/small,
|
||||
/area/awaymission/museum)
|
||||
/area/awaymission/museum/cafeteria)
|
||||
"uu" = (
|
||||
/obj/structure/rack,
|
||||
/obj/effect/spawner/random/engineering/material,
|
||||
@@ -2711,7 +2721,7 @@
|
||||
note_info = "I'VE WORKED HERE FOR 7 YEARS! JUST TO BE REPLACED BY A VENDING MACHINE?! YOU KNOW WHAT? FUCK YOU, I'VE LOCKED DOWN THE CAFETERIA AND WON'T BE COMING OUT 'TILL YOU GIVE ME MY JOB BACK!"
|
||||
},
|
||||
/turf/open/floor/iron,
|
||||
/area/awaymission/museum)
|
||||
/area/awaymission/museum/cafeteria)
|
||||
"wh" = (
|
||||
/obj/structure/broken_flooring/corner/always_floorplane/directional/west,
|
||||
/obj/structure/lattice,
|
||||
@@ -2723,7 +2733,7 @@
|
||||
id = "museum_right_wing"
|
||||
},
|
||||
/turf/open/floor/iron,
|
||||
/area/awaymission/museum)
|
||||
/area/awaymission/museum/cafeteria)
|
||||
"wk" = (
|
||||
/obj/machinery/vending/dinnerware,
|
||||
/turf/open/floor/iron/freezer,
|
||||
@@ -2805,7 +2815,7 @@
|
||||
},
|
||||
/obj/effect/turf_decal/tile/neutral/opposingcorners,
|
||||
/turf/open/floor/iron/dark,
|
||||
/area/awaymission/museum)
|
||||
/area/awaymission/museum/cafeteria)
|
||||
"wZ" = (
|
||||
/turf/open/misc/beach/coast{
|
||||
dir = 1
|
||||
@@ -3547,7 +3557,7 @@
|
||||
/obj/structure/mirror/directional/east,
|
||||
/obj/structure/sink/directional/west,
|
||||
/turf/open/floor/iron/white/small,
|
||||
/area/awaymission/museum)
|
||||
/area/awaymission/museum/cafeteria)
|
||||
"CI" = (
|
||||
/obj/effect/turf_decal/caution,
|
||||
/obj/effect/decal/cleanable/dirt/dust,
|
||||
@@ -3973,7 +3983,7 @@
|
||||
dir = 4
|
||||
},
|
||||
/turf/open/floor/iron/dark,
|
||||
/area/awaymission/museum)
|
||||
/area/awaymission/museum/cafeteria)
|
||||
"FY" = (
|
||||
/obj/structure/chair/sofa/bench/left,
|
||||
/turf/open/floor/iron/cafeteria,
|
||||
@@ -4156,7 +4166,7 @@
|
||||
id = "museum_right_wing"
|
||||
},
|
||||
/turf/open/floor/iron/dark,
|
||||
/area/awaymission/museum)
|
||||
/area/awaymission/museum/cafeteria)
|
||||
"HE" = (
|
||||
/obj/effect/turf_decal/siding/dark_blue{
|
||||
dir = 1
|
||||
@@ -4210,7 +4220,7 @@
|
||||
},
|
||||
/obj/machinery/light/small/dim/directional/west,
|
||||
/turf/open/floor/iron/white/small,
|
||||
/area/awaymission/museum)
|
||||
/area/awaymission/museum/cafeteria)
|
||||
"HY" = (
|
||||
/obj/machinery/light/floor,
|
||||
/obj/effect/decal/cleanable/dirt/dust,
|
||||
@@ -4242,7 +4252,7 @@
|
||||
/area/awaymission/museum)
|
||||
"Ir" = (
|
||||
/turf/closed/indestructible/fakedoor,
|
||||
/area/awaymission/museum)
|
||||
/area/awaymission/museum/cafeteria)
|
||||
"Iu" = (
|
||||
/turf/open/floor/mineral/titanium/blue,
|
||||
/area/awaymission/museum)
|
||||
@@ -4369,7 +4379,7 @@
|
||||
id_tag = "museum_toilet1"
|
||||
},
|
||||
/turf/open/floor/iron,
|
||||
/area/awaymission/museum)
|
||||
/area/awaymission/museum/cafeteria)
|
||||
"Js" = (
|
||||
/obj/effect/turf_decal/tile/neutral/opposingcorners,
|
||||
/obj/effect/turf_decal/siding/dark_blue{
|
||||
@@ -4493,7 +4503,7 @@
|
||||
content = list("Instructions; stand upright; remove safety clip; aim noozle at base of fire... the rest is up to you.")
|
||||
},
|
||||
/turf/open/floor/iron/white/small,
|
||||
/area/awaymission/museum)
|
||||
/area/awaymission/museum/cafeteria)
|
||||
"KB" = (
|
||||
/obj/structure/sign/warning/no_smoking/circle/directional/east,
|
||||
/turf/open/floor/iron/cafeteria,
|
||||
@@ -4623,7 +4633,7 @@
|
||||
/obj/effect/turf_decal/siding/dark_blue,
|
||||
/obj/effect/turf_decal/tile/neutral/opposingcorners,
|
||||
/turf/open/floor/iron/dark,
|
||||
/area/awaymission/museum)
|
||||
/area/awaymission/museum/cafeteria)
|
||||
"Mg" = (
|
||||
/obj/structure/plaque/static_plaque/golden/commission/tram,
|
||||
/turf/closed/indestructible/reinforced,
|
||||
@@ -4971,6 +4981,12 @@
|
||||
},
|
||||
/turf/open/indestructible/plating,
|
||||
/area/awaymission/museum)
|
||||
"PI" = (
|
||||
/obj/effect/turf_decal/tile/neutral/opposingcorners,
|
||||
/obj/effect/turf_decal/siding/dark_blue,
|
||||
/obj/effect/decal/cleanable/dirt/dust,
|
||||
/turf/open/floor/iron/dark,
|
||||
/area/awaymission/museum/cafeteria)
|
||||
"PK" = (
|
||||
/obj/machinery/door/poddoor{
|
||||
id = "gatewayfake"
|
||||
@@ -5291,7 +5307,7 @@
|
||||
/obj/effect/decal/cleanable/dirt/dust,
|
||||
/obj/structure/fluff/fake_scrubber,
|
||||
/turf/open/floor/iron/white/small,
|
||||
/area/awaymission/museum)
|
||||
/area/awaymission/museum/cafeteria)
|
||||
"So" = (
|
||||
/obj/machinery/shower/directional/east,
|
||||
/turf/open/floor/iron/white/textured_large,
|
||||
@@ -5340,7 +5356,7 @@
|
||||
late_initialize_pop = 1
|
||||
},
|
||||
/turf/open/floor/iron/dark,
|
||||
/area/awaymission/museum)
|
||||
/area/awaymission/museum/cafeteria)
|
||||
"SU" = (
|
||||
/obj/effect/decal/cleanable/dirt/dust,
|
||||
/obj/item/stack/spacecash/c1000,
|
||||
@@ -5491,6 +5507,10 @@
|
||||
/obj/structure/fluff/fake_scrubber,
|
||||
/turf/open/floor/iron,
|
||||
/area/awaymission/museum)
|
||||
"Up" = (
|
||||
/obj/machinery/light/floor,
|
||||
/turf/open/floor/iron,
|
||||
/area/awaymission/museum/cafeteria)
|
||||
"Uq" = (
|
||||
/obj/effect/smooths_with_walls,
|
||||
/turf/cordon/secret,
|
||||
@@ -5543,7 +5563,7 @@
|
||||
/obj/structure/sink/directional/west,
|
||||
/obj/effect/decal/cleanable/blood/oil/slippery,
|
||||
/turf/open/floor/iron/white/small,
|
||||
/area/awaymission/museum)
|
||||
/area/awaymission/museum/cafeteria)
|
||||
"UI" = (
|
||||
/obj/effect/turf_decal/tile/green/opposingcorners,
|
||||
/obj/effect/decal/cleanable/dirt/dust,
|
||||
@@ -5878,7 +5898,7 @@
|
||||
},
|
||||
/obj/machinery/light/small/dim/directional/west,
|
||||
/turf/open/floor/iron/white/small,
|
||||
/area/awaymission/museum)
|
||||
/area/awaymission/museum/cafeteria)
|
||||
"WZ" = (
|
||||
/obj/structure/chair/sofa/bench{
|
||||
dir = 1
|
||||
@@ -6026,7 +6046,7 @@
|
||||
/obj/effect/decal/cleanable/dirt/dust,
|
||||
/obj/structure/fluff/fake_camera,
|
||||
/turf/open/floor/iron/white/small,
|
||||
/area/awaymission/museum)
|
||||
/area/awaymission/museum/cafeteria)
|
||||
"Yr" = (
|
||||
/obj/effect/turf_decal/tile/neutral/opposingcorners,
|
||||
/obj/structure/table/reinforced,
|
||||
@@ -43388,11 +43408,11 @@ re
|
||||
re
|
||||
re
|
||||
re
|
||||
FK
|
||||
Ph
|
||||
HD
|
||||
wi
|
||||
ST
|
||||
FK
|
||||
Ph
|
||||
re
|
||||
re
|
||||
re
|
||||
@@ -43637,17 +43657,17 @@ re
|
||||
re
|
||||
re
|
||||
re
|
||||
FK
|
||||
FK
|
||||
FK
|
||||
FK
|
||||
FK
|
||||
FK
|
||||
FK
|
||||
Ph
|
||||
Ph
|
||||
Ph
|
||||
Ph
|
||||
Ph
|
||||
Ph
|
||||
Ph
|
||||
re
|
||||
FK
|
||||
aa
|
||||
uY
|
||||
Ph
|
||||
PI
|
||||
ms
|
||||
ci
|
||||
jC
|
||||
re
|
||||
@@ -43894,19 +43914,19 @@ re
|
||||
re
|
||||
re
|
||||
re
|
||||
FK
|
||||
Ph
|
||||
aO
|
||||
FK
|
||||
Ph
|
||||
WY
|
||||
FK
|
||||
Ph
|
||||
HW
|
||||
FK
|
||||
FK
|
||||
FK
|
||||
Ph
|
||||
Ph
|
||||
Ph
|
||||
Mb
|
||||
TM
|
||||
Up
|
||||
wV
|
||||
FK
|
||||
Ph
|
||||
re
|
||||
re
|
||||
re
|
||||
@@ -44151,19 +44171,19 @@ re
|
||||
re
|
||||
re
|
||||
re
|
||||
FK
|
||||
Ph
|
||||
wg
|
||||
FK
|
||||
Ph
|
||||
us
|
||||
FK
|
||||
Ph
|
||||
Jp
|
||||
FK
|
||||
Ph
|
||||
um
|
||||
FK
|
||||
Ph
|
||||
Mb
|
||||
uY
|
||||
ms
|
||||
wV
|
||||
FK
|
||||
Ph
|
||||
re
|
||||
re
|
||||
re
|
||||
@@ -44408,17 +44428,17 @@ re
|
||||
re
|
||||
re
|
||||
re
|
||||
FK
|
||||
Gn
|
||||
Gn
|
||||
Gn
|
||||
Ph
|
||||
ia
|
||||
ia
|
||||
ia
|
||||
Sm
|
||||
Gn
|
||||
ia
|
||||
Kz
|
||||
Gn
|
||||
FK
|
||||
ia
|
||||
Ph
|
||||
ju
|
||||
uY
|
||||
ms
|
||||
ci
|
||||
Ir
|
||||
re
|
||||
@@ -44665,19 +44685,19 @@ re
|
||||
re
|
||||
re
|
||||
re
|
||||
FK
|
||||
Ph
|
||||
nY
|
||||
Gn
|
||||
Gn
|
||||
Gn
|
||||
Gn
|
||||
Gn
|
||||
Gn
|
||||
ia
|
||||
ia
|
||||
ia
|
||||
ia
|
||||
ia
|
||||
ia
|
||||
kx
|
||||
uY
|
||||
uY
|
||||
ms
|
||||
ms
|
||||
wV
|
||||
FK
|
||||
Ph
|
||||
re
|
||||
re
|
||||
re
|
||||
@@ -44922,19 +44942,19 @@ re
|
||||
re
|
||||
re
|
||||
re
|
||||
FK
|
||||
Ph
|
||||
ut
|
||||
UH
|
||||
gE
|
||||
CG
|
||||
Gn
|
||||
ia
|
||||
CG
|
||||
Yn
|
||||
FK
|
||||
RC
|
||||
TM
|
||||
Ph
|
||||
sR
|
||||
Up
|
||||
FU
|
||||
FK
|
||||
Ph
|
||||
re
|
||||
re
|
||||
re
|
||||
@@ -45179,19 +45199,19 @@ re
|
||||
re
|
||||
re
|
||||
re
|
||||
FK
|
||||
FK
|
||||
FK
|
||||
FK
|
||||
FK
|
||||
FK
|
||||
FK
|
||||
FK
|
||||
FK
|
||||
Ph
|
||||
Ph
|
||||
Ph
|
||||
Ph
|
||||
Ph
|
||||
Ph
|
||||
Ph
|
||||
Ph
|
||||
Ph
|
||||
Mb
|
||||
uY
|
||||
ms
|
||||
wV
|
||||
FK
|
||||
Ph
|
||||
Uq
|
||||
re
|
||||
re
|
||||
@@ -45444,9 +45464,9 @@ re
|
||||
re
|
||||
re
|
||||
re
|
||||
FK
|
||||
Ph
|
||||
pN
|
||||
uY
|
||||
ms
|
||||
hS
|
||||
oP
|
||||
re
|
||||
@@ -45701,11 +45721,11 @@ re
|
||||
re
|
||||
re
|
||||
re
|
||||
FK
|
||||
FK
|
||||
Ph
|
||||
Ph
|
||||
pz
|
||||
kL
|
||||
FK
|
||||
Ph
|
||||
re
|
||||
re
|
||||
re
|
||||
|
||||
@@ -2113,8 +2113,8 @@
|
||||
/area/awaymission/snowdin/post/hydro)
|
||||
"hZ" = (
|
||||
/obj/item/gun/ballistic/rifle/boltaction,
|
||||
/obj/item/ammo_box/strilka310,
|
||||
/obj/item/ammo_box/strilka310,
|
||||
/obj/item/ammo_box/speedloader/strilka310,
|
||||
/obj/item/ammo_box/speedloader/strilka310,
|
||||
/obj/structure/closet/secure_closet{
|
||||
icon_state = "sec";
|
||||
name = "security officer's locker";
|
||||
|
||||
@@ -36029,12 +36029,9 @@
|
||||
/turf/open/floor/plating,
|
||||
/area/station/engineering/atmos/project)
|
||||
"kpz" = (
|
||||
/obj/structure/rack,
|
||||
/obj/item/aicard,
|
||||
/obj/item/pai_card,
|
||||
/obj/item/circuitboard/aicore,
|
||||
/obj/machinery/power/apc/auto_name/directional/north,
|
||||
/obj/structure/cable,
|
||||
/obj/machinery/modular_computer/preset/research,
|
||||
/turf/open/floor/wood,
|
||||
/area/station/command/heads_quarters/rd)
|
||||
"kpC" = (
|
||||
@@ -39959,6 +39956,10 @@
|
||||
/area/station/commons/fitness/recreation)
|
||||
"lAu" = (
|
||||
/obj/structure/cable,
|
||||
/obj/structure/rack,
|
||||
/obj/item/aicard,
|
||||
/obj/item/pai_card,
|
||||
/obj/item/circuitboard/aicore,
|
||||
/turf/open/floor/wood,
|
||||
/area/station/command/heads_quarters/rd)
|
||||
"lAE" = (
|
||||
@@ -82589,7 +82590,7 @@
|
||||
/turf/open/floor/iron,
|
||||
/area/station/hallway/primary/aft)
|
||||
"xZp" = (
|
||||
/obj/machinery/computer/rdconsole,
|
||||
/obj/machinery/modular_computer/preset/research,
|
||||
/turf/open/floor/carpet,
|
||||
/area/station/command/bridge)
|
||||
"xZG" = (
|
||||
|
||||
@@ -15709,10 +15709,10 @@
|
||||
},
|
||||
/area/station/hallway/primary/fore)
|
||||
"dRh" = (
|
||||
/obj/machinery/telecomms/bus/preset_four,
|
||||
/obj/effect/turf_decal/tile/brown/anticorner/contrasted{
|
||||
dir = 1
|
||||
},
|
||||
/obj/machinery/telecomms/bus/preset_two,
|
||||
/turf/open/floor/iron/telecomms,
|
||||
/area/station/tcommsat/server)
|
||||
"dRo" = (
|
||||
@@ -39973,10 +39973,10 @@
|
||||
/turf/open/floor/iron,
|
||||
/area/station/security/range)
|
||||
"jPC" = (
|
||||
/obj/machinery/telecomms/bus/preset_two,
|
||||
/obj/effect/turf_decal/tile/neutral/anticorner/contrasted{
|
||||
dir = 4
|
||||
},
|
||||
/obj/machinery/telecomms/bus/preset_four,
|
||||
/turf/open/floor/iron/telecomms,
|
||||
/area/station/tcommsat/server)
|
||||
"jPE" = (
|
||||
@@ -47677,9 +47677,6 @@
|
||||
/area/station/engineering/atmos/mix)
|
||||
"lKk" = (
|
||||
/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4,
|
||||
/obj/effect/turf_decal/siding/green/corner{
|
||||
dir = 4
|
||||
},
|
||||
/obj/effect/decal/cleanable/dirt,
|
||||
/obj/effect/landmark/event_spawn,
|
||||
/turf/open/floor/iron,
|
||||
|
||||
@@ -27799,7 +27799,7 @@
|
||||
/obj/item/reagent_containers/cup/glass/drinkingglass/shotglass,
|
||||
/obj/item/reagent_containers/cup/glass/drinkingglass/shotglass,
|
||||
/obj/item/gun/ballistic/revolver/russian,
|
||||
/obj/item/ammo_box/a357,
|
||||
/obj/item/ammo_box/speedloader/c357,
|
||||
/obj/item/reagent_containers/cup/glass/bottle/vodka/badminka,
|
||||
/obj/effect/turf_decal/bot_white/left,
|
||||
/obj/effect/turf_decal/tile/neutral/fourcorners,
|
||||
|
||||
+2878
-2863
File diff suppressed because it is too large
Load Diff
@@ -15284,6 +15284,7 @@
|
||||
dir = 1
|
||||
},
|
||||
/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2,
|
||||
/obj/item/pipe_dispenser,
|
||||
/turf/open/floor/engine,
|
||||
/area/station/engineering/supermatter/room)
|
||||
"cpk" = (
|
||||
@@ -44751,7 +44752,6 @@
|
||||
/obj/structure/table/reinforced,
|
||||
/obj/item/t_scanner,
|
||||
/obj/item/pipe_dispenser,
|
||||
/obj/item/pipe_dispenser,
|
||||
/obj/item/storage/belt/utility,
|
||||
/obj/effect/turf_decal/bot,
|
||||
/obj/machinery/atmospherics/pipe/smart/simple/scrubbers/visible,
|
||||
|
||||
@@ -9129,8 +9129,8 @@
|
||||
/area/centcom/central_command_areas/courtroom)
|
||||
"QY" = (
|
||||
/obj/item/storage/box/handcuffs,
|
||||
/obj/item/ammo_box/a357,
|
||||
/obj/item/ammo_box/a357,
|
||||
/obj/item/ammo_box/speedloader/c357,
|
||||
/obj/item/ammo_box/speedloader/c357,
|
||||
/obj/item/gun/ballistic/revolver/mateba,
|
||||
/obj/structure/table/reinforced,
|
||||
/obj/machinery/firealarm/directional/south,
|
||||
|
||||
@@ -256,6 +256,10 @@
|
||||
/obj/structure/cable,
|
||||
/turf/open/floor/catwalk_floor,
|
||||
/area/station/maintenance/department/crew_quarters/dorms)
|
||||
"Gv" = (
|
||||
/obj/effect/landmark/firealarm_sanity,
|
||||
/turf/open/floor/grass,
|
||||
/area/station/asteroid)
|
||||
"GE" = (
|
||||
/obj/structure/flora/bush/flowers_br/style_random,
|
||||
/turf/open/floor/grass,
|
||||
@@ -1082,7 +1086,7 @@ GE
|
||||
vg
|
||||
ci
|
||||
rO
|
||||
rO
|
||||
Gv
|
||||
rO
|
||||
rO
|
||||
Cp
|
||||
|
||||
@@ -45250,7 +45250,7 @@
|
||||
/obj/structure/safe/vault,
|
||||
/obj/item/clothing/head/costume/bearpelt,
|
||||
/obj/item/gun/ballistic/revolver/russian,
|
||||
/obj/item/ammo_box/a357,
|
||||
/obj/item/ammo_box/speedloader/c357,
|
||||
/obj/effect/turf_decal/bot_white/left,
|
||||
/obj/effect/turf_decal/tile/neutral/fourcorners,
|
||||
/obj/machinery/light/dim/directional/east,
|
||||
|
||||
@@ -45211,6 +45211,7 @@
|
||||
pixel_x = -3;
|
||||
pixel_y = 3
|
||||
},
|
||||
/obj/item/clothing/gloves/color/yellow,
|
||||
/turf/open/floor/iron/textured,
|
||||
/area/station/engineering/storage/tech)
|
||||
"pEk" = (
|
||||
|
||||
@@ -6,9 +6,9 @@
|
||||
/area/centcom/basketball)
|
||||
"aw" = (
|
||||
/obj/structure/table,
|
||||
/obj/item/ammo_box/strilka310,
|
||||
/obj/item/ammo_box/strilka310,
|
||||
/obj/item/ammo_box/strilka310,
|
||||
/obj/item/ammo_box/speedloader/strilka310,
|
||||
/obj/item/ammo_box/speedloader/strilka310,
|
||||
/obj/item/ammo_box/speedloader/strilka310,
|
||||
/obj/effect/turf_decal/stripes/line{
|
||||
dir = 8
|
||||
},
|
||||
@@ -348,9 +348,9 @@
|
||||
/area/centcom/basketball)
|
||||
"Bd" = (
|
||||
/obj/structure/table,
|
||||
/obj/item/ammo_box/strilka310,
|
||||
/obj/item/ammo_box/strilka310,
|
||||
/obj/item/ammo_box/strilka310,
|
||||
/obj/item/ammo_box/speedloader/strilka310,
|
||||
/obj/item/ammo_box/speedloader/strilka310,
|
||||
/obj/item/ammo_box/speedloader/strilka310,
|
||||
/turf/open/floor/iron/dark,
|
||||
/area/centcom/basketball)
|
||||
"BJ" = (
|
||||
|
||||
@@ -876,7 +876,7 @@
|
||||
/area/deathmatch)
|
||||
"Kz" = (
|
||||
/obj/effect/spawner/random/trash/box,
|
||||
/obj/item/ammo_box/a357,
|
||||
/obj/item/ammo_box/speedloader/c357,
|
||||
/turf/open/indestructible/plating,
|
||||
/area/deathmatch)
|
||||
"KC" = (
|
||||
|
||||
@@ -34,7 +34,7 @@
|
||||
locked = 0
|
||||
},
|
||||
/obj/effect/decal/cleanable/fuel_pool/hivis,
|
||||
/obj/item/ammo_box/c38,
|
||||
/obj/item/ammo_box/speedloader/c38,
|
||||
/obj/effect/turf_decal/stripes/asteroid/line{
|
||||
dir = 6
|
||||
},
|
||||
@@ -242,7 +242,7 @@
|
||||
locked = 0
|
||||
},
|
||||
/obj/effect/decal/cleanable/fuel_pool/hivis,
|
||||
/obj/item/ammo_box/c38,
|
||||
/obj/item/ammo_box/speedloader/c38,
|
||||
/obj/effect/turf_decal/stripes/asteroid/line{
|
||||
dir = 4
|
||||
},
|
||||
@@ -617,7 +617,7 @@
|
||||
/area/deathmatch)
|
||||
"EX" = (
|
||||
/obj/structure/lattice/catwalk,
|
||||
/obj/item/ammo_box/c38/match,
|
||||
/obj/item/ammo_box/speedloader/c38/match,
|
||||
/turf/open/chasm/true/no_smooth/fake_motion_sand/fast,
|
||||
/area/deathmatch)
|
||||
"Fa" = (
|
||||
@@ -932,7 +932,7 @@
|
||||
locked = 0
|
||||
},
|
||||
/obj/effect/decal/cleanable/fuel_pool/hivis,
|
||||
/obj/item/ammo_box/c38,
|
||||
/obj/item/ammo_box/speedloader/c38,
|
||||
/obj/effect/turf_decal/stripes/asteroid/line{
|
||||
dir = 4
|
||||
},
|
||||
|
||||
@@ -564,7 +564,7 @@
|
||||
/area/deathmatch)
|
||||
"Kb" = (
|
||||
/obj/structure/table/reinforced,
|
||||
/obj/item/ammo_box/strilka310/surplus,
|
||||
/obj/item/ammo_box/speedloader/strilka310/surplus,
|
||||
/turf/open/indestructible/dark/smooth_large,
|
||||
/area/deathmatch)
|
||||
"Kr" = (
|
||||
|
||||
@@ -242,7 +242,7 @@
|
||||
/obj/effect/turf_decal/siding/wood{
|
||||
dir = 4
|
||||
},
|
||||
/obj/item/ammo_box/strilka310,
|
||||
/obj/item/ammo_box/speedloader/strilka310,
|
||||
/obj/effect/decal/cleanable/dirt,
|
||||
/obj/structure/railing/corner/end/flip{
|
||||
dir = 8
|
||||
|
||||
@@ -77,7 +77,7 @@
|
||||
/obj/effect/turf_decal/trimline/dark_blue/corner{
|
||||
dir = 8
|
||||
},
|
||||
/obj/item/ammo_box/a357,
|
||||
/obj/item/ammo_box/speedloader/c357,
|
||||
/obj/item/gun/ballistic/revolver/golden,
|
||||
/turf/open/floor/iron/smooth_corner{
|
||||
dir = 8
|
||||
|
||||
@@ -147,25 +147,25 @@
|
||||
"gE" = (
|
||||
/obj/effect/turf_decal/tile/dark_blue/diagonal_edge,
|
||||
/obj/structure/table/reinforced/plasmarglass,
|
||||
/obj/item/ammo_box/c38/match{
|
||||
/obj/item/ammo_box/speedloader/c38/match{
|
||||
pixel_x = -5;
|
||||
pixel_y = 4
|
||||
},
|
||||
/obj/item/ammo_box/c38/match{
|
||||
/obj/item/ammo_box/speedloader/c38/match{
|
||||
pixel_x = -1;
|
||||
pixel_y = 4
|
||||
},
|
||||
/obj/item/ammo_box/c38/match{
|
||||
/obj/item/ammo_box/speedloader/c38/match{
|
||||
pixel_x = 3;
|
||||
pixel_y = 4
|
||||
},
|
||||
/obj/item/ammo_box/c38/match{
|
||||
/obj/item/ammo_box/speedloader/c38/match{
|
||||
pixel_x = -8
|
||||
},
|
||||
/obj/item/ammo_box/c38/match{
|
||||
/obj/item/ammo_box/speedloader/c38/match{
|
||||
pixel_x = -4
|
||||
},
|
||||
/obj/item/ammo_box/c38/match,
|
||||
/obj/item/ammo_box/speedloader/c38/match,
|
||||
/turf/open/floor/iron/white/diagonal,
|
||||
/area/shuttle/hunter)
|
||||
"gW" = (
|
||||
|
||||
@@ -173,10 +173,10 @@
|
||||
/obj/structure/closet/crate/secure/weapon{
|
||||
name = "surplus crate"
|
||||
},
|
||||
/obj/item/ammo_box/strilka310,
|
||||
/obj/item/ammo_box/strilka310,
|
||||
/obj/item/ammo_box/strilka310,
|
||||
/obj/item/ammo_box/strilka310,
|
||||
/obj/item/ammo_box/speedloader/strilka310,
|
||||
/obj/item/ammo_box/speedloader/strilka310,
|
||||
/obj/item/ammo_box/speedloader/strilka310,
|
||||
/obj/item/ammo_box/speedloader/strilka310,
|
||||
/turf/open/floor/pod/dark,
|
||||
/area/shuttle/hunter/russian)
|
||||
"qF" = (
|
||||
@@ -611,7 +611,7 @@
|
||||
/obj/effect/decal/cleanable/dirt,
|
||||
/obj/item/gun/ballistic/automatic/pistol,
|
||||
/obj/item/ammo_box/magazine/m9mm,
|
||||
/obj/item/ammo_box/strilka310,
|
||||
/obj/item/ammo_box/speedloader/strilka310,
|
||||
/obj/item/crowbar,
|
||||
/turf/open/floor/pod/dark,
|
||||
/area/shuttle/hunter/russian)
|
||||
|
||||
@@ -802,18 +802,18 @@
|
||||
dir = 8
|
||||
},
|
||||
/obj/effect/turf_decal/bot,
|
||||
/obj/item/ammo_box/strilka310/phasic{
|
||||
/obj/item/ammo_box/speedloader/strilka310/phasic{
|
||||
pixel_y = -5;
|
||||
pixel_x = 5
|
||||
},
|
||||
/obj/item/ammo_box/strilka310/phasic{
|
||||
/obj/item/ammo_box/speedloader/strilka310/phasic{
|
||||
pixel_x = 5
|
||||
},
|
||||
/obj/item/ammo_box/strilka310/phasic{
|
||||
/obj/item/ammo_box/speedloader/strilka310/phasic{
|
||||
pixel_x = -5;
|
||||
pixel_y = -5
|
||||
},
|
||||
/obj/item/ammo_box/strilka310/phasic{
|
||||
/obj/item/ammo_box/speedloader/strilka310/phasic{
|
||||
pixel_x = -5
|
||||
},
|
||||
/obj/item/gun/ballistic/rifle/boltaction/prime{
|
||||
|
||||
@@ -2205,11 +2205,11 @@
|
||||
pixel_y = 4
|
||||
},
|
||||
/obj/item/ammo_box/c10mm,
|
||||
/obj/item/ammo_box/a357{
|
||||
/obj/item/ammo_box/speedloader/c357{
|
||||
icon_state = "357-7";
|
||||
pixel_y = 3
|
||||
},
|
||||
/obj/item/ammo_box/a357{
|
||||
/obj/item/ammo_box/speedloader/c357{
|
||||
icon_state = "357-7";
|
||||
pixel_x = 2
|
||||
},
|
||||
@@ -2360,7 +2360,7 @@
|
||||
/obj/item/storage/lockbox/medal{
|
||||
req_access = list("syndicate_leader")
|
||||
},
|
||||
/obj/item/ammo_box/a357{
|
||||
/obj/item/ammo_box/speedloader/c357{
|
||||
icon_state = "357-7";
|
||||
pixel_x = 2
|
||||
},
|
||||
|
||||
@@ -4096,7 +4096,7 @@
|
||||
/area/virtual_domain)
|
||||
"Il" = (
|
||||
/obj/structure/lattice,
|
||||
/obj/item/ammo_box/strilka310/surplus,
|
||||
/obj/item/ammo_box/speedloader/strilka310/surplus,
|
||||
/turf/open/space/basic,
|
||||
/area/virtual_domain)
|
||||
"Io" = (
|
||||
|
||||
@@ -236,16 +236,22 @@ GLOBAL_LIST_INIT(shove_disarming_types, typecacheof(list(
|
||||
// Ammo box multiload defines
|
||||
/// Ammo box does not accept multiload in or out, e.g. ammo box CANNOT transfer multiple casings in one action, either IN or OUT.
|
||||
#define AMMO_BOX_MULTILOAD_NONE 0
|
||||
/// Ammo box accepts multiload going in, e.g. ammo box can transfer multiple casings IN at once.
|
||||
/// Ammo box accepts multiload going in, e.g. a magazine being fed from a stripper clip.
|
||||
#define AMMO_BOX_MULTILOAD_IN (1 << 0)
|
||||
/// Ammo box accepts multiload going out, e.g. ammo box can transfer multiple casings OUT at once.
|
||||
/// Ammo box can multiload going out to other ammo boxes, but not loaded magazines, e.g. an ammo box feeding into an unloaded magazine.
|
||||
#define AMMO_BOX_MULTILOAD_OUT (1 << 1)
|
||||
/// Ammo box can multiload going out into loaded magazines, e.g. a speedloader feeding into a revolver's cylinder or a stripper clip feeding into a loaded magazine.
|
||||
#define AMMO_BOX_MULTILOAD_OUT_LOADED (1 << 2)
|
||||
/// Ammo box accepts multiload in AND out, e.g. ammo box can transfer multiple casings IN at once *and* OUT at once.
|
||||
#define AMMO_BOX_MULTILOAD_BOTH AMMO_BOX_MULTILOAD_IN | AMMO_BOX_MULTILOAD_OUT
|
||||
/// Ammo boxes are assumed to have some variety of magazine loading assistance.
|
||||
#define AMMO_BOX_MULTILOAD_BOTH (AMMO_BOX_MULTILOAD_IN | AMMO_BOX_MULTILOAD_OUT)
|
||||
/// Ammo box can accept multiloads, AND can give multiloads to boxes that are loaded or not loaded. Individual stripper clips would count for this.
|
||||
#define AMMO_BOX_MULTILOAD_ALL (AMMO_BOX_MULTILOAD_IN | AMMO_BOX_MULTILOAD_OUT | AMMO_BOX_MULTILOAD_OUT_LOADED)
|
||||
|
||||
DEFINE_BITFIELD(ammo_box_multiload, list(
|
||||
"LOAD_IN" = AMMO_BOX_MULTILOAD_IN,
|
||||
"LOAD_OUT" = AMMO_BOX_MULTILOAD_OUT,
|
||||
"LOAD_OUT_LOADED" = AMMO_BOX_MULTILOAD_OUT_LOADED,
|
||||
))
|
||||
|
||||
#define SUPPRESSED_NONE 0
|
||||
|
||||
@@ -65,16 +65,15 @@
|
||||
#define COMSIG_MOVABLE_CANCEL_HEARING (1<<0)
|
||||
///from base of atom/movable/Hear(): (proc args list(message, atom/movable/speaker, message_language, raw_message, radio_freq, list/spans, list/message_mods = list(), message_range))
|
||||
#define COMSIG_MOVABLE_HEAR "movable_hear"
|
||||
#define HEARING_MESSAGE 1
|
||||
#define HEARING_SPEAKER 2
|
||||
#define HEARING_LANGUAGE 3
|
||||
#define HEARING_RAW_MESSAGE 4
|
||||
#define HEARING_RADIO_FREQ 5
|
||||
#define HEARING_RADIO_FREQ_NAME 6
|
||||
#define HEARING_RADIO_FREQ_COLOR 7
|
||||
#define HEARING_SPANS 8
|
||||
#define HEARING_MESSAGE_MODE 9
|
||||
#define HEARING_RANGE 10
|
||||
#define HEARING_SPEAKER 1
|
||||
#define HEARING_LANGUAGE 2
|
||||
#define HEARING_RAW_MESSAGE 3
|
||||
#define HEARING_RADIO_FREQ 4
|
||||
#define HEARING_RADIO_FREQ_NAME 5
|
||||
#define HEARING_RADIO_FREQ_COLOR 6
|
||||
#define HEARING_SPANS 7
|
||||
#define HEARING_MESSAGE_MODE 8
|
||||
#define HEARING_RANGE 9
|
||||
|
||||
///called when space wind can't move a movable. (pressure_difference, pressure_direction)
|
||||
#define COMSIG_MOVABLE_RESISTED_SPACEWIND "movable_resisted_wind"
|
||||
@@ -116,7 +115,7 @@
|
||||
#define MOVABLE_SAY_QUOTE_MESSAGE_SPANS 2
|
||||
#define MOVABLE_SAY_QUOTE_MESSAGE_MODS 3
|
||||
|
||||
/// From /datum/element/immerse/proc/add_submerge_overlay(): (visual_overlay)
|
||||
/// From /datum/element/immerse/proc/add_immerse_overlay(): (atom/movable/immerse_mask/effect_relay)
|
||||
#define COMSIG_MOVABLE_EDIT_UNIQUE_IMMERSE_OVERLAY "movable_edit_unique_submerge_overlay"
|
||||
/// From base of area/Exited(): (area/left, direction)
|
||||
#define COMSIG_MOVABLE_EXITED_AREA "movable_exited_area"
|
||||
|
||||
@@ -351,4 +351,7 @@
|
||||
#define COMSIG_LIVING_GHOSTROLE_INFO "living_ghostrole_info"
|
||||
|
||||
///from mob/living/befriend()
|
||||
#define COMSIG_LIVING_MADE_NEW_FRIEND "made_new_friend"
|
||||
#define COMSIG_LIVING_MADE_NEW_FRIEND "living_made_new_friend"
|
||||
|
||||
/// From /mob/living/update_offsets(animate) : (new_x, new_y, new_w, new_z, animate)
|
||||
#define COMSIG_LIVING_UPDATE_OFFSETS "living_update_offsets"
|
||||
|
||||
@@ -270,13 +270,6 @@
|
||||
#define GASFIRE_LAYER 5.05
|
||||
#define RIPPLE_LAYER 5.1
|
||||
|
||||
/**
|
||||
* The layer of the visual overlay used in the submerge element.
|
||||
* The vis overlay inherits the planes of the movables it's attached to (that also have KEEP_TOGETHER added)
|
||||
* We just have to make sure the visual overlay is rendered above all the other overlays of those movables.
|
||||
*/
|
||||
#define WATER_VISUAL_OVERLAY_LAYER 1000
|
||||
|
||||
// SEETHROUGH_PLANE layers here, tho it has no layer values
|
||||
|
||||
//---------- LIGHTING -------------
|
||||
|
||||
@@ -25,6 +25,7 @@
|
||||
#define BORGTHERM (1<<1)
|
||||
#define BORGXRAY (1<<2)
|
||||
#define BORGMATERIAL (1<<3)
|
||||
#define BORGDEFAULT 0
|
||||
|
||||
//for clothing visor toggles, these determine which vars to toggle
|
||||
#define VISOR_FLASHPROTECT (1<<0)
|
||||
|
||||
@@ -1192,11 +1192,6 @@ Remember to update _globalvars/traits.dm if you're adding/removing/renaming trai
|
||||
#define TRAIT_ELEVATING_OBJECT "elevating_object"
|
||||
/// From [/datum/element/elevation_core] for purpose of checking if the turf has the trait from an instance of the element
|
||||
#define TRAIT_ELEVATED_TURF "elevated_turf"
|
||||
/**
|
||||
* With this, the immerse overlay will give the atom its own submersion visual overlay
|
||||
* instead of one that's also shared with other movables, thus making editing its appearance possible.
|
||||
*/
|
||||
#define TRAIT_UNIQUE_IMMERSE "unique_immerse"
|
||||
|
||||
/// This item is currently under the control of telekinesis
|
||||
#define TRAIT_TELEKINESIS_CONTROLLED "telekinesis_controlled"
|
||||
|
||||
@@ -272,19 +272,19 @@ GLOBAL_LIST_INIT(wounding_types_to_series, list(
|
||||
RETURN_TYPE(/datum/wound) // note that just because its set to return this doesnt mean its non-nullable
|
||||
|
||||
var/list/wounding_type_list = list()
|
||||
for (var/wounding_type as anything in wounding_types)
|
||||
for (var/wounding_type in wounding_types)
|
||||
wounding_type_list += GLOB.wounding_types_to_series[wounding_type]
|
||||
if (!length(wounding_type_list))
|
||||
return null
|
||||
|
||||
var/list/datum/wound/paths_to_pick_from = list()
|
||||
for (var/series as anything in shuffle(wounding_type_list))
|
||||
for (var/series in shuffle(wounding_type_list))
|
||||
var/list/severity_list = GLOB.wound_series_collections[series]
|
||||
if (!length(severity_list))
|
||||
continue
|
||||
|
||||
var/picked_severity
|
||||
for (var/severity_text as anything in shuffle(GLOB.wound_severities_chronological))
|
||||
for (var/severity_text in shuffle(GLOB.wound_severities_chronological))
|
||||
var/severity = text2num(severity_text)
|
||||
if (!ISINRANGE(severity, severity_min, severity_max))
|
||||
continue
|
||||
|
||||
@@ -197,6 +197,7 @@
|
||||
} while(FALSE)
|
||||
|
||||
#define SORT_FIRST_INDEX(list) (list[1])
|
||||
#define SORT_PRIORITY_INDEX(list) (list["priority"])
|
||||
#define SORT_COMPARE_DIRECTLY(thing) (thing)
|
||||
#define SORT_VAR_NO_TYPE(varname) var/varname
|
||||
/****
|
||||
|
||||
@@ -6,9 +6,7 @@
|
||||
var/gun_neurons_activated = controller.blackboard[BB_MONKEY_GUN_NEURONS_ACTIVATED]
|
||||
var/top_force = 0
|
||||
var/obj/item/top_force_item
|
||||
for(var/obj/item/item as anything in held_weapons)
|
||||
if(!item)
|
||||
continue
|
||||
for(var/obj/item/item in held_weapons)
|
||||
if(HAS_TRAIT(item, TRAIT_NEEDS_TWO_HANDS) || controller.blackboard[BB_MONKEY_BLACKLISTITEMS][item])
|
||||
continue
|
||||
if(gun_neurons_activated && isgun(item))
|
||||
@@ -19,9 +17,7 @@
|
||||
top_force = item.force
|
||||
top_force_item = item
|
||||
|
||||
for(var/obj/item/item as anything in choices)
|
||||
if(!item)
|
||||
continue
|
||||
for(var/obj/item/item in choices)
|
||||
if(HAS_TRAIT(item, TRAIT_NEEDS_TWO_HANDS) || controller.blackboard[BB_MONKEY_BLACKLISTITEMS][item])
|
||||
continue
|
||||
if(gun_neurons_activated && isgun(item))
|
||||
|
||||
@@ -89,7 +89,7 @@
|
||||
var/list/material_map_amounts = list()
|
||||
for(var/atom/object as anything in reccursive_contents)
|
||||
var/list/item_materials = object.custom_materials
|
||||
for(var/mat as anything in custom_materials)
|
||||
for(var/mat in custom_materials)
|
||||
var/mat_amount = 1 //no materials mean we assign this default amount
|
||||
if(length(item_materials))
|
||||
mat_amount = item_materials[mat] || 1 //if this object doesn't have our material type then assign a default value of 1
|
||||
@@ -104,7 +104,7 @@
|
||||
mat_list_per_item += mat_amount
|
||||
|
||||
//Step 3: normalize & scale material_map_amounts with material_map_sum
|
||||
for(var/mat as anything in material_map_amounts)
|
||||
for(var/mat in material_map_amounts)
|
||||
var/mat_sum = material_map_sum[mat]
|
||||
var/list/mat_per_item = material_map_amounts[mat]
|
||||
for(var/i in 1 to mat_per_item.len)
|
||||
@@ -114,7 +114,7 @@
|
||||
var/index = 1
|
||||
for(var/atom/object as anything in reccursive_contents)
|
||||
var/list/final_material_list = list()
|
||||
for(var/mat as anything in material_map_amounts)
|
||||
for(var/mat in material_map_amounts)
|
||||
var/list/mat_per_item = material_map_amounts[mat]
|
||||
final_material_list[mat] = mat_per_item[index]
|
||||
object.set_custom_materials(final_material_list, multiplier)
|
||||
|
||||
@@ -34,6 +34,7 @@ GLOBAL_LIST_INIT(duplicate_forbidden_vars, list(
|
||||
"parent",
|
||||
"parent_type",
|
||||
"power_supply",
|
||||
"pixloc",
|
||||
"quirks",
|
||||
"reagents",
|
||||
"_signal_procs",
|
||||
@@ -65,14 +66,16 @@ GLOBAL_PROTECT(duplicate_forbidden_vars)
|
||||
|
||||
var/atom/made_copy = new original.type(spawning_location)
|
||||
|
||||
for(var/atom_vars in original.vars - GLOB.duplicate_forbidden_vars)
|
||||
if(islist(original.vars[atom_vars]))
|
||||
var/list/var_list = original.vars[atom_vars]
|
||||
made_copy.vars[atom_vars] = var_list.Copy()
|
||||
continue
|
||||
else if(istype(original.vars[atom_vars], /datum) || ismob(original.vars[atom_vars]))
|
||||
for(var/atom_vars in (original.vars - GLOB.duplicate_forbidden_vars))
|
||||
var/var_value = original.vars[atom_vars]
|
||||
if(isdatum(var_value))
|
||||
continue // this would reference the original's object, that will break when it is used or deleted.
|
||||
made_copy.vars[atom_vars] = original.vars[atom_vars]
|
||||
|
||||
if(islist(var_value))
|
||||
var/list/var_list = var_value
|
||||
var_value = var_list.Copy()
|
||||
|
||||
made_copy.vars[atom_vars] = var_value
|
||||
|
||||
if(isliving(made_copy))
|
||||
if(iscarbon(made_copy))
|
||||
|
||||
@@ -161,7 +161,7 @@
|
||||
/proc/init_subtypes_w_path_keys(prototype, list/L)
|
||||
if(!istype(L))
|
||||
L = list()
|
||||
for(var/path as anything in subtypesof(prototype))
|
||||
for(var/path in subtypesof(prototype))
|
||||
L[path] = new path()
|
||||
return L
|
||||
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
|
||||
playsound(origin_turf, 'sound/items/airhorn/airhorn.ogg', 100, TRUE)
|
||||
|
||||
for(var/mob/living/carbon/victim as anything in hearers(max(light_range, medium_range, heavy_range), origin_turf))
|
||||
for(var/mob/living/carbon/victim in hearers(max(light_range, medium_range, heavy_range), origin_turf))
|
||||
if(!victim.can_hear())
|
||||
continue
|
||||
var/distance = get_dist(origin_turf, victim.loc)
|
||||
|
||||
@@ -29,6 +29,9 @@
|
||||
/obj/item/organ = "ORGAN",
|
||||
/obj/item/mod/control = "MODSUIT",
|
||||
/obj/item/mod/module = "MODSUIT_MOD",
|
||||
/obj/item/ammo_box = "AMMOBOX",
|
||||
/obj/item/ammo_box/magazine = "AMMOBOX_MAGAZINE",
|
||||
/obj/item/ammo_box/speedloader = "AMMOBOX_SPEEDLOADER",
|
||||
/obj/item/gun = "GUN",
|
||||
/obj/item/gun/magic = "GUN_MAGIC",
|
||||
/obj/item/gun/energy = "GUN_ENERGY",
|
||||
|
||||
@@ -121,7 +121,7 @@ GLOBAL_LIST_INIT(plant_traits, init_plant_traits())
|
||||
// So instead, we're gonna wing it
|
||||
var/list/reagent_to_react_count = list()
|
||||
for(var/datum/chemical_reaction/reaction as anything in reactions)
|
||||
for(var/reagent_id as anything in reaction.required_reagents)
|
||||
for(var/reagent_id in reaction.required_reagents)
|
||||
reagent_to_react_count[reagent_id] += 1
|
||||
|
||||
var/list/reaction_lookup = GLOB.chemical_reactions_list_reactant_index
|
||||
@@ -130,7 +130,7 @@ GLOBAL_LIST_INIT(plant_traits, init_plant_traits())
|
||||
// Doing this separately because it relies on the loop above, and this is easier to parse
|
||||
for(var/datum/chemical_reaction/reaction as anything in reactions)
|
||||
var/preferred_id = null
|
||||
for(var/reagent_id as anything in reaction.required_reagents)
|
||||
for(var/reagent_id in reaction.required_reagents)
|
||||
if(isnull(preferred_id))
|
||||
preferred_id = reagent_id
|
||||
continue
|
||||
@@ -207,5 +207,5 @@ GLOBAL_LIST_INIT(plant_traits, init_plant_traits())
|
||||
only_names = sort_list(only_names)
|
||||
|
||||
//build map with sorted keys
|
||||
for(var/name as anything in only_names)
|
||||
for(var/name in only_names)
|
||||
.[name] = name_to_reagent[name]
|
||||
|
||||
@@ -90,7 +90,6 @@ GLOBAL_LIST_INIT(traits_by_type, list(
|
||||
"TRAIT_STOP_FISH_REPRODUCTION_AND_GROWTH" = TRAIT_STOP_FISH_REPRODUCTION_AND_GROWTH,
|
||||
"TRAIT_TELEKINESIS_CONTROLLED" = TRAIT_TELEKINESIS_CONTROLLED,
|
||||
"TRAIT_UNDERFLOOR" = TRAIT_UNDERFLOOR,
|
||||
"TRAIT_UNIQUE_IMMERSE" = TRAIT_UNIQUE_IMMERSE,
|
||||
"TRAIT_VALID_DNA_INFUSION" = TRAIT_VALID_DNA_INFUSION,
|
||||
"TRAIT_WADDLING" = TRAIT_WADDLING,
|
||||
"TRAIT_WAS_RENAMED" = TRAIT_WAS_RENAMED,
|
||||
|
||||
@@ -213,7 +213,7 @@ GLOBAL_LIST_INIT(available_erp_ui_styles, list(
|
||||
if(should_sight_scale(new_sight) == should_sight_scale(old_sight))
|
||||
return
|
||||
|
||||
for(var/group_key as anything in master_groups)
|
||||
for(var/group_key in master_groups)
|
||||
var/datum/plane_master_group/group = master_groups[group_key]
|
||||
group.build_planes_offset(src, current_plane_offset)
|
||||
|
||||
@@ -237,7 +237,7 @@ GLOBAL_LIST_INIT(available_erp_ui_styles, list(
|
||||
current_plane_offset = new_offset
|
||||
|
||||
SEND_SIGNAL(src, COMSIG_HUD_OFFSET_CHANGED, old_offset, new_offset)
|
||||
for(var/group_key as anything in master_groups)
|
||||
for(var/group_key in master_groups)
|
||||
var/datum/plane_master_group/group = master_groups[group_key]
|
||||
group.build_planes_offset(src, new_offset)
|
||||
|
||||
|
||||
@@ -31,21 +31,21 @@ INITIALIZE_IMMEDIATE(/atom/movable/plane_master_controller)
|
||||
return returned_planes
|
||||
|
||||
///Full override so we can just use filterrific
|
||||
/atom/movable/plane_master_controller/add_filter(name, priority, list/params)
|
||||
/atom/movable/plane_master_controller/add_filter(name, priority, list/params, update = TRUE)
|
||||
. = ..()
|
||||
for(var/atom/movable/screen/plane_master/pm_iterator as anything in get_planes())
|
||||
pm_iterator.add_filter(name, priority, params)
|
||||
pm_iterator.add_filter(name, priority, params, update)
|
||||
|
||||
///Full override so we can just use filterrific
|
||||
/atom/movable/plane_master_controller/remove_filter(name_or_names)
|
||||
/atom/movable/plane_master_controller/remove_filter(name_or_names, update = TRUE)
|
||||
. = ..()
|
||||
for(var/atom/movable/screen/plane_master/pm_iterator as anything in get_planes())
|
||||
pm_iterator.remove_filter(name_or_names)
|
||||
pm_iterator.remove_filter(name_or_names, update)
|
||||
|
||||
/atom/movable/plane_master_controller/update_filters()
|
||||
/atom/movable/plane_master_controller/update_filters(start_index = null)
|
||||
. = ..()
|
||||
for(var/atom/movable/screen/plane_master/pm_iterator as anything in get_planes())
|
||||
pm_iterator.update_filters()
|
||||
pm_iterator.update_filters(start_index)
|
||||
|
||||
///Gets all filters for this controllers plane masters
|
||||
/atom/movable/plane_master_controller/proc/get_filters(name)
|
||||
|
||||
@@ -347,7 +347,7 @@ ADMIN_VERB(cmd_controller_view_ui, R_SERVER|R_DEBUG, "Controller Overview", "Vie
|
||||
|
||||
// Allows subsystems to declare other subsystems that must initialize after them.
|
||||
for(var/datum/controller/subsystem/subsystem as anything in subsystems)
|
||||
for(var/dependent_type as anything in subsystem.dependents)
|
||||
for(var/dependent_type in subsystem.dependents)
|
||||
if(!ispath(dependent_type, /datum/controller/subsystem))
|
||||
stack_trace("ERROR: MC: subsystem `[subsystem.type]` has an invalid dependent: `[dependent_type]`. Skipping")
|
||||
continue
|
||||
@@ -357,7 +357,7 @@ ADMIN_VERB(cmd_controller_view_ui, R_SERVER|R_DEBUG, "Controller Overview", "Vie
|
||||
|
||||
// Constructs a reverse-dependency graph.
|
||||
for(var/datum/controller/subsystem/subsystem as anything in subsystems)
|
||||
for(var/dependency_type as anything in subsystem.dependencies)
|
||||
for(var/dependency_type in subsystem.dependencies)
|
||||
if(!ispath(dependency_type, /datum/controller/subsystem))
|
||||
stack_trace("ERROR: MC: subsystem `[subsystem.type]` has an invalid dependency: `[dependency_type]`. Skipping")
|
||||
continue
|
||||
@@ -1041,4 +1041,3 @@ ADMIN_VERB(cmd_controller_view_ui, R_SERVER|R_DEBUG, "Controller Overview", "Vie
|
||||
return FALSE
|
||||
last_profiled = REALTIMEOFDAY
|
||||
SSprofiler.DumpFile(allow_yield = FALSE)
|
||||
|
||||
|
||||
@@ -431,7 +431,7 @@ Versioning
|
||||
/datum/controller/subsystem/blackbox/proc/ReportRoundstartManifest(list/characters)
|
||||
var/list/query_rows = list()
|
||||
var/list/special_columns = list("server_ip" = "INET_ATON(?)")
|
||||
for(var/mob_ckey as anything in characters)
|
||||
for(var/mob_ckey in characters)
|
||||
var/mob/living/new_character = characters[mob_ckey]
|
||||
query_rows += list(list(
|
||||
"server_ip" = world.internet_address || 0,
|
||||
|
||||
@@ -14,6 +14,6 @@ MOVEMENT_SUBSYSTEM_DEF(ai_movement)
|
||||
|
||||
/datum/controller/subsystem/movement/ai_movement/proc/SetupAIMovementInstances()
|
||||
movement_types = list()
|
||||
for(var/key as anything in subtypesof(/datum/ai_movement))
|
||||
for(var/key in subtypesof(/datum/ai_movement))
|
||||
var/datum/ai_movement/ai_movement = new key
|
||||
movement_types[key] = ai_movement
|
||||
|
||||
@@ -21,26 +21,12 @@ SUBSYSTEM_DEF(ore_generation)
|
||||
*/
|
||||
var/list/ore_vent_minerals = list()
|
||||
|
||||
/// A tracker of how many of each ore vent size we have in the game. Useful for tracking purposes.
|
||||
|
||||
/datum/controller/subsystem/ore_generation/Initialize()
|
||||
//Basically, we're going to round robin through the list of ore vents and assign a mineral to them until complete.
|
||||
while(length(ore_vent_minerals) > 0) //Keep looping if there's more to assign
|
||||
var/stallbreaker = 0
|
||||
for(var/obj/structure/ore_vent/vent as anything in possible_vents)
|
||||
if(length(ore_vent_minerals) <= 0) //But break early if there's none left.
|
||||
break
|
||||
if(vent.unique_vent)
|
||||
continue //Ya'll already got your minerals.
|
||||
if(length(difflist(first = ore_vent_minerals, second = vent.mineral_breakdown, skiprep = 1)))
|
||||
vent.generate_mineral_breakdown(new_minerals = 1, map_loading = TRUE)
|
||||
else
|
||||
stallbreaker++
|
||||
if(stallbreaker >= length(possible_vents))
|
||||
break //We've done all we can here. break inner loop
|
||||
continue
|
||||
if(stallbreaker >= length(possible_vents))
|
||||
break //We've done all we can here. break outer loop
|
||||
for(var/obj/structure/ore_vent/vent as anything in possible_vents)
|
||||
if(vent.unique_vent)
|
||||
continue //Ya'll already got your minerals.
|
||||
vent.generate_mineral_breakdown(map_loading = TRUE)
|
||||
|
||||
/// Handles roundstart logging
|
||||
logger.Log(
|
||||
|
||||
@@ -117,7 +117,7 @@ PROCESSING_SUBSYSTEM_DEF(fishing)
|
||||
continue
|
||||
LAZYOR(fish_safe_turfs_by_type[fish_path], source.associated_safe_turfs)
|
||||
//If a subtype doesn't have set safe turfs, it'll inherit them from the parent type.
|
||||
for(var/fish_type as anything in fish_safe_turfs_by_type)
|
||||
for(var/fish_type in fish_safe_turfs_by_type)
|
||||
for(var/fish_subtype in subtypesof(fish_type))
|
||||
if(!length(fish_safe_turfs_by_type[fish_subtype]))
|
||||
fish_safe_turfs_by_type[fish_subtype] = fish_safe_turfs_by_type[fish_type]
|
||||
|
||||
@@ -34,7 +34,7 @@ PROCESSING_SUBSYSTEM_DEF(greyscale)
|
||||
#endif
|
||||
|
||||
// This final verification step is for things that need other greyscale configurations to be finished loading
|
||||
for(var/greyscale_type as anything in configurations)
|
||||
for(var/greyscale_type in configurations)
|
||||
CHECK_TICK
|
||||
var/datum/greyscale_config/config = configurations[greyscale_type]
|
||||
config.CrossVerify()
|
||||
|
||||
@@ -91,7 +91,7 @@ GLOBAL_LIST_INIT(target_interested_atoms, typecacheof(list(/mob, /obj/machinery/
|
||||
/datum/ai_behavior/find_potential_targets/proc/new_turf_found(turf/found, datum/ai_controller/controller, datum/targeting_strategy/strategy)
|
||||
var/valid_found = FALSE
|
||||
var/mob/pawn = controller.pawn
|
||||
for(var/maybe_target as anything in found)
|
||||
for(var/maybe_target in found)
|
||||
if(maybe_target == pawn)
|
||||
continue
|
||||
if(!is_type_in_typecache(maybe_target, GLOB.target_interested_atoms))
|
||||
@@ -120,7 +120,7 @@ GLOBAL_LIST_INIT(target_interested_atoms, typecacheof(list(/mob, /obj/machinery/
|
||||
/datum/ai_behavior/find_potential_targets/proc/new_atoms_found(list/atom/movable/found, datum/ai_controller/controller, target_key, datum/targeting_strategy/strategy, hiding_location_key)
|
||||
var/mob/pawn = controller.pawn
|
||||
var/list/accepted_targets = list()
|
||||
for(var/maybe_target as anything in found)
|
||||
for(var/maybe_target in found)
|
||||
if(maybe_target == pawn)
|
||||
continue
|
||||
// Need to better handle viewers here
|
||||
|
||||
@@ -97,7 +97,7 @@
|
||||
if (!length(required_traits))
|
||||
return TRUE
|
||||
|
||||
for (var/trait as anything in required_traits)
|
||||
for (var/trait in required_traits)
|
||||
if (HAS_TRAIT(the_target, trait))
|
||||
return TRUE
|
||||
return FALSE
|
||||
|
||||
@@ -95,7 +95,7 @@
|
||||
var/mob/living/living_pawn = controller.pawn
|
||||
|
||||
var/list/nearby_items = list()
|
||||
for (var/obj/new_friend as anything in oview(search_range, controller.pawn))
|
||||
for (var/obj/new_friend in oview(search_range, controller.pawn))
|
||||
if (!isitem(new_friend) && !isstructure(new_friend))
|
||||
continue
|
||||
if (is_type_in_list(new_friend, GLOB.animatable_blacklist))
|
||||
|
||||
@@ -198,7 +198,7 @@
|
||||
var/list/alarms_cache = alarms //Cache for sonic speec
|
||||
for(var/alarm_type in alarms_cache)
|
||||
var/list/alarms_of_type = alarms_cache[alarm_type] //Sonic cache speed forads
|
||||
for(var/area_name as anything in alarms_of_type)
|
||||
for(var/area_name in alarms_of_type)
|
||||
var/list/alarm_packet = alarms_of_type[area_name]
|
||||
var/list/cameras = alarm_packet[2]
|
||||
if(cameras)
|
||||
|
||||
@@ -183,7 +183,7 @@ GLOBAL_LIST_INIT(armor_by_type, generate_armor_type_cache())
|
||||
|
||||
/// Checks if any of the armor values are non-zero, so this technically also counts negative armor!
|
||||
/datum/armor/proc/has_any_armor()
|
||||
for(var/rating as anything in ARMOR_LIST_ALL())
|
||||
for(var/rating in ARMOR_LIST_ALL())
|
||||
if(vars[rating])
|
||||
return TRUE
|
||||
return FALSE
|
||||
|
||||
@@ -216,7 +216,7 @@
|
||||
owner.imaginary_group -= src
|
||||
return ..()
|
||||
|
||||
/mob/eye/imaginary_friend/Hear(message, atom/movable/speaker, datum/language/message_language, raw_message, radio_freq, freq_name, freq_color, list/spans, list/message_mods = list(), message_range)
|
||||
/mob/eye/imaginary_friend/Hear(atom/movable/speaker, datum/language/message_language, raw_message, radio_freq, freq_name, freq_color, list/spans, list/message_mods = list(), message_range)
|
||||
if (safe_read_pref(client, /datum/preference/toggle/enable_runechat) && (safe_read_pref(client, /datum/preference/toggle/enable_runechat_non_mobs) || ismob(speaker)))
|
||||
create_chat_message(speaker, message_language, raw_message, spans)
|
||||
to_chat(src, compose_message(speaker, message_language, raw_message, radio_freq, freq_name, freq_color, spans, message_mods))
|
||||
@@ -257,14 +257,13 @@
|
||||
log_sayverb_talk(message, message_mods, tag = "imaginary friend", forced_by = forced)
|
||||
|
||||
var/messagepart = generate_messagepart(message, spans, message_mods)
|
||||
var/rendered = "[span_name("[name]")] [messagepart]"
|
||||
var/dead_rendered = "[span_name("[name] (Imaginary friend of [owner])")] [messagepart]"
|
||||
|
||||
var/language = message_language || owner.get_selected_language()
|
||||
Hear(rendered, src, language, message, null, null, null, spans, message_mods) // We always hear what we say
|
||||
Hear(src, language, message, null, null, null, spans, message_mods) // We always hear what we say
|
||||
var/group = owner.imaginary_group - src // The people in our group don't, so we have to exclude ourselves not to hear twice
|
||||
for(var/mob/person in group)
|
||||
person.Hear(null, src, language, message, null, null, null, spans, message_mods, range)
|
||||
person.Hear(src, language, message, null, null, null, spans, message_mods, range)
|
||||
|
||||
// Speech bubble, but only for those who have runechat off
|
||||
var/list/speech_bubble_recipients = list()
|
||||
|
||||
@@ -690,7 +690,7 @@
|
||||
talk_tuah(pick(hurt_lines))
|
||||
|
||||
/datum/brain_trauma/special/axedoration/proc/talk_tuah(sent_message = "Hello World.")
|
||||
owner.Hear(null, GLOB.bridge_axe, owner.get_selected_language(), sent_message)
|
||||
owner.Hear(GLOB.bridge_axe, owner.get_selected_language(), sent_message)
|
||||
|
||||
/datum/brain_trauma/special/axedoration/proc/get_axe_location()
|
||||
if(!GLOB.bridge_axe)
|
||||
|
||||
@@ -540,7 +540,7 @@
|
||||
|
||||
var/list/highest_val_list = list(tracked_fish_by_type[1]) //In case there's only one type of fish in here...
|
||||
var/highest_val = -1
|
||||
for(var/fish_type as anything in can_survive_with)
|
||||
for(var/fish_type in can_survive_with)
|
||||
var/list/compatible_types = can_survive_with[fish_type]
|
||||
var/fish_amount = fish_alive_by_type[fish_type]
|
||||
for(var/obj/item/fish/fish_instance as anything in tracked_fish_by_type[fish_type])
|
||||
|
||||
@@ -2,8 +2,9 @@
|
||||
#define CONTENTS_INSTANCES "instances"
|
||||
#define CONTENTS_MACHINERY "machinery"
|
||||
#define CONTENTS_STRUCTURES "structures"
|
||||
#define CONTENTS_REAGENTS "reagents"
|
||||
#define CONTENTS_REQS_COUNT "reqs_count"
|
||||
#define CONTENTS_TOOL_BEHAVIOUR "tool_behaviour"
|
||||
#define CONTENTS_POSSIBLE_TOOLS "tool_instances"
|
||||
|
||||
/// The portion of time spent crafting that recipe dependant on the speed of the tools
|
||||
#define RECIPE_DYNAMIC_TIME_COEFF 0.85
|
||||
@@ -61,7 +62,7 @@
|
||||
var/list/item_instances = contents[CONTENTS_INSTANCES]
|
||||
var/list/machines = contents[CONTENTS_MACHINERY]
|
||||
var/list/structures = contents[CONTENTS_STRUCTURES]
|
||||
contents = contents[CONTENTS_REAGENTS]
|
||||
contents = contents[CONTENTS_REQS_COUNT]
|
||||
|
||||
|
||||
var/list/requirements_list = list()
|
||||
@@ -132,81 +133,68 @@
|
||||
continue
|
||||
. += AM
|
||||
|
||||
/datum/component/personal_crafting/proc/get_surroundings(atom/a, list/blacklist=null)
|
||||
/datum/component/personal_crafting/proc/get_surroundings(atom/source, list/blacklist=null)
|
||||
. = list()
|
||||
.[CONTENTS_TOOL_BEHAVIOUR] = list()
|
||||
.[CONTENTS_REAGENTS] = list()
|
||||
.[CONTENTS_REQS_COUNT] = list()
|
||||
.[CONTENTS_INSTANCES] = list()
|
||||
.[CONTENTS_MACHINERY] = list()
|
||||
.[CONTENTS_STRUCTURES] = list()
|
||||
for(var/obj/object in get_environment(a, blacklist))
|
||||
for(var/obj/object in get_environment(source, blacklist))
|
||||
if(isitem(object))
|
||||
var/obj/item/item = object
|
||||
LAZYADDASSOCLIST(.[CONTENTS_INSTANCES], item.type, item)
|
||||
if(isstack(item))
|
||||
var/obj/item/stack/stack = item
|
||||
.[CONTENTS_REAGENTS][item.type] += stack.amount
|
||||
.[CONTENTS_REQS_COUNT][item.type] += stack.amount
|
||||
else
|
||||
.[CONTENTS_REAGENTS][item.type] += 1
|
||||
.[CONTENTS_REQS_COUNT][item.type] += 1
|
||||
if(is_reagent_container(item) && item.is_drainable() && length(item.reagents.reagent_list)) //some container that has some reagents inside it that can be drained
|
||||
var/obj/item/reagent_containers/container = item
|
||||
for(var/datum/reagent/reagent as anything in container.reagents.reagent_list)
|
||||
.[CONTENTS_REAGENTS][reagent.type] += reagent.volume
|
||||
else //a reagent container that is empty can also be used as a tool. e.g. glass bottle can be used as a rolling pin
|
||||
if(item.tool_behaviour)
|
||||
var/current_tool_speed = .[CONTENTS_TOOL_BEHAVIOUR][item.tool_behaviour]
|
||||
if(current_tool_speed < item.toolspeed)
|
||||
.[CONTENTS_TOOL_BEHAVIOUR][item.tool_behaviour] = item.toolspeed
|
||||
.[CONTENTS_REQS_COUNT][reagent.type] += reagent.volume
|
||||
if(item.tool_behaviour)
|
||||
var/current_tool_speed = .[CONTENTS_TOOL_BEHAVIOUR][item.tool_behaviour]
|
||||
if(current_tool_speed < item.toolspeed)
|
||||
.[CONTENTS_TOOL_BEHAVIOUR][item.tool_behaviour] = item.toolspeed
|
||||
else if (ismachinery(object))
|
||||
LAZYADDASSOCLIST(.[CONTENTS_MACHINERY], object.type, object)
|
||||
else if (isstructure(object))
|
||||
LAZYADDASSOCLIST(.[CONTENTS_STRUCTURES], object.type, object)
|
||||
|
||||
var/list/within_source = list()
|
||||
for(var/obj/item/item in source.contents)
|
||||
within_source += item
|
||||
if(item.atom_storage)
|
||||
within_source += item.contents
|
||||
|
||||
for(var/obj/item/item as anything in within_source)
|
||||
if(!item.tool_behaviour)
|
||||
continue
|
||||
var/current_tool_speed = .[CONTENTS_TOOL_BEHAVIOUR][item.tool_behaviour]
|
||||
if(current_tool_speed < item.toolspeed)
|
||||
.[CONTENTS_TOOL_BEHAVIOUR][item.tool_behaviour] = item.toolspeed
|
||||
|
||||
var/list/instances = .[CONTENTS_INSTANCES]
|
||||
for(var/item_type in instances)
|
||||
.[CONTENTS_POSSIBLE_TOOLS] += instances[item_type]
|
||||
.[CONTENTS_POSSIBLE_TOOLS] += within_source
|
||||
|
||||
/// Returns a boolean on whether the tool requirements of the input recipe are satisfied by the input source and surroundings.
|
||||
/datum/component/personal_crafting/proc/check_tools(atom/source, datum/crafting_recipe/recipe, list/surroundings, final_check = FALSE)
|
||||
if(!length(recipe.tool_behaviors) && !length(recipe.tool_paths))
|
||||
return TRUE
|
||||
|
||||
var/list/available_tools = list()
|
||||
var/list/present_qualities = list()
|
||||
|
||||
var/list/all_instances = list()
|
||||
for(var/atom/movable/movable as anything in source.contents)
|
||||
all_instances += movable
|
||||
if(movable.atom_storage)
|
||||
all_instances += movable.contents
|
||||
|
||||
for(var/obj/item/contained_item in all_instances) //fill the available tools list with available tool types and behaviours
|
||||
available_tools[contained_item.type] = TRUE
|
||||
if(contained_item.tool_behaviour)
|
||||
present_qualities[contained_item.tool_behaviour] = TRUE
|
||||
|
||||
for(var/quality in surroundings[CONTENTS_TOOL_BEHAVIOUR])
|
||||
present_qualities[quality] = TRUE
|
||||
|
||||
for(var/path in surroundings[CONTENTS_REAGENTS])
|
||||
available_tools[path] = TRUE
|
||||
|
||||
for(var/required_quality in recipe.tool_behaviors)
|
||||
if(!present_qualities[required_quality])
|
||||
if(!(required_quality in surroundings[CONTENTS_TOOL_BEHAVIOUR]))
|
||||
return FALSE
|
||||
|
||||
var/list/possible_tool_instances = surroundings[CONTENTS_POSSIBLE_TOOLS]
|
||||
for(var/required_path in recipe.tool_paths)
|
||||
var/found_this_tool = FALSE
|
||||
for(var/tool_path in available_tools)
|
||||
if(!ispath(tool_path, required_path))
|
||||
continue
|
||||
found_this_tool = TRUE
|
||||
break
|
||||
if(!found_this_tool)
|
||||
if(!(locate(required_path) in possible_tool_instances))
|
||||
return FALSE
|
||||
|
||||
//add the contents of the assoc list of the surrounding instances to all_instances for the recipe.check_tools() call
|
||||
var/list/surrounding_instances = surroundings[CONTENTS_INSTANCES]
|
||||
for(var/type_key in surrounding_instances)
|
||||
all_instances |= surrounding_instances[type_key]
|
||||
|
||||
return recipe.check_tools(source, all_instances, final_check)
|
||||
return recipe.check_tools(source, possible_tool_instances, final_check)
|
||||
|
||||
/datum/component/personal_crafting/proc/construct_item(atom/crafter, datum/crafting_recipe/recipe)
|
||||
if(!crafter)
|
||||
@@ -233,10 +221,10 @@
|
||||
//Then divide it by the number of tools used in the recipe, and recalculate it.
|
||||
dynamic_recipe_time /= tools_used
|
||||
|
||||
var/instances = contents[CONTENTS_INSTANCES]
|
||||
var/list/possible_tool_instances = contents[CONTENTS_POSSIBLE_TOOLS]
|
||||
for(var/tool in recipe.tool_paths)
|
||||
var/best_speed = 10 //failsafe-ish
|
||||
for(var/obj/item/item as anything in instances)
|
||||
for(var/obj/item/item as anything in possible_tool_instances)
|
||||
if(!istype(item, tool) || best_speed < item.toolspeed)
|
||||
continue
|
||||
best_speed = item.toolspeed
|
||||
@@ -760,6 +748,7 @@
|
||||
#undef CONTENTS_INSTANCES
|
||||
#undef CONTENTS_MACHINERY
|
||||
#undef CONTENTS_STRUCTURES
|
||||
#undef CONTENTS_REAGENTS
|
||||
#undef CONTENTS_REQS_COUNT
|
||||
#undef CONTENTS_TOOL_BEHAVIOUR
|
||||
#undef RECIPE_DYNAMIC_TIME_COEFF
|
||||
#undef CONTENTS_POSSIBLE_TOOLS
|
||||
|
||||
@@ -58,7 +58,7 @@
|
||||
ingredient_names = processed_holder.ingredient_names
|
||||
custom_name = processed_holder.custom_name
|
||||
atom_parent.name = "[custom_adjective()] [custom_name] [atom_parent.name]"
|
||||
for(var/fillcol as anything in processed_holder.filling_colors)
|
||||
for(var/fillcol in processed_holder.filling_colors)
|
||||
apply_fill(fillcol)
|
||||
|
||||
/datum/component/ingredients_holder/Destroy(force)
|
||||
|
||||
@@ -460,10 +460,10 @@
|
||||
|
||||
//we now summarize the chat msgs collected
|
||||
if(!(mat_container_flags & MATCONTAINER_SILENT))
|
||||
for(var/status as anything in chat_msgs)
|
||||
for(var/status in chat_msgs)
|
||||
var/list/status_data = chat_msgs[status]
|
||||
|
||||
for(var/item_name as anything in status_data)
|
||||
for(var/item_name in status_data)
|
||||
//read the params
|
||||
var/list/chat_data = status_data[item_name]
|
||||
var/count = chat_data["count"]
|
||||
|
||||
@@ -52,7 +52,7 @@
|
||||
SIGNAL_HANDLER
|
||||
RegisterSignal(new_friend, COMSIG_KB_LIVING_VIEW_PET_COMMANDS, PROC_REF(on_key_pressed))
|
||||
RegisterSignal(new_friend, DEACTIVATE_KEYBIND(COMSIG_KB_LIVING_VIEW_PET_COMMANDS), PROC_REF(on_key_unpressed))
|
||||
for (var/command_name as anything in available_commands)
|
||||
for (var/command_name in available_commands)
|
||||
var/datum/pet_command/command = available_commands[command_name]
|
||||
INVOKE_ASYNC(command, TYPE_PROC_REF(/datum/pet_command, add_new_friend), new_friend)
|
||||
|
||||
@@ -71,7 +71,7 @@
|
||||
COMSIG_KB_LIVING_VIEW_PET_COMMANDS,
|
||||
DEACTIVATE_KEYBIND(COMSIG_KB_LIVING_VIEW_PET_COMMANDS),
|
||||
))
|
||||
for (var/command_name as anything in available_commands)
|
||||
for (var/command_name in available_commands)
|
||||
var/datum/pet_command/command = available_commands[command_name]
|
||||
INVOKE_ASYNC(command, TYPE_PROC_REF(/datum/pet_command, remove_friend), old_friend)
|
||||
|
||||
@@ -116,7 +116,7 @@
|
||||
/// Actually display the radial menu and then do something with the result
|
||||
/datum/component/obeys_commands/proc/display_radial_menu(mob/living/friend)
|
||||
var/list/radial_options = list()
|
||||
for (var/command_name as anything in available_commands)
|
||||
for (var/command_name in available_commands)
|
||||
var/datum/pet_command/command = available_commands[command_name]
|
||||
var/datum/radial_menu_choice/choice = command.provide_radial_data()
|
||||
if (!choice)
|
||||
|
||||
@@ -107,7 +107,7 @@
|
||||
* if check_verbosity is true, skip the match if there spoken_text is way longer than the match
|
||||
*/
|
||||
/datum/pet_command/proc/find_command_in_text(spoken_text, check_verbosity = FALSE)
|
||||
for (var/command as anything in speech_commands)
|
||||
for (var/command in speech_commands)
|
||||
if (!findtext(spoken_text, command))
|
||||
continue
|
||||
if(check_verbosity && length(spoken_text) > length(command) + MAX_NAME_LEN)
|
||||
@@ -220,5 +220,3 @@
|
||||
return FALSE
|
||||
parent.visible_message(span_warning("[parent] follows [friend]'s gesture towards [potential_target] [pointed_reaction]!"))
|
||||
return TRUE
|
||||
|
||||
|
||||
|
||||
@@ -19,7 +19,7 @@
|
||||
src.regeneration_time = regeneration_time
|
||||
|
||||
var/atom/movable/living_parent = parent
|
||||
for(var/type_path as anything in shield_overlays)
|
||||
for(var/type_path in shield_overlays)
|
||||
if(!ispath(type_path))
|
||||
continue
|
||||
var/obj/effect/overlay/new_effect = new type_path()
|
||||
|
||||
@@ -185,7 +185,8 @@
|
||||
if(seat.buckle_lying && rider.body_position == LYING_DOWN)
|
||||
y_offset += (-1 * PIXEL_Y_OFFSET_LYING)
|
||||
|
||||
rider.add_offsets(RIDING_SOURCE, x_add = x_offset, y_add = y_offset, animate = animate)
|
||||
// Rider uses pixel_z offsets as they're above the turf, not up north on the turf
|
||||
rider.add_offsets(RIDING_SOURCE, x_add = x_offset, z_add = y_offset, animate = animate)
|
||||
rider.layer = layer
|
||||
|
||||
#undef GET_X_OFFSET
|
||||
|
||||
@@ -210,7 +210,7 @@
|
||||
))
|
||||
|
||||
var/list/remaining_stock = list()
|
||||
for(var/item as anything in stock_list)
|
||||
for(var/item in stock_list)
|
||||
remaining_stock[item] = stock_list[item]
|
||||
data["extra_purchasable"] = extra_purchasable
|
||||
data["extra_purchasable_stock"] = extra_purchasable_stock
|
||||
|
||||
+113
-69
@@ -55,9 +55,12 @@
|
||||
*/
|
||||
var/list/cooldowns
|
||||
|
||||
|
||||
/// List for handling persistent filters.
|
||||
var/list/filter_data
|
||||
/// An accursed beast of a list that contains our filters. Why? Because var/list/filters on atoms/images isn't actually a list
|
||||
/// but a snowflaked skinwalker pretending to be one, which doesn't support half the list procs/operations and the other half behaves weirdly
|
||||
/// so we cut down on filter creation and appearance update costs by editing *this* list, and then assigning ours to it
|
||||
var/list/filter_cache
|
||||
|
||||
#ifdef REFERENCE_TRACKING
|
||||
/// When was this datum last touched by a reftracker?
|
||||
@@ -321,38 +324,67 @@
|
||||
* * name - Filter name
|
||||
* * priority - Priority used when sorting the filter.
|
||||
* * params - Parameters of the filter.
|
||||
* * update - If we should update our actual filters list, or wait until something updates it later
|
||||
*/
|
||||
/datum/proc/add_filter(name, priority, list/params)
|
||||
LAZYINITLIST(filter_data)
|
||||
var/list/copied_parameters = params.Copy()
|
||||
copied_parameters["priority"] = priority
|
||||
filter_data[name] = copied_parameters
|
||||
update_filters()
|
||||
|
||||
///A version of add_filter that takes a list of filters to add rather than being individual, to limit calls to update_filters().
|
||||
/datum/proc/add_filters(list/list/filters)
|
||||
LAZYINITLIST(filter_data)
|
||||
for(var/list/individual_filter as anything in filters)
|
||||
var/list/params = individual_filter["params"]
|
||||
var/list/copied_parameters = params.Copy()
|
||||
copied_parameters["priority"] = individual_filter["priority"]
|
||||
filter_data[individual_filter["name"]] = copied_parameters
|
||||
update_filters()
|
||||
|
||||
/// Reapplies all the filters.
|
||||
/datum/proc/update_filters()
|
||||
/datum/proc/add_filter(name, priority, list/params, update = TRUE)
|
||||
ASSERT(isatom(src) || isimage(src))
|
||||
var/atom/atom_cast = src // filters only work with images or atoms.
|
||||
atom_cast.filters = null
|
||||
sortTim(filter_data, GLOBAL_PROC_REF(cmp_filter_data_priority), TRUE)
|
||||
for(var/filter_raw in filter_data)
|
||||
var/list/data = filter_data[filter_raw]
|
||||
var/list/arguments = data.Copy()
|
||||
LAZYINITLIST(filter_data)
|
||||
LAZYINITLIST(filter_cache)
|
||||
var/list/copied_parameters = params.Copy()
|
||||
copied_parameters["name"] = name
|
||||
copied_parameters["priority"] = priority
|
||||
for (var/list/filter_info as anything in filter_data)
|
||||
if (filter_info["name"] == name)
|
||||
filter_data -= filter_info
|
||||
filter_cache -= name
|
||||
break
|
||||
|
||||
BINARY_INSERT_DEFINE(list(copied_parameters), filter_data, SORT_VAR_NO_TYPE, copied_parameters, SORT_PRIORITY_INDEX, COMPARE_KEY)
|
||||
|
||||
for (var/index in 1 to length(filter_data))
|
||||
var/list/filter_info = filter_data[index]
|
||||
if (filter_info["name"] != name)
|
||||
continue
|
||||
var/list/arguments = filter_info.Copy()
|
||||
arguments -= "priority"
|
||||
atom_cast.filters += filter(arglist(arguments))
|
||||
filter_cache.Insert(index, filter(arglist(arguments)))
|
||||
break
|
||||
|
||||
if (update)
|
||||
atom_cast.filters = filter_cache
|
||||
|
||||
/// A version of add_filter that takes a list of filters to add rather than being individual, to limit appearance updates
|
||||
/datum/proc/add_filters(list/list/filters, update = TRUE)
|
||||
ASSERT(isatom(src) || isimage(src))
|
||||
var/atom/atom_cast = src // filters only work with images or atoms.
|
||||
for (var/list/individual_filter as anything in filters)
|
||||
add_filter(individual_filter["name"], individual_filter["priority"], individual_filter["params"], update = FALSE)
|
||||
if (update)
|
||||
atom_cast.filters = filter_cache
|
||||
|
||||
/// Reapplies all the filters. If start_index is passed, only a portion of all filters are reapplied starting from said index
|
||||
/datum/proc/update_filters(start_index = null)
|
||||
ASSERT(isatom(src) || isimage(src))
|
||||
var/atom/atom_cast = src // filters only work with images or atoms.
|
||||
if (start_index)
|
||||
filter_cache.Cut(start_index)
|
||||
else
|
||||
atom_cast.filters = null
|
||||
filter_cache.Cut()
|
||||
|
||||
for (var/index in start_index || 1 to length(filter_data))
|
||||
var/list/filter_info = filter_data[index]
|
||||
var/list/arguments = filter_info.Copy()
|
||||
arguments -= "priority"
|
||||
if (start_index) // See https://www.byond.com/forum/post/2980598 as to why we cannot just override the existing filter
|
||||
atom_cast.filters -= filter_info["name"] // We're trapped in the belly of this horrible machine
|
||||
filter_cache += filter(arglist(arguments)) // And the machine is bleeding to death
|
||||
|
||||
atom_cast.filters = filter_cache
|
||||
UNSETEMPTY(filter_data)
|
||||
|
||||
/obj/item/update_filters()
|
||||
/obj/item/update_filters(start_index = null)
|
||||
. = ..()
|
||||
update_item_action_buttons()
|
||||
|
||||
@@ -362,17 +394,29 @@
|
||||
* * name - Filter name
|
||||
* * new_params - New parameters of the filter
|
||||
* * overwrite - TRUE means we replace the parameter list completely. FALSE means we only replace the things on new_params.
|
||||
* * update - If we should apply our filter cache to our actual filters
|
||||
*/
|
||||
/datum/proc/modify_filter(name, list/new_params, overwrite = FALSE)
|
||||
var/filter = get_filter(name)
|
||||
if(!filter)
|
||||
/datum/proc/modify_filter(name, list/new_params, overwrite = FALSE, update = TRUE)
|
||||
ASSERT(isatom(src) || isimage(src))
|
||||
var/atom/atom_cast = src // filters only work with images or atoms.
|
||||
for (var/index in 1 to length(filter_data))
|
||||
var/list/filter_info = filter_data[index]
|
||||
if (filter_info["name"] != name)
|
||||
continue
|
||||
|
||||
if (overwrite)
|
||||
filter_data[index] = new_params
|
||||
else
|
||||
for (var/thing in new_params)
|
||||
filter_info[thing] = new_params[thing]
|
||||
|
||||
var/list/arguments = filter_info.Copy()
|
||||
arguments -= "priority"
|
||||
filter_cache[index] = filter(arglist(arguments))
|
||||
|
||||
if (update)
|
||||
atom_cast.filters = filter_cache
|
||||
return
|
||||
if(overwrite)
|
||||
filter_data[name] = new_params
|
||||
else
|
||||
for(var/thing in new_params)
|
||||
filter_data[name][thing] = new_params[thing]
|
||||
update_filters()
|
||||
|
||||
/** Update a filter's parameter and animate this change. If the filter doesn't exist we won't do anything.
|
||||
* Basically a [datum/proc/modify_filter] call but with animations. Unmodified filter parameters are kept.
|
||||
@@ -386,7 +430,7 @@
|
||||
*/
|
||||
/datum/proc/transition_filter(name, list/new_params, time, easing, loop)
|
||||
var/filter = get_filter(name)
|
||||
if(!filter)
|
||||
if (!filter)
|
||||
return
|
||||
// This can get injected by the filter procs, we want to support them so bye byeeeee
|
||||
new_params -= "type"
|
||||
@@ -399,75 +443,75 @@
|
||||
* * duration - the time it takes to animate this step
|
||||
* * easing - the type of easing this step has
|
||||
*/
|
||||
/proc/FilterChainStep(params, duration, easing)
|
||||
/proc/filter_chain_step(params, duration, easing, flags)
|
||||
params -= "type"
|
||||
return list("params"= params, "duration"=duration, "easing"=easing)
|
||||
return list("params" = params, "duration" = duration, "easing" = easing, "flags" = flags)
|
||||
|
||||
/** Similar to transition_filter(), except it creates an animation chain that moves between a list of states.
|
||||
* Arguments:
|
||||
* * name - Filter name
|
||||
* * num_loops - Amount of times the chain loops. INDEFINITE = Infinite
|
||||
* * ... - a list of each link in the animation chain. Use FilterChainStep(params, duration, easing) for each link
|
||||
* * ... - a list of each link in the animation chain. Use filter_chain_step(params, duration, easing) for each link
|
||||
* Example use:
|
||||
* * add_filter("blue_pulse", 1, color_matrix_filter(COLOR_WHITE))
|
||||
* * transition_filter_chain(src, "blue_pulse", INDEFINITE,\
|
||||
* * FilterChainStep(color_matrix_filter(COLOR_BLUE), 10 SECONDS, CUBIC_EASING),\
|
||||
* * FilterChainStep(color_matrix_filter(COLOR_WHITE), 10 SECONDS, CUBIC_EASING))
|
||||
* * filter_chain_step(color_matrix_filter(COLOR_BLUE), 10 SECONDS, CUBIC_EASING),\
|
||||
* * filter_chain_step(color_matrix_filter(COLOR_WHITE), 10 SECONDS, CUBIC_EASING))
|
||||
* The above code would edit a color_matrix_filter() to slowly turn blue over 10 seconds before returning back to white 10 seconds after, repeating this chain forever.
|
||||
*/
|
||||
/datum/proc/transition_filter_chain(name, num_loops, ...)
|
||||
var/list/transition_steps = args.Copy(3)
|
||||
var/filter = get_filter(name)
|
||||
if(!filter)
|
||||
if (!filter)
|
||||
return
|
||||
var/list/first_step = transition_steps[1]
|
||||
animate(filter, first_step["params"], time = first_step["duration"], easing = first_step["easing"], loop = num_loops)
|
||||
for(var/transition_step in 2 to length(transition_steps))
|
||||
animate(filter, first_step["params"], time = first_step["duration"], easing = first_step["easing"], flags = first_step["flags"], loop = num_loops)
|
||||
for (var/transition_step in 2 to length(transition_steps))
|
||||
var/list/this_step = transition_steps[transition_step]
|
||||
animate(this_step["params"], time = this_step["duration"], easing = this_step["easing"])
|
||||
|
||||
animate(this_step["params"], time = this_step["duration"], easing = this_step["easing"], flags = this_step["flags"])
|
||||
|
||||
/// Updates the priority of the passed filter key
|
||||
/datum/proc/change_filter_priority(name, new_priority)
|
||||
if(!filter_data || !filter_data[name])
|
||||
return
|
||||
for (var/list/filter_info as anything in filter_data)
|
||||
if (filter_info["name"] != name)
|
||||
continue
|
||||
|
||||
filter_data[name]["priority"] = new_priority
|
||||
update_filters()
|
||||
remove_filter(name, update = FALSE)
|
||||
add_filter(name, new_priority, filter_info)
|
||||
return
|
||||
|
||||
/// Returns the filter associated with the passed key
|
||||
/datum/proc/get_filter(name)
|
||||
ASSERT(isatom(src) || isimage(src))
|
||||
if(filter_data && filter_data[name])
|
||||
var/atom/atom_cast = src // filters only work with images or atoms.
|
||||
return atom_cast.filters[filter_data.Find(name)]
|
||||
|
||||
/// Returns the indice in filters of the given filter name.
|
||||
/// If it is not found, returns null.
|
||||
/datum/proc/get_filter_index(name)
|
||||
return filter_data?.Find(name)
|
||||
var/atom/atom_cast = src // filters only work with images or atoms.
|
||||
return atom_cast.filters[name]
|
||||
|
||||
/// Removes the passed filter, or multiple filters, if supplied with a list.
|
||||
/datum/proc/remove_filter(name_or_names)
|
||||
/datum/proc/remove_filter(name_or_names, update = TRUE)
|
||||
ASSERT(isatom(src) || isimage(src))
|
||||
if(!filter_data)
|
||||
return
|
||||
|
||||
var/atom/atom_cast = src // filters only work with images or atoms.
|
||||
var/list/names = islist(name_or_names) ? name_or_names : list(name_or_names)
|
||||
|
||||
. = FALSE
|
||||
for(var/name in names)
|
||||
if(filter_data[name])
|
||||
filter_data -= name
|
||||
. = TRUE
|
||||
|
||||
if(.)
|
||||
update_filters()
|
||||
var/list/new_data = list()
|
||||
var/list/new_cache = list()
|
||||
for (var/index in 1 to length(filter_data))
|
||||
var/list/filter_info = filter_data[index]
|
||||
if (!(filter_info["name"] in names))
|
||||
new_data += list(filter_info)
|
||||
new_cache += filter_cache[index]
|
||||
filter_data = new_data
|
||||
filter_cache = new_cache
|
||||
if (update)
|
||||
atom_cast.filters = filter_cache
|
||||
return .
|
||||
|
||||
/datum/proc/clear_filters()
|
||||
ASSERT(isatom(src) || isimage(src))
|
||||
var/atom/atom_cast = src // filters only work with images or atoms.
|
||||
filter_data = null
|
||||
filter_cache = null
|
||||
atom_cast.filters = null
|
||||
|
||||
/// Calls qdel on itself, because signals dont allow callbacks
|
||||
|
||||
@@ -70,7 +70,7 @@
|
||||
/datum/element/art/commoner/apply_moodlet(atom/source, mob/living/user, impress)
|
||||
var/msg
|
||||
var/list/haters = list()
|
||||
for(var/hater_department_type as anything in list(/datum/job_department/security, /datum/job_department/command))
|
||||
for(var/hater_department_type in list(/datum/job_department/security, /datum/job_department/command))
|
||||
var/datum/job_department/hater_department = SSjob.get_department_type(hater_department_type)
|
||||
for(var/datum/job/hater_job as anything in hater_department.department_jobs)
|
||||
haters += hater_job.title
|
||||
|
||||
+158
-263
@@ -5,61 +5,31 @@ GLOBAL_LIST_INIT(immerse_ignored_movable, typecacheof(list(
|
||||
/obj/projectile,
|
||||
)))
|
||||
|
||||
/**
|
||||
* A visual element that makes movables entering the attached turfs look immersed into that turf.
|
||||
*
|
||||
* Abandon all hope, ye who read forth, for this immerse works on mind-numbing workarounds,
|
||||
*/
|
||||
/// A visual element that makes movables entering the attached turfs look immersed into that turf.
|
||||
/// May the gods forgive me for the bullshit you're about to witness
|
||||
/datum/element/immerse
|
||||
element_flags = ELEMENT_DETACH_ON_HOST_DESTROY | ELEMENT_BESPOKE
|
||||
argument_hash_start_idx = 2
|
||||
///An association list of turfs that have this element attached and their affected contents.
|
||||
var/list/attached_turfs_and_movables = list()
|
||||
|
||||
///A list of icons generated from a target and a mask, later used as appearances for the overlays.
|
||||
var/static/list/generated_immerse_icons = list()
|
||||
///A list of instances of /atom/movable/immerse_overlay then used as visual overlays for the immersed movables.
|
||||
/// An association list of turfs that have this element attached and their affected contents.
|
||||
var/list/attached_turf_contents = list()
|
||||
|
||||
/// A list of generated immersion masks based on object width, height and whever they're fully immersed underwater
|
||||
var/list/immersion_masks = list()
|
||||
/// An assoc list of instances of /atom/movable/immerse_mask used as abstract effect relays, because god is dead
|
||||
var/list/generated_visual_overlays = list()
|
||||
///An association list of movables as key and overlays as assoc.
|
||||
var/list/immersed_movables
|
||||
/// icon_state used as a mask by our turf
|
||||
var/mask_icon = "immerse"
|
||||
/// Alpha of the mask, to make the liquid partially transparent
|
||||
var/alpha = 180
|
||||
|
||||
var/icon
|
||||
var/icon_state
|
||||
var/mask_icon
|
||||
var/color
|
||||
var/alpha
|
||||
|
||||
/datum/element/immerse/Attach(turf/target, icon, icon_state, mask_icon, color = "#777777", alpha = 180)
|
||||
/datum/element/immerse/Attach(turf/target, mask_icon = "immerse", alpha = 180)
|
||||
. = ..()
|
||||
if(!isturf(target) || !icon || !icon_state || !mask_icon)
|
||||
if(!isturf(target) || !mask_icon)
|
||||
return ELEMENT_INCOMPATIBLE
|
||||
|
||||
src.icon = icon
|
||||
src.icon_state = icon_state
|
||||
src.color = color
|
||||
src.alpha = alpha
|
||||
src.mask_icon = mask_icon
|
||||
|
||||
/**
|
||||
* Hello, you may be wondering why we're blending icons and not simply
|
||||
* overlaying one mutable appearance with the blend multiply on another.
|
||||
* Well, the latter option doesn't work as neatly when added
|
||||
* to an atom with the KEEP_TOGETHER appearance flag, with the mask icon also
|
||||
* showing on said atom, while we don't want it to.
|
||||
*
|
||||
* Also using KEEP_APART isn't an option, because unless it's drawn as one with
|
||||
* its visual loation, the whole plane the atom belongs to will count as part of the
|
||||
* mask of the final visual overlay since that's how the BLEND_INSET_OVERLAY blend mode works here.
|
||||
* In layman terms, with KEEP_APART on, if a flying monkey gets nears an immersed
|
||||
* human, the visual overlay will appear on the flying monkey even if it shouldn't.
|
||||
*/
|
||||
var/icon/immerse_icon = generated_immerse_icons["[icon]-[icon_state]-[mask_icon]"]
|
||||
if(!immerse_icon)
|
||||
immerse_icon = icon(icon, icon_state)
|
||||
var/icon/sub_mask = icon('icons/effects/effects.dmi', mask_icon)
|
||||
immerse_icon.Blend(sub_mask, ICON_MULTIPLY)
|
||||
immerse_icon = fcopy_rsc(immerse_icon)
|
||||
generated_immerse_icons["[icon]-[icon_state]-[mask_icon]"] = immerse_icon
|
||||
src.alpha = alpha
|
||||
|
||||
RegisterSignal(target, SIGNAL_ADDTRAIT(TRAIT_IMMERSE_STOPPED), PROC_REF(stop_immersion))
|
||||
RegisterSignal(target, SIGNAL_REMOVETRAIT(TRAIT_IMMERSE_STOPPED), PROC_REF(start_immersion))
|
||||
@@ -73,29 +43,30 @@ GLOBAL_LIST_INIT(immerse_ignored_movable, typecacheof(list(
|
||||
stop_immersion(source)
|
||||
return ..()
|
||||
|
||||
///Makes the element start affecting the turf and its contents. Called on Attach() or when TRAIT_IMMERSE_STOPPED is removed.
|
||||
|
||||
/// Makes the element start affecting the turf and its contents. Called on Attach() or when TRAIT_IMMERSE_STOPPED is removed.
|
||||
/datum/element/immerse/proc/start_immersion(turf/source)
|
||||
SIGNAL_HANDLER
|
||||
RegisterSignals(source, list(COMSIG_ATOM_ABSTRACT_ENTERED, COMSIG_ATOM_AFTER_SUCCESSFUL_INITIALIZED_ON), PROC_REF(on_init_or_entered))
|
||||
RegisterSignal(source, COMSIG_ATOM_ABSTRACT_EXITED, PROC_REF(on_atom_exited))
|
||||
attached_turfs_and_movables += source
|
||||
attached_turf_contents += source
|
||||
for(var/atom/movable/movable as anything in source)
|
||||
if(!(movable.flags_1 & INITIALIZED_1) || movable.invisibility >= INVISIBILITY_OBSERVER)
|
||||
continue
|
||||
on_init_or_entered(source, movable)
|
||||
|
||||
///Stops the element from affecting on the turf and its contents. Called on Detach() or when TRAIT_IMMERSE_STOPPED is added.
|
||||
/// Stops the element from affecting on the turf and its contents. Called on Detach() or when TRAIT_IMMERSE_STOPPED is added.
|
||||
/datum/element/immerse/proc/stop_immersion(turf/source)
|
||||
SIGNAL_HANDLER
|
||||
UnregisterSignal(source, list(COMSIG_ATOM_ABSTRACT_ENTERED, COMSIG_ATOM_AFTER_SUCCESSFUL_INITIALIZED_ON, COMSIG_ATOM_ABSTRACT_EXITED))
|
||||
for(var/atom/movable/movable as anything in attached_turfs_and_movables[source])
|
||||
for(var/atom/movable/movable as anything in attached_turf_contents[source])
|
||||
remove_from_element(source, movable)
|
||||
attached_turfs_and_movables -= source
|
||||
attached_turf_contents -= source
|
||||
|
||||
/**
|
||||
* If the movable is within the right layers and planes, not in the list of movable types to ignore,
|
||||
* or already affected by the element for that matter, Signals will be registered and,
|
||||
* unless the movable (or whatever it's buckled to) is flying, it'll appear as if immersed in that water.
|
||||
* or already affected by the element for that matter, signals will be registered and,
|
||||
* unless the movable is flying, it'll appear as if immersed in that water.
|
||||
*/
|
||||
/datum/element/immerse/proc/on_init_or_entered(turf/source, atom/movable/movable)
|
||||
SIGNAL_HANDLER
|
||||
@@ -103,123 +74,34 @@ GLOBAL_LIST_INIT(immerse_ignored_movable, typecacheof(list(
|
||||
return
|
||||
if(HAS_TRAIT(movable, TRAIT_IMMERSED) || HAS_TRAIT(movable, TRAIT_WALLMOUNTED))
|
||||
return
|
||||
if(!ISINRANGE(movable.plane, MUTATE_PLANE(FLOOR_PLANE, source), MUTATE_PLANE(GAME_PLANE, source)))
|
||||
if(!ISINRANGE(PLANE_TO_TRUE(movable.plane), FLOOR_PLANE, GAME_PLANE))
|
||||
return
|
||||
|
||||
// First, floor plane objects use TOPDOWN_LAYER, second this check shouldn't apply to them anyway.
|
||||
var/layer_to_check = IS_TOPDOWN_PLANE(source.plane) ? TOPDOWN_ABOVE_WATER_LAYER : ABOVE_ALL_MOB_LAYER
|
||||
//First, floor plane objects use TOPDOWN_LAYER, second this check shouldn't apply to them anyway.
|
||||
if(movable.layer >= layer_to_check)
|
||||
return
|
||||
if(is_type_in_typecache(movable, GLOB.immerse_ignored_movable))
|
||||
return
|
||||
|
||||
var/atom/movable/buckled
|
||||
var/atom/movable/buckled = null
|
||||
if(isliving(movable))
|
||||
var/mob/living/living_mob = movable
|
||||
RegisterSignal(living_mob, COMSIG_LIVING_SET_BUCKLED, PROC_REF(on_set_buckled))
|
||||
buckled = living_mob.buckled
|
||||
RegisterSignal(living_mob, COMSIG_LIVING_SET_BUCKLED, PROC_REF(on_set_buckled))
|
||||
RegisterSignal(living_mob, COMSIG_LIVING_UPDATE_OFFSETS, PROC_REF(on_update_offsets))
|
||||
RegisterSignal(movable, COMSIG_LIVING_POST_UPDATE_TRANSFORM, PROC_REF(on_update_transform))
|
||||
|
||||
try_immerse(movable, buckled)
|
||||
RegisterSignal(movable, COMSIG_ATOM_SPIN_ANIMATION, PROC_REF(on_spin_animation))
|
||||
RegisterSignal(movable, COMSIG_QDELETING, PROC_REF(on_movable_qdel))
|
||||
LAZYADD(attached_turfs_and_movables[source], movable)
|
||||
try_immerse(movable, buckled)
|
||||
LAZYADD(attached_turf_contents[source], movable)
|
||||
ADD_TRAIT(movable, TRAIT_IMMERSED, ELEMENT_TRAIT(src))
|
||||
|
||||
/datum/element/immerse/proc/on_movable_qdel(atom/movable/source)
|
||||
SIGNAL_HANDLER
|
||||
remove_from_element(source.loc, source)
|
||||
|
||||
/**
|
||||
* The main proc, which adds a visual overlay to the movable that has entered the turf to make it look immersed.
|
||||
* It's kind of iffy but basically, we want the overlay to cover as much area as needed to
|
||||
* avoid the movable's icon from spilling horizontally or below.
|
||||
* Also, while these visual overlays are mainly cached movables, for certain movables, such as living mobs,
|
||||
* we want them to have their own unique vis overlay with additional signals registered.
|
||||
* This allows the vis overlay to look more or less unchanged while its owner is spinning or resting
|
||||
* without otherwise affecting other movables with identical overlays.
|
||||
*/
|
||||
/datum/element/immerse/proc/add_immerse_overlay(atom/movable/movable)
|
||||
var/list/icon_dimensions = get_icon_dimensions(movable.icon)
|
||||
var/width = icon_dimensions["width"] || ICON_SIZE_X
|
||||
var/height = icon_dimensions["height"] || ICON_SIZE_Y
|
||||
|
||||
///This determines if the overlay should cover the entire surface of the object or not
|
||||
var/layer_to_check = IS_TOPDOWN_PLANE(movable.plane) ? TOPDOWN_WATER_LEVEL_LAYER : WATER_LEVEL_LAYER
|
||||
var/is_below_water = (movable.layer < layer_to_check) ? "underwater-" : ""
|
||||
|
||||
var/atom/movable/immerse_overlay/vis_overlay = generated_visual_overlays["[is_below_water][width]x[height]"]
|
||||
|
||||
if(!vis_overlay) //create the overlay if not already done.
|
||||
vis_overlay = generate_vis_overlay(width, height, is_below_water)
|
||||
|
||||
|
||||
ADD_KEEP_TOGETHER(movable, ELEMENT_TRAIT(src))
|
||||
|
||||
/**
|
||||
* Let's give an unique immerse visual only to those movables that would
|
||||
* benefit from this the most, for the sake of a smidge of lightweightness.
|
||||
*/
|
||||
if(HAS_TRAIT(movable, TRAIT_UNIQUE_IMMERSE))
|
||||
var/atom/movable/immerse_overlay/original_vis_overlay = vis_overlay
|
||||
vis_overlay = new(null)
|
||||
vis_overlay.appearance = original_vis_overlay
|
||||
vis_overlay.extra_width = original_vis_overlay.extra_width
|
||||
vis_overlay.extra_height = original_vis_overlay.extra_height
|
||||
vis_overlay.overlay_appearance = original_vis_overlay.overlay_appearance
|
||||
SEND_SIGNAL(movable, COMSIG_MOVABLE_EDIT_UNIQUE_IMMERSE_OVERLAY, vis_overlay)
|
||||
RegisterSignal(movable, COMSIG_ATOM_SPIN_ANIMATION, PROC_REF(on_spin_animation))
|
||||
RegisterSignal(movable, COMSIG_LIVING_POST_UPDATE_TRANSFORM, PROC_REF(on_update_transform))
|
||||
|
||||
movable.vis_contents |= vis_overlay
|
||||
|
||||
LAZYSET(immersed_movables, movable, vis_overlay)
|
||||
|
||||
///Initializes and caches a new visual overlay given parameters such as width, height and whether it should appear fully underwater.
|
||||
/datum/element/immerse/proc/generate_vis_overlay(width, height, is_below_water)
|
||||
|
||||
var/atom/movable/immerse_overlay/vis_overlay = new(null, src)
|
||||
|
||||
/**
|
||||
* vis contents spin around the center of the icon of their vis locs
|
||||
* but since we want the appearance to stay where it should be,
|
||||
* we have to counteract this one.
|
||||
*/
|
||||
var/extra_width = (width - ICON_SIZE_X) * 0.5
|
||||
var/extra_height = (height - ICON_SIZE_Y) * 0.5
|
||||
var/mutable_appearance/overlay_appearance = new()
|
||||
var/icon/immerse_icon = generated_immerse_icons["[icon]-[icon_state]-[mask_icon]"]
|
||||
var/last_i = width/ICON_SIZE_X
|
||||
for(var/i in -1 to last_i)
|
||||
var/mutable_appearance/underwater = mutable_appearance(icon, icon_state)
|
||||
underwater.pixel_w = ICON_SIZE_X * i - extra_width
|
||||
underwater.pixel_z = -ICON_SIZE_Y - extra_height
|
||||
overlay_appearance.overlays += underwater
|
||||
|
||||
var/mutable_appearance/water_level = is_below_water ? underwater : mutable_appearance(immerse_icon)
|
||||
water_level.pixel_w = ICON_SIZE_X * i - extra_width
|
||||
water_level.pixel_z = -extra_height
|
||||
overlay_appearance.overlays += water_level
|
||||
|
||||
|
||||
vis_overlay.color = color
|
||||
vis_overlay.alpha = alpha
|
||||
vis_overlay.overlays = list(overlay_appearance)
|
||||
|
||||
vis_overlay.extra_width = extra_width
|
||||
vis_overlay.extra_height = extra_height
|
||||
vis_overlay.overlay_appearance = overlay_appearance
|
||||
|
||||
generated_visual_overlays["[is_below_water][width]x[height]"] = vis_overlay
|
||||
return vis_overlay
|
||||
|
||||
///This proc removes the vis_overlay, the keep together trait and some signals from the movable.
|
||||
/datum/element/immerse/proc/remove_immerse_overlay(atom/movable/movable)
|
||||
var/atom/movable/immerse_overlay/vis_overlay = LAZYACCESS(immersed_movables, movable)
|
||||
LAZYREMOVE(immersed_movables, movable)
|
||||
REMOVE_KEEP_TOGETHER(movable, ELEMENT_TRAIT(src))
|
||||
movable.vis_contents -= vis_overlay
|
||||
if(HAS_TRAIT(movable, TRAIT_UNIQUE_IMMERSE))
|
||||
UnregisterSignal(movable, list(COMSIG_ATOM_SPIN_ANIMATION, COMSIG_LIVING_POST_UPDATE_TRANSFORM, COMSIG_QDELETING))
|
||||
if(!QDELETED(vis_overlay))
|
||||
qdel(vis_overlay)
|
||||
/**
|
||||
* Called by init_or_entered() and on_set_buckled().
|
||||
* This applies the overlay if neither the movable or whatever is buckled to (exclusive to living mobs) are flying
|
||||
@@ -229,29 +111,34 @@ GLOBAL_LIST_INIT(immerse_ignored_movable, typecacheof(list(
|
||||
var/atom/movable/to_check = buckled || movable
|
||||
if(!(to_check.movement_type & MOVETYPES_NOT_TOUCHING_GROUND) && !movable.throwing)
|
||||
add_immerse_overlay(movable)
|
||||
if(!buckled)
|
||||
RegisterSignal(movable, COMSIG_MOVETYPE_FLAG_ENABLED, PROC_REF(on_move_flag_enabled))
|
||||
RegisterSignal(movable, COMSIG_MOVETYPE_FLAG_DISABLED, PROC_REF(on_move_flag_disabled))
|
||||
RegisterSignal(movable, COMSIG_MOVABLE_POST_THROW, PROC_REF(on_throw))
|
||||
RegisterSignal(movable, COMSIG_MOVABLE_THROW_LANDED, PROC_REF(on_throw_landed))
|
||||
if(buckled)
|
||||
return
|
||||
RegisterSignal(movable, COMSIG_MOVETYPE_FLAG_ENABLED, PROC_REF(on_move_flag_enabled))
|
||||
RegisterSignal(movable, COMSIG_MOVETYPE_FLAG_DISABLED, PROC_REF(on_move_flag_disabled))
|
||||
RegisterSignal(movable, COMSIG_MOVABLE_POST_THROW, PROC_REF(on_throw))
|
||||
RegisterSignal(movable, COMSIG_MOVABLE_THROW_LANDED, PROC_REF(on_throw_landed))
|
||||
|
||||
/**
|
||||
* Called by on_set_buckled() and remove_from_element().
|
||||
* This removes the filter and signals from the movable unless it doesn't have them.
|
||||
*/
|
||||
/// Called by on_set_buckled() and remove_from_element().
|
||||
/// This removes the filter and signals from the movable unless it doesn't have them.
|
||||
/datum/element/immerse/proc/try_unimmerse(atom/movable/movable, atom/movable/buckled)
|
||||
var/atom/movable/to_check = buckled || movable
|
||||
if(!(to_check.movement_type & MOVETYPES_NOT_TOUCHING_GROUND) && !movable.throwing)
|
||||
remove_immerse_overlay(movable)
|
||||
if(!buckled)
|
||||
UnregisterSignal(movable, list(COMSIG_MOVETYPE_FLAG_ENABLED, COMSIG_MOVETYPE_FLAG_DISABLED, COMSIG_MOVABLE_POST_THROW, COMSIG_MOVABLE_THROW_LANDED))
|
||||
if(buckled)
|
||||
return
|
||||
UnregisterSignal(movable, list(
|
||||
COMSIG_MOVETYPE_FLAG_ENABLED,
|
||||
COMSIG_MOVETYPE_FLAG_DISABLED,
|
||||
COMSIG_MOVABLE_POST_THROW,
|
||||
COMSIG_MOVABLE_THROW_LANDED
|
||||
))
|
||||
|
||||
/datum/element/immerse/proc/on_set_buckled(mob/living/source, atom/movable/new_buckled)
|
||||
SIGNAL_HANDLER
|
||||
try_unimmerse(source, source.buckled)
|
||||
try_immerse(source, new_buckled)
|
||||
|
||||
///Removes the overlay from mob and bucklees is flying.
|
||||
/// Removes the overlay from mob and bucklees is flying.
|
||||
/datum/element/immerse/proc/on_move_flag_enabled(atom/movable/source, flag, old_movement_type)
|
||||
SIGNAL_HANDLER
|
||||
if(!(flag & MOVETYPES_NOT_TOUCHING_GROUND) || (old_movement_type & MOVETYPES_NOT_TOUCHING_GROUND) || source.throwing)
|
||||
@@ -260,7 +147,7 @@ GLOBAL_LIST_INIT(immerse_ignored_movable, typecacheof(list(
|
||||
for(var/mob/living/buckled_mob as anything in source.buckled_mobs)
|
||||
remove_immerse_overlay(buckled_mob)
|
||||
|
||||
///Works just like on_move_flag_enabled, except it only has to check that movable isn't flying
|
||||
/// Works just like on_move_flag_enabled, except it only has to check that movable isn't flying
|
||||
/datum/element/immerse/proc/on_throw(atom/movable/source)
|
||||
SIGNAL_HANDLER
|
||||
if(source.movement_type & MOVETYPES_NOT_TOUCHING_GROUND)
|
||||
@@ -269,7 +156,7 @@ GLOBAL_LIST_INIT(immerse_ignored_movable, typecacheof(list(
|
||||
for(var/mob/living/buckled_mob as anything in source.buckled_mobs)
|
||||
remove_immerse_overlay(buckled_mob)
|
||||
|
||||
///Readds the overlay to the mob and bucklees if no longer flying.
|
||||
/// Readds the overlay to the mob and bucklees if no longer flying.
|
||||
/datum/element/immerse/proc/on_move_flag_disabled(atom/movable/source, flag, old_movement_type)
|
||||
SIGNAL_HANDLER
|
||||
if(!(flag & MOVETYPES_NOT_TOUCHING_GROUND) || (source.movement_type & MOVETYPES_NOT_TOUCHING_GROUND) || source.throwing)
|
||||
@@ -278,7 +165,7 @@ GLOBAL_LIST_INIT(immerse_ignored_movable, typecacheof(list(
|
||||
for(var/mob/living/buckled_mob as anything in source.buckled_mobs)
|
||||
add_immerse_overlay(buckled_mob)
|
||||
|
||||
///Works just like on_move_flag_disabled, except it only has to check that movable isn't flying
|
||||
/// Works just like on_move_flag_disabled, except it only has to check that movable isn't flying
|
||||
/datum/element/immerse/proc/on_throw_landed(atom/movable/source)
|
||||
SIGNAL_HANDLER
|
||||
if(source.movement_type & MOVETYPES_NOT_TOUCHING_GROUND)
|
||||
@@ -287,123 +174,131 @@ GLOBAL_LIST_INIT(immerse_ignored_movable, typecacheof(list(
|
||||
for(var/mob/living/buckled_mob as anything in source.buckled_mobs)
|
||||
add_immerse_overlay(buckled_mob)
|
||||
|
||||
/**
|
||||
* Called when a movable exits the turf. If its new location is not in the list of turfs with this element,
|
||||
* Remove the movable from the element.
|
||||
*/
|
||||
/// Called when a movable exits the turf. If its new location is not in the list of turfs with this element,
|
||||
/// remove the movable from the element.
|
||||
/datum/element/immerse/proc/on_atom_exited(turf/source, atom/movable/exited, direction)
|
||||
SIGNAL_HANDLER
|
||||
if(!(exited.loc in attached_turfs_and_movables))
|
||||
if(!attached_turf_contents[exited.loc])
|
||||
remove_from_element(source, exited)
|
||||
else
|
||||
LAZYREMOVE(attached_turfs_and_movables[source], exited)
|
||||
LAZYADD(attached_turfs_and_movables[exited.loc], exited)
|
||||
return
|
||||
LAZYREMOVE(attached_turf_contents[source], exited)
|
||||
LAZYADD(attached_turf_contents[exited.loc], exited)
|
||||
|
||||
///Remove any signal, overlay, trait given to the movable and reference to it within the element.
|
||||
//// Remove any signal, overlay, trait given to the movable and reference to it within the element.
|
||||
/datum/element/immerse/proc/remove_from_element(turf/source, atom/movable/movable)
|
||||
var/atom/movable/buckled
|
||||
var/atom/movable/buckled = null
|
||||
if(isliving(movable))
|
||||
var/mob/living/living_mob = movable
|
||||
buckled = living_mob.buckled
|
||||
try_unimmerse(movable, buckled)
|
||||
|
||||
LAZYREMOVE(attached_turfs_and_movables[source], movable)
|
||||
UnregisterSignal(movable, list(COMSIG_LIVING_SET_BUCKLED, COMSIG_QDELETING))
|
||||
try_unimmerse(movable, buckled)
|
||||
LAZYREMOVE(attached_turf_contents[source], movable)
|
||||
UnregisterSignal(movable, list(COMSIG_LIVING_SET_BUCKLED, COMSIG_QDELETING, COMSIG_LIVING_UPDATE_OFFSETS, COMSIG_ATOM_SPIN_ANIMATION, COMSIG_LIVING_POST_UPDATE_TRANSFORM))
|
||||
REMOVE_TRAIT(movable, TRAIT_IMMERSED, ELEMENT_TRAIT(src))
|
||||
|
||||
/// Generate a mask filter mutable to use as render_source for the alpha filter based on provided width, height and immersion state
|
||||
/datum/element/immerse/proc/generate_immerse_mask(width, height, is_below_water)
|
||||
var/clean_height = height
|
||||
width = ceil(width / ICON_SIZE_X) * ICON_SIZE_X
|
||||
height = ceil(height / ICON_SIZE_Y) * ICON_SIZE_Y
|
||||
|
||||
var/mask_key = "[width]-[height]-[is_below_water]"
|
||||
var/mutable_appearance/target_mask = immersion_masks[mask_key]
|
||||
if (target_mask)
|
||||
return target_mask
|
||||
|
||||
if (width == ICON_SIZE_X && height == ICON_SIZE_Y)
|
||||
target_mask = mutable_appearance('icons/effects/effects.dmi', mask_icon, alpha = alpha)
|
||||
immersion_masks[mask_key] = target_mask
|
||||
return target_mask
|
||||
|
||||
var/icon/column_icon = icon('icons/effects/effects.dmi', mask_icon)
|
||||
var/y_tiles = 1
|
||||
if (height != ICON_SIZE_Y)
|
||||
column_icon.Crop(1, 1, ICON_SIZE_X, ICON_SIZE_Y) // Use base icon and crop it out so animation frames respect dmi's delays
|
||||
y_tiles = ceil((height / ICON_SIZE_Y - 1) / 2) + 1
|
||||
column_icon.Scale(ICON_SIZE_X, y_tiles * ICON_SIZE_Y)
|
||||
var/icon/effect_icon = icon('icons/effects/effects.dmi', mask_icon)
|
||||
var/icon/fill_icon = icon('icons/effects/alphacolors.dmi', "white")
|
||||
for (var/y_tile in 1 to y_tiles - 1)
|
||||
column_icon.Blend(fill_icon, ICON_OVERLAY, 1, 1 + (y_tile - 1) * ICON_SIZE_Y)
|
||||
column_icon.Blend(effect_icon, ICON_OVERLAY, 1, 1 + (y_tiles - 1) * ICON_SIZE_Y)
|
||||
|
||||
var/icon/immerse_icon = null
|
||||
if (width == ICON_SIZE_X)
|
||||
immerse_icon = column_icon
|
||||
else
|
||||
immerse_icon = icon('icons/effects/effects.dmi', mask_icon) // Use base icon and crop it out so animation frames respect dmi's delays
|
||||
immerse_icon.Crop(1, 1, ICON_SIZE_X, ICON_SIZE_Y)
|
||||
immerse_icon.Scale(ceil(width / ICON_SIZE_X) * ICON_SIZE_X, ceil(height / ICON_SIZE_Y) * ICON_SIZE_Y)
|
||||
for (var/x_tile in 1 to ceil(width / ICON_SIZE_X))
|
||||
immerse_icon.Blend(column_icon, ICON_OVERLAY, 1 + (x_tile - 1) * ICON_SIZE_X, 1)
|
||||
target_mask = mutable_appearance(immerse_icon)
|
||||
target_mask.alpha = alpha
|
||||
target_mask.pixel_y = -(y_tiles - 1) * ICON_SIZE_Y + floor((clean_height - ICON_SIZE_Y) / 2)
|
||||
immersion_masks[mask_key] = target_mask
|
||||
return target_mask
|
||||
|
||||
/datum/element/immerse/proc/add_immerse_overlay(atom/movable/movable)
|
||||
// This determines if the overlay should cover the entire surface of the object or not
|
||||
var/layer_to_check = IS_TOPDOWN_PLANE(movable.plane) ? TOPDOWN_WATER_LEVEL_LAYER : WATER_LEVEL_LAYER
|
||||
var/is_below_water = (movable.layer < layer_to_check) ? "underwater-" : ""
|
||||
// Tall mobs still only get covered to their feet, unless they're offset down
|
||||
var/mutable_appearance/immerse_mask = generate_immerse_mask(movable.get_cached_width(), max(ICON_SIZE_Y - movable.pixel_z, ICON_SIZE_Y), is_below_water)
|
||||
var/atom/movable/immerse_mask/effect_relay = generated_visual_overlays[movable]
|
||||
if (!effect_relay)
|
||||
effect_relay = new(movable)
|
||||
movable.vis_contents += effect_relay
|
||||
generated_visual_overlays[movable] = effect_relay
|
||||
var/mutable_appearance/mask_copy = new(immerse_mask)
|
||||
effect_relay.appearance = mask_copy
|
||||
effect_relay.render_target = "*immerse_[REF(movable)]"
|
||||
SEND_SIGNAL(movable, COMSIG_MOVABLE_EDIT_UNIQUE_IMMERSE_OVERLAY, effect_relay)
|
||||
// Should always render above any other filters that could be adding visuals
|
||||
movable.add_filter("immerse_mask", INFINITY, alpha_mask_filter(y = -floor((movable.get_cached_height() - ICON_SIZE_Y) / 2) - movable.pixel_z, render_source = effect_relay.render_target, flags = MASK_INVERSE))
|
||||
|
||||
/datum/element/immerse/proc/remove_immerse_overlay(atom/movable/movable, deleting = TRUE)
|
||||
movable.remove_filter("immerse_mask")
|
||||
if (!deleting)
|
||||
return
|
||||
var/atom/movable/immerse_mask/mask = generated_visual_overlays[movable]
|
||||
movable.vis_contents -= mask
|
||||
generated_visual_overlays -= movable
|
||||
QDEL_NULL(mask)
|
||||
|
||||
/// A band-aid to keep the (unique) visual overlay from scaling and rotating along with its owner. I'm sorry.
|
||||
/datum/element/immerse/proc/on_update_transform(mob/living/source, resize, new_lying_angle, is_opposite_angle)
|
||||
SIGNAL_HANDLER
|
||||
var/matrix/new_transform = matrix()
|
||||
new_transform.Scale(1/source.current_size)
|
||||
new_transform.Scale(1 / source.current_size)
|
||||
new_transform.Turn(-new_lying_angle)
|
||||
var/atom/movable/immerse_mask/effect_relay = generated_visual_overlays[source]
|
||||
var/mutable_appearance/relay_appearance = new(effect_relay.appearance)
|
||||
relay_appearance.transform = new_transform
|
||||
effect_relay.appearance = relay_appearance
|
||||
|
||||
var/atom/movable/immerse_overlay/vis_overlay = immersed_movables[source]
|
||||
if(is_opposite_angle)
|
||||
vis_overlay.transform = new_transform
|
||||
vis_overlay.adjust_living_overlay_offset(source)
|
||||
return
|
||||
|
||||
/**
|
||||
* Here, we temporarily switch from the offset of the mutable appearance to one for movable used as visual overlay.
|
||||
* Why? While visual overlays can be animated, their fixed point stays at the center of the icon of the atom
|
||||
* they're attached to and not theirs, which can make manipulating the transform var a pain, but because
|
||||
* we cannot do that with normal overlay or filters (reliably), we have to bend a knee and try to compensate it.
|
||||
*/
|
||||
vis_overlay.overlays = list(vis_overlay.overlay_appearance)
|
||||
|
||||
/// Oh, yeah, didn't I mention turning a visual overlay affects its pixel x/y/w/z too? Yeah, it sucks.
|
||||
var/new_x = vis_overlay.extra_width
|
||||
var/new_y = vis_overlay.extra_height
|
||||
var/old_div = source.current_size / resize
|
||||
var/offset_lying = source.rotate_on_lying ? PIXEL_Y_OFFSET_LYING : source.get_transform_translation_size(old_div)
|
||||
switch(source.lying_prev)
|
||||
if(270)
|
||||
vis_overlay.pixel_x += -offset_lying / old_div
|
||||
if(90)
|
||||
vis_overlay.pixel_x += offset_lying / old_div
|
||||
if(0)
|
||||
vis_overlay.pixel_y += -source.get_transform_translation_size(old_div) / old_div
|
||||
|
||||
switch(new_lying_angle)
|
||||
if(270)
|
||||
new_x += -offset_lying / source.current_size
|
||||
if(90)
|
||||
new_x += offset_lying / source.current_size
|
||||
if(0)
|
||||
new_y += -source.get_transform_translation_size(old_div) / old_div
|
||||
|
||||
animate(vis_overlay, transform = new_transform, pixel_x = new_x, pixel_y = new_y, time = UPDATE_TRANSFORM_ANIMATION_TIME, easing = (EASE_IN|EASE_OUT))
|
||||
addtimer(CALLBACK(vis_overlay, TYPE_PROC_REF(/atom/movable/immerse_overlay, adjust_living_overlay_offset), source), UPDATE_TRANSFORM_ANIMATION_TIME)
|
||||
|
||||
///Spin the overlay in the opposite direction so it doesn't look like it's spinning at all.
|
||||
/// Spin the overlay in the opposite direction so it doesn't look like it's spinning at all.
|
||||
/datum/element/immerse/proc/on_spin_animation(atom/source, speed, loops, segments, segment)
|
||||
SIGNAL_HANDLER
|
||||
var/atom/movable/immerse_overlay/vis_overlay = immersed_movables[source]
|
||||
vis_overlay.do_spin_animation(speed, loops, segments, -segment)
|
||||
var/atom/movable/immerse_mask/immerse_mask = generated_visual_overlays[source]
|
||||
immerse_mask.do_spin_animation(speed, loops, segments, -segment)
|
||||
|
||||
///We need to make sure to remove hard refs from the element when deleted.
|
||||
/datum/element/immerse/proc/clear_overlay_refs(atom/movable/immerse_overlay/source)
|
||||
//Assume that every vis loc is also in the immersed_movables list
|
||||
for(var/atom/movable/vis_loc as anything in source.vis_locs)
|
||||
remove_from_element(vis_loc.loc, vis_loc)
|
||||
LAZYREMOVE(generated_visual_overlays, source)
|
||||
source.overlay_appearance = null
|
||||
/datum/element/immerse/proc/on_update_offsets(mob/living/source, new_x, new_y, new_w, new_z, animate)
|
||||
SIGNAL_HANDLER
|
||||
var/old_height = ceil(max(ICON_SIZE_Y - source.pixel_z, ICON_SIZE_Y) / ICON_SIZE_Y)
|
||||
var/new_height = ceil(max(ICON_SIZE_Y - new_z, ICON_SIZE_Y) / ICON_SIZE_Y)
|
||||
if (old_height != new_height)
|
||||
remove_immerse_overlay(source, FALSE)
|
||||
add_immerse_overlay(source)
|
||||
|
||||
///The not-quite-perfect movable used by the immerse element for its nefarious deeds.
|
||||
/atom/movable/immerse_overlay
|
||||
appearance_flags = RESET_TRANSFORM|RESET_COLOR|RESET_ALPHA|KEEP_TOGETHER
|
||||
vis_flags = VIS_INHERIT_PLANE|VIS_INHERIT_ID
|
||||
mouse_opacity = MOUSE_OPACITY_TRANSPARENT
|
||||
blend_mode = BLEND_INSET_OVERLAY
|
||||
layer = WATER_VISUAL_OVERLAY_LAYER
|
||||
plane = FLOAT_PLANE
|
||||
/**
|
||||
* The actual overlay used to make the mob look like it's half-covered in water.
|
||||
*
|
||||
* For visual overlays, pixel y/x/w/z are amplified by the a, b, d, e variables
|
||||
* of the transform matrix of the movable they're attached to.
|
||||
* For example, if a mob is twice its normal size (a = 2, e = 2),
|
||||
* offsetting the movable used as visual overlay by 4 pixels to the right will result
|
||||
* in the visual overlay moving 8 pixels to the right.
|
||||
*
|
||||
* This however, doesn't extend to the overlays of our visual overlay. which is why there's
|
||||
* a mutable appearance variable that we use for those pixel offsets that really shouldn't be affected
|
||||
* by the transform of our vis loc(s) in the first place.
|
||||
*/
|
||||
var/mutable_appearance/overlay_appearance
|
||||
///The base pixel x offset of this movable
|
||||
var/extra_width = 0
|
||||
///The base pixel y offset of this movable
|
||||
var/extra_height = 0
|
||||
if (source.pixel_z == new_z)
|
||||
return
|
||||
|
||||
/atom/movable/immerse_overlay/Initialize(mapload, datum/element/immerse/element)
|
||||
. = ..()
|
||||
verbs.Cut() //"Cargo cultttttt" or something. Either way, they're better off without verbs.
|
||||
element?.RegisterSignal(src, COMSIG_QDELETING, TYPE_PROC_REF(/datum/element/immerse, clear_overlay_refs))
|
||||
if (animate)
|
||||
source.transition_filter("immerse_mask", list("y" = -floor((source.get_cached_height() - ICON_SIZE_Y) / 2) - new_z), time = UPDATE_TRANSFORM_ANIMATION_TIME)
|
||||
else
|
||||
source.modify_filter("immerse_mask", list("y" = -floor((source.get_cached_height() - ICON_SIZE_Y) / 2) - new_z))
|
||||
|
||||
///Called by COMSIG_MOVABLE_EDIT_UNIQUE_IMMERSE_OVERLAY for living mobs and a few procs from the immerse element.
|
||||
/atom/movable/immerse_overlay/proc/adjust_living_overlay_offset(mob/living/source)
|
||||
pixel_x = extra_width
|
||||
pixel_y = extra_height
|
||||
overlays = list(overlay_appearance)
|
||||
/atom/movable/immerse_mask
|
||||
appearance_flags = RESET_TRANSFORM|RESET_COLOR|RESET_ALPHA|KEEP_APART
|
||||
vis_flags = VIS_HIDE
|
||||
|
||||
@@ -19,10 +19,7 @@
|
||||
#define POSITIVE_INSTABILITY_MAJOR 35
|
||||
|
||||
/datum/mutation
|
||||
var/name
|
||||
|
||||
/datum/mutation
|
||||
name = "mutation"
|
||||
var/name = "mutation"
|
||||
/// Description of the mutation
|
||||
var/desc = "A mutation."
|
||||
/// Is this mutation currently locked?
|
||||
|
||||
@@ -13,7 +13,8 @@
|
||||
var/scream_delay = 50
|
||||
var/last_scream = 0
|
||||
var/bodypart_color = COLOR_DARK_LIME
|
||||
/// List of traits to add/remove when someone gets this mutation.
|
||||
/// Determines whether or not our version of hulk breaks their arm when destroying walls.
|
||||
var/no_recoil = TRUE
|
||||
mutation_traits = list(
|
||||
TRAIT_CHUNKYFINGERS,
|
||||
TRAIT_HULK,
|
||||
@@ -61,30 +62,6 @@
|
||||
/datum/mutation/hulk/proc/scream_attack(mob/living/carbon/human/source)
|
||||
source.say("WAAAAAAAAAAAAAAGH!", forced="hulk")
|
||||
|
||||
/**
|
||||
*Checks damage of a hulk's arm and applies bone wounds as necessary.
|
||||
*
|
||||
*Called by specific atoms being attacked, such as walls. If an atom
|
||||
*does not call this proc, than punching that atom will not cause
|
||||
*arm breaking (even if the atom deals recoil damage to hulks).
|
||||
*Arguments:
|
||||
*arg1 is the arm to evaluate damage of and possibly break.
|
||||
*/
|
||||
/datum/mutation/hulk/proc/break_an_arm(obj/item/bodypart/arm)
|
||||
var/severity
|
||||
switch(arm.brute_dam)
|
||||
if(45 to 50)
|
||||
severity = WOUND_SEVERITY_CRITICAL
|
||||
if(41 to 45)
|
||||
severity = WOUND_SEVERITY_SEVERE
|
||||
if(35 to 41)
|
||||
severity = WOUND_SEVERITY_MODERATE
|
||||
|
||||
if (isnull(severity))
|
||||
return
|
||||
|
||||
owner.cause_wound_of_type_and_severity(WOUND_BLUNT, arm, severity, wound_source = "hulk smashing")
|
||||
|
||||
/datum/mutation/hulk/on_life(seconds_per_tick, times_fired)
|
||||
if(owner.health < owner.crit_threshold)
|
||||
on_losing(owner)
|
||||
@@ -264,7 +241,7 @@
|
||||
health_req = 0
|
||||
instability = 0
|
||||
scream_delay = 2.5 SECONDS // halved to be more annoying (spell doesn't last long anyways)
|
||||
/// List of traits to add/remove when someone gets this mutation.
|
||||
no_recoil = FALSE
|
||||
mutation_traits = list(
|
||||
TRAIT_HULK,
|
||||
TRAIT_PUSHIMMUNE,
|
||||
@@ -275,7 +252,7 @@
|
||||
name = "Hulk (Super)"
|
||||
health_req = 0
|
||||
instability = 0
|
||||
/// List of traits to add/remove when someone gets this mutation.
|
||||
no_recoil = FALSE
|
||||
mutation_traits = list(
|
||||
TRAIT_CHUNKYFINGERS,
|
||||
TRAIT_HULK,
|
||||
|
||||
@@ -45,7 +45,7 @@ GLOBAL_DATUM_INIT(manifest, /datum/manifest, new)
|
||||
"trim" = trim,
|
||||
)
|
||||
continue
|
||||
for(var/department_type as anything in job.departments_list)
|
||||
for(var/department_type in job.departments_list)
|
||||
//Jobs under multiple departments should only be displayed if this is their first department or the command department
|
||||
if(job.departments_list[1] != department_type && !(job.departments_bitflags & DEPARTMENT_BITFLAG_COMMAND))
|
||||
continue
|
||||
@@ -238,4 +238,3 @@ GLOBAL_DATUM_INIT(manifest, /datum/manifest, new)
|
||||
"manifest" = get_manifest(),
|
||||
"positions" = positions
|
||||
)
|
||||
|
||||
|
||||
@@ -33,11 +33,11 @@
|
||||
return
|
||||
|
||||
var/final_phrase = ""
|
||||
var/original_char = ""
|
||||
|
||||
for(var/i = 1, i <= length(phrase), i += length(original_char))
|
||||
original_char = phrase[i]
|
||||
final_phrase += apply_speech(original_char)
|
||||
var/list/words = splittext(phrase, " ")
|
||||
var/list/new_words = list()
|
||||
for(var/i in 1 to length(words))
|
||||
new_words += apply_speech(words[i], i)
|
||||
final_phrase = jointext(new_words, " ")
|
||||
|
||||
if(final_phrase == phrase)
|
||||
return // No change was done, whatever
|
||||
@@ -51,13 +51,13 @@
|
||||
|
||||
/**
|
||||
* Applies the speech effects on the past character, changing
|
||||
* the original_char into the modified_char.
|
||||
* the original_word into some modified_word
|
||||
*
|
||||
* Return the modified_char to be reapplied to the message.
|
||||
* Return the newly modified word
|
||||
*/
|
||||
/datum/status_effect/speech/proc/apply_speech(original_char)
|
||||
/datum/status_effect/speech/proc/apply_speech(original_word, index)
|
||||
stack_trace("[type] didn't implement apply_speech.")
|
||||
return original_char
|
||||
return original_word
|
||||
|
||||
/datum/status_effect/speech/stutter
|
||||
id = "stutter"
|
||||
@@ -65,33 +65,41 @@
|
||||
tts_filter = "tremolo=f=10:d=0.8,rubberband=tempo=0.5"
|
||||
|
||||
/// The probability of adding a stutter to any character
|
||||
var/stutter_prob = 80
|
||||
var/stutter_prob = 75
|
||||
/// The chance of a four character stutter
|
||||
var/four_char_chance = 10
|
||||
/// The chance of a three character stutter
|
||||
var/three_char_chance = 20
|
||||
/// The chance of a two character stutter
|
||||
var/two_char_chance = 95
|
||||
/// Regex of characters we won't apply a stutter to
|
||||
var/static/regex/no_stutter
|
||||
var/two_char_chance = 90
|
||||
/// Regex to apply generically to stuttered words
|
||||
/// * 1st capture group is any leading invalid characters (can be empty)
|
||||
/// * 2nd capture group is either a digraph (th, qu, ch) or a consonant
|
||||
/// * 3rd capture group is the rest of the word (can be empty)
|
||||
VAR_FINAL/static/regex/stutter_regex
|
||||
|
||||
/datum/status_effect/speech/stutter/on_creation(mob/living/new_owner, ...)
|
||||
. = ..()
|
||||
if(!.)
|
||||
return
|
||||
if(!no_stutter)
|
||||
no_stutter = regex(@@[aeiouAEIOU ""''()[\]{}.!?,:;_`~-]@)
|
||||
stutter_regex ||= regex(@@^([\s"'()[\]{}.!?,:;_`~-]*\b)([^aeoiuh\d]h|qu|[^\d])(.*)@, "i")
|
||||
return ..()
|
||||
|
||||
/datum/status_effect/speech/stutter/apply_speech(original_char)
|
||||
if(prob(stutter_prob) && !no_stutter.Find(original_char))
|
||||
if(prob(four_char_chance))
|
||||
return "[original_char]-[original_char]-[original_char]-[original_char]"
|
||||
if(prob(three_char_chance))
|
||||
return "[original_char]-[original_char]-[original_char]"
|
||||
if(prob(two_char_chance))
|
||||
return "[original_char]-[original_char]"
|
||||
/datum/status_effect/speech/stutter/apply_speech(original_word, index)
|
||||
if(!prob(stutter_prob))
|
||||
return original_word
|
||||
|
||||
return original_char
|
||||
if(stutter_regex.Find(original_word))
|
||||
return "[stutter_regex.group[1]][stutter_char(stutter_regex.group[2])][stutter_regex.group[3]]"
|
||||
|
||||
return original_word // i give up
|
||||
|
||||
/datum/status_effect/speech/stutter/proc/stutter_char(some_char)
|
||||
if(prob(four_char_chance))
|
||||
return "[some_char]-[some_char]-[some_char]-[some_char]"
|
||||
if(prob(three_char_chance))
|
||||
return "[some_char]-[some_char]-[some_char]"
|
||||
if(prob(two_char_chance))
|
||||
return "[some_char]-[some_char]"
|
||||
|
||||
return some_char
|
||||
|
||||
/datum/status_effect/speech/stutter/anxiety
|
||||
id = "anxiety_stutter"
|
||||
@@ -133,7 +141,7 @@
|
||||
if(prob(capitalize_prob))
|
||||
var/exclamation = pick("!", "!!", "!!!")
|
||||
message = uppertext(message)
|
||||
message += "[apply_speech(exclamation, exclamation)]"
|
||||
message += "[stutter_char(exclamation)]"
|
||||
|
||||
message_args[TREAT_MESSAGE_ARG] = message
|
||||
|
||||
@@ -170,6 +178,12 @@
|
||||
/// Strings that are appended to a character - populated in on_creation
|
||||
var/list/string_additions
|
||||
|
||||
/// Regex for characters we won't apply any slurring to
|
||||
var/static/regex/no_slur
|
||||
|
||||
/// If the last character we processed was a replacement, don't do another replacement right after it
|
||||
VAR_PRIVATE/replacement_dupe_check = FALSE
|
||||
|
||||
/datum/status_effect/speech/slurring/on_creation(mob/living/new_owner, duration = 10 SECONDS)
|
||||
. = ..()
|
||||
if(!.)
|
||||
@@ -184,46 +198,57 @@
|
||||
string_replacements = speech_changes["string_replacements"]
|
||||
string_additions = speech_changes["string_additions"]
|
||||
|
||||
/datum/status_effect/speech/slurring/apply_speech(original_char)
|
||||
no_slur ||= regex(@@[ "'()[\]{}.!?,:;_`~-]@)
|
||||
|
||||
/datum/status_effect/speech/slurring/apply_speech(original_word, index)
|
||||
var/original_char = ""
|
||||
var/modified_word = ""
|
||||
for(var/i = 1, i <= length(original_word), i += length(original_char))
|
||||
original_char = original_word[i]
|
||||
modified_word += slur_character(original_char, i)
|
||||
return modified_word
|
||||
|
||||
/datum/status_effect/speech/slurring/proc/slur_character(original_char, index)
|
||||
var/modified_char = original_char
|
||||
var/allow_slurring = index != 1 && !no_slur.Find(modified_char)
|
||||
var/lower_char = LOWER_TEXT(modified_char)
|
||||
if(prob(common_prob) && (lower_char in common_replacements))
|
||||
var/to_replace = common_replacements[lower_char]
|
||||
if(islist(to_replace))
|
||||
modified_char = pick(to_replace)
|
||||
else
|
||||
modified_char = to_replace
|
||||
modified_char = islist(to_replace) ? pick(to_replace) : to_replace
|
||||
replacement_dupe_check = FALSE
|
||||
|
||||
if(prob(uncommon_prob) && (modified_char in uncommon_replacements))
|
||||
else if(prob(uncommon_prob) && (modified_char in uncommon_replacements))
|
||||
var/to_replace = uncommon_replacements[modified_char]
|
||||
if(islist(to_replace))
|
||||
modified_char = pick(to_replace)
|
||||
else
|
||||
modified_char = to_replace
|
||||
modified_char = islist(to_replace) ? pick(to_replace) : to_replace
|
||||
replacement_dupe_check = FALSE
|
||||
|
||||
if(prob(replacement_prob))
|
||||
var/replacements_len = length(string_replacements)
|
||||
var/additions_len = length(string_additions)
|
||||
if(replacements_len && additions_len)
|
||||
// Calculate the probability of grabbing a replacement vs an addition
|
||||
var/weight = (replacements_len + additions_len) / replacements_len * 100
|
||||
if(prob(weight))
|
||||
else if(allow_slurring) // Don't do replacements on the first character, or punctuation
|
||||
if(!replacement_dupe_check && prob(replacement_prob))
|
||||
var/replacements_len = length(string_replacements)
|
||||
var/additions_len = length(string_additions)
|
||||
if(replacements_len && additions_len)
|
||||
// Calculate the probability of grabbing a replacement vs an addition
|
||||
var/weight = (replacements_len + additions_len) / replacements_len * 100
|
||||
if(prob(weight))
|
||||
modified_char = pick(string_replacements)
|
||||
else
|
||||
modified_char += pick(string_additions)
|
||||
|
||||
else if(replacements_len)
|
||||
modified_char = pick(string_replacements)
|
||||
else
|
||||
|
||||
else if(additions_len)
|
||||
modified_char += pick(string_additions)
|
||||
replacement_dupe_check = TRUE
|
||||
|
||||
else if(replacements_len)
|
||||
modified_char = pick(string_replacements)
|
||||
else if(prob(doubletext_prob))
|
||||
modified_char += "[modified_char][prob(50) ? "" : modified_char]"
|
||||
replacement_dupe_check = FALSE
|
||||
|
||||
else if(additions_len)
|
||||
modified_char += pick(string_additions)
|
||||
|
||||
if(prob(doubletext_prob))
|
||||
if(prob(50))
|
||||
modified_char += "[modified_char]"
|
||||
else
|
||||
modified_char += "[modified_char][modified_char]"
|
||||
else
|
||||
// If we don't allow replacements we don't want the next character to be a replacement either
|
||||
// This makes some more coherent speech by disallowing structures like "Y'''e"
|
||||
replacement_dupe_check = TRUE
|
||||
|
||||
return modified_char
|
||||
|
||||
@@ -231,8 +256,8 @@
|
||||
id = "generic_slurring"
|
||||
common_prob = 33
|
||||
uncommon_prob = 0
|
||||
replacement_prob = 5
|
||||
doubletext_prob = 10
|
||||
replacement_prob = 24
|
||||
doubletext_prob = 40
|
||||
text_modification_file = "slurring_drunk_text.json"
|
||||
|
||||
/datum/status_effect/speech/slurring/drunk
|
||||
@@ -248,13 +273,13 @@
|
||||
var/current_drunkness = owner.get_drunk_amount()
|
||||
// These numbers are arbitarily picked
|
||||
// Common replacements start at about 20, and maxes out at about 85
|
||||
common_prob = clamp((current_drunkness * 0.8) - 16, 0, 50)
|
||||
common_prob = clamp((current_drunkness * 0.8) - 16, 4, 50)
|
||||
// Uncommon replacements (burping) start at 50 and max out at 110 (when you are dying)
|
||||
uncommon_prob = clamp((current_drunkness * 0.2) - 10, 0, 12)
|
||||
uncommon_prob = clamp((current_drunkness * 0.3) - 10, 0, 12)
|
||||
// Replacements start at 20 and max out at about 60
|
||||
replacement_prob = clamp((current_drunkness * 0.4) - 8, 0, 12)
|
||||
replacement_prob = clamp((current_drunkness * 0.6) - 8, 0, 12)
|
||||
// Double texting start out at about 25 and max out at about 60
|
||||
doubletext_prob = clamp((current_drunkness * 0.5) - 12, 0, 20)
|
||||
doubletext_prob = clamp((current_drunkness * 0.8) - 8, 2, 50)
|
||||
return ..()
|
||||
|
||||
/datum/status_effect/speech/slurring/cult
|
||||
|
||||
@@ -340,7 +340,7 @@
|
||||
/datum/storage/unfathomable_curio/New(atom/parent, max_slots, max_specific_storage, max_total_storage, rustle_sound, remove_rustle_sound)
|
||||
. = ..()
|
||||
set_holdable(list(
|
||||
/obj/item/ammo_box/strilka310/lionhunter,
|
||||
/obj/item/ammo_box/speedloader/strilka310/lionhunter,
|
||||
/obj/item/heretic_labyrinth_handbook,
|
||||
/obj/item/bodypart, // Bodyparts are often used in rituals.
|
||||
/obj/item/clothing/neck/eldritch_amulet,
|
||||
|
||||
@@ -55,9 +55,7 @@
|
||||
/obj/item/ammo_box/magazine/m45,
|
||||
/obj/item/ammo_box/magazine/m50,
|
||||
/obj/item/gun/ballistic/revolver,
|
||||
/obj/item/ammo_box/c38, // Revolver speedloaders.
|
||||
/obj/item/ammo_box/a357,
|
||||
/obj/item/ammo_box/strilka310,
|
||||
/obj/item/ammo_box/speedloader, // Speedloaders, which includes stripper clips on a technicality.
|
||||
/obj/item/ammo_box/magazine/toy/pistol,
|
||||
/obj/item/gun/energy/e_gun/mini,
|
||||
/obj/item/gun/energy/disabler,
|
||||
@@ -84,9 +82,7 @@
|
||||
/obj/item/ammo_box/magazine/m45,
|
||||
/obj/item/ammo_box/magazine/m50,
|
||||
/obj/item/gun/ballistic/revolver,
|
||||
/obj/item/ammo_box/c38,
|
||||
/obj/item/ammo_box/a357,
|
||||
/obj/item/ammo_box/strilka310,
|
||||
/obj/item/ammo_box/speedloader,
|
||||
/obj/item/ammo_box/magazine/toy/pistol,
|
||||
/obj/item/gun/energy/recharge/ebow,
|
||||
/obj/item/gun/energy/e_gun/mini,
|
||||
@@ -107,9 +103,7 @@
|
||||
holdables = list(
|
||||
/obj/item/gun, // ALL guns.
|
||||
/obj/item/ammo_box/magazine, // ALL magazines.
|
||||
/obj/item/ammo_box/c38, //There isn't a speedloader parent type, so I just put these three here by hand.
|
||||
/obj/item/ammo_box/a357, //I didn't want to just use /obj/item/ammo_box, because then this could hold huge boxes of ammo.
|
||||
/obj/item/ammo_box/strilka310,
|
||||
/obj/item/ammo_box/speedloader, // ALL speedloaders (there's 3 types at time of writing so it's probably fine)
|
||||
/obj/item/ammo_casing, // For shotgun shells, rockets, launcher grenades, and a few other things.
|
||||
/obj/item/grenade, // All regular grenades, the big grenade launcher fires these.
|
||||
)
|
||||
|
||||
@@ -216,7 +216,7 @@
|
||||
/obj/item/reagent_containers/cup/glass/bottle/vodka,
|
||||
/obj/item/reagent_containers/cup/glass/bottle/molotov,
|
||||
/obj/item/reagent_containers/cup/glass/drinkingglass,
|
||||
/obj/item/ammo_box/strilka310
|
||||
/obj/item/ammo_box/speedloader/strilka310
|
||||
))
|
||||
|
||||
///Void cloak pocket
|
||||
@@ -234,7 +234,7 @@
|
||||
. = ..()
|
||||
set_holdable(
|
||||
can_hold_list = list(
|
||||
/obj/item/ammo_box/strilka310/lionhunter,
|
||||
/obj/item/ammo_box/speedloader/strilka310/lionhunter,
|
||||
/obj/item/bodypart, // Bodyparts are often used in rituals. They're also often normal sized, so you can only fit one.
|
||||
/obj/item/clothing/neck/eldritch_amulet,
|
||||
/obj/item/clothing/neck/heretic_focus,
|
||||
|
||||
@@ -158,7 +158,7 @@
|
||||
if (!length(suggested_wounding_types))
|
||||
return FALSE
|
||||
|
||||
for (var/iter_wounding_type as anything in suggested_wounding_types)
|
||||
for (var/iter_wounding_type in suggested_wounding_types)
|
||||
if (!(iter_wounding_type in required_wounding_types))
|
||||
if (match_all_wounding_types)
|
||||
return FALSE
|
||||
|
||||
@@ -725,7 +725,7 @@
|
||||
// fleshy burns will look for flesh then bone
|
||||
// dislocations will look for flesh, then bone, then metal
|
||||
var/file = default_scar_file
|
||||
for (var/biotype as anything in pregen_data.scar_priorities)
|
||||
for (var/biotype in pregen_data.scar_priorities)
|
||||
if (scarred_limb.biological_state & text2num(biotype))
|
||||
file = GLOB.biotypes_to_scar_file[biotype]
|
||||
break
|
||||
|
||||
@@ -162,7 +162,12 @@
|
||||
/atom/proc/get_name_chaser(mob/user, list/name_chaser = list())
|
||||
return name_chaser
|
||||
|
||||
/// Used by mobs to determine the name for someone wearing a mask, or with a disfigured or missing face. By default just returns the atom's name. add_id_name will control whether or not we append "(as [id_name])".
|
||||
/// force_real_name will always return real_name and add (as face_name/id_name) if it doesn't match their appearance
|
||||
/atom/proc/get_visible_name(add_id_name, force_real_name)
|
||||
/**
|
||||
* Used by mobs to determine the name for someone wearing a mask, or with a disfigured or missing face.
|
||||
* By default just returns the atom's name.
|
||||
*
|
||||
* * add_id_name - If TRUE, ID information such as honorifics or name (if mismatched) are appended
|
||||
* * force_real_name - If TRUE, will always return real_name and add (as face_name/id_name) if it doesn't match their appearance
|
||||
*/
|
||||
/atom/proc/get_visible_name(add_id_name = TRUE, force_real_name = FALSE)
|
||||
return name
|
||||
|
||||
@@ -1056,7 +1056,7 @@
|
||||
var/list/part_list = replacer_tool.get_sorted_parts(ignore_stacks = TRUE)
|
||||
if(!part_list.len)
|
||||
return FALSE
|
||||
for(var/primary_part_base as anything in component_parts)
|
||||
for(var/primary_part_base in component_parts)
|
||||
//we exchanged all we could time to bail
|
||||
if(!part_list.len)
|
||||
break
|
||||
@@ -1156,7 +1156,7 @@
|
||||
// we infer the required stack stuff inside the machine from the circuitboards requested components
|
||||
if(istype(component_ref, /obj/item/circuitboard/machine))
|
||||
var/obj/item/circuitboard/machine/board = component_ref
|
||||
for(var/component as anything in board.req_components)
|
||||
for(var/component in board.req_components)
|
||||
if(!ispath(component, /obj/item/stack))
|
||||
continue
|
||||
part_count[component] = board.req_components[component]
|
||||
|
||||
@@ -391,7 +391,7 @@
|
||||
data["enemy_mp"] = enemy_mp
|
||||
|
||||
data["equipped_gear"] = list()
|
||||
for(var/gear_slot as anything in equipped_gear)
|
||||
for(var/gear_slot in equipped_gear)
|
||||
var/datum/battle_arcade_gear/user_gear = equipped_gear[gear_slot]
|
||||
if(!istype(user_gear))
|
||||
continue
|
||||
|
||||
@@ -44,7 +44,7 @@
|
||||
/obj/machinery/door/password/get_save_vars()
|
||||
return ..() + NAMEOF(src, password)
|
||||
|
||||
/obj/machinery/door/password/Hear(message, atom/movable/speaker, message_language, raw_message, radio_freq, radio_freq_name, radio_freq_color, list/spans, list/message_mods = list(), message_range)
|
||||
/obj/machinery/door/password/Hear(atom/movable/speaker, message_language, raw_message, radio_freq, radio_freq_name, radio_freq_color, list/spans, list/message_mods = list(), message_range)
|
||||
. = ..()
|
||||
if(!density || !voice_activated || radio_freq)
|
||||
return
|
||||
|
||||
@@ -19,16 +19,22 @@
|
||||
/// The current deconstruction step
|
||||
var/deconstruction = BLASTDOOR_FINISHED
|
||||
/// The door's ID (used for buttons, etc to control the door)
|
||||
var/id = 1
|
||||
var/id = null
|
||||
/// The sound that plays when the door opens/closes
|
||||
var/animation_sound = 'sound/machines/blastdoor.ogg'
|
||||
var/show_nav_computer_icon = TRUE
|
||||
///The mob who crafted this blastdoor
|
||||
var/datum/weakref/owner
|
||||
|
||||
/obj/machinery/door/poddoor/Initialize(mapload)
|
||||
. = ..()
|
||||
if(show_nav_computer_icon)
|
||||
AddElement(/datum/element/nav_computer_icon, 'icons/effects/nav_computer_indicators.dmi', "airlock", TRUE)
|
||||
|
||||
/obj/machinery/door/poddoor/Destroy()
|
||||
owner = null
|
||||
return ..()
|
||||
|
||||
/datum/armor/door_poddoor
|
||||
melee = 50
|
||||
bullet = 100
|
||||
@@ -46,7 +52,7 @@
|
||||
if(panel_open)
|
||||
if(deconstruction == BLASTDOOR_FINISHED)
|
||||
. += span_notice("The maintenance panel is opened and the electronics could be <b>pried</b> out.")
|
||||
. += span_notice("\The [src] could be calibrated to a blast door controller ID with a <b>multitool</b> or a <b>blast door controller</b>.")
|
||||
. += span_notice("\The [src] could be calibrated to a blast door controller ID with a <b>blast door controller</b>.")
|
||||
else if(deconstruction == BLASTDOOR_NEEDS_ELECTRONICS)
|
||||
. += span_notice("The <i>electronics</i> are missing and there are some <b>wires</b> sticking out.")
|
||||
else if(deconstruction == BLASTDOOR_NEEDS_WIRES)
|
||||
@@ -71,9 +77,6 @@
|
||||
if(TOOL_SCREWDRIVER)
|
||||
context[SCREENTIP_CONTEXT_LMB] = "Open panel"
|
||||
return CONTEXTUAL_SCREENTIP_SET
|
||||
if(TOOL_MULTITOOL)
|
||||
context[SCREENTIP_CONTEXT_LMB] = "Calibrate ID"
|
||||
return CONTEXTUAL_SCREENTIP_SET
|
||||
if(TOOL_CROWBAR)
|
||||
context[SCREENTIP_CONTEXT_LMB] = "Remove electronics"
|
||||
return CONTEXTUAL_SCREENTIP_SET
|
||||
@@ -84,6 +87,10 @@
|
||||
context[SCREENTIP_CONTEXT_LMB] = "Disassemble"
|
||||
return CONTEXTUAL_SCREENTIP_SET
|
||||
|
||||
/obj/machinery/door/poddoor/on_craft_completion(list/components, datum/crafting_recipe/current_recipe, atom/crafter)
|
||||
. = ..()
|
||||
owner = WEAKREF(crafter)
|
||||
|
||||
/obj/machinery/door/poddoor/item_interaction(mob/living/user, obj/item/tool, list/modifiers)
|
||||
if(deconstruction == BLASTDOOR_NEEDS_WIRES && istype(tool, /obj/item/stack/cable_coil))
|
||||
var/obj/item/stack/cable_coil/coil = tool
|
||||
@@ -117,8 +124,22 @@
|
||||
balloon_alert(user, "open the panel first!")
|
||||
return ITEM_INTERACT_BLOCKING
|
||||
var/obj/item/assembly/control/controller_item = tool
|
||||
if(controller_item.id == -1)
|
||||
//collect existing ids
|
||||
var/list/door_ids = list()
|
||||
for(var/obj/machinery/door/poddoor/M as anything in SSmachines.get_machines_by_type_and_subtypes(/obj/machinery/door/poddoor))
|
||||
if(!M.id || (M.id in door_ids))
|
||||
continue
|
||||
door_ids += "[M.id]"
|
||||
|
||||
//create new id
|
||||
var/new_id = 0
|
||||
while("[new_id]" in door_ids)
|
||||
new_id += 1
|
||||
controller_item.id = "[new_id]"
|
||||
id = controller_item.id
|
||||
balloon_alert(user, "id changed")
|
||||
owner = WEAKREF(user)
|
||||
balloon_alert(user, "id changed to [id]")
|
||||
return ITEM_INTERACT_SUCCESS
|
||||
|
||||
return NONE
|
||||
@@ -131,24 +152,6 @@
|
||||
else if (default_deconstruction_screwdriver(user, icon_state, icon_state, tool))
|
||||
return ITEM_INTERACT_SUCCESS
|
||||
|
||||
/obj/machinery/door/poddoor/multitool_act(mob/living/user, obj/item/tool)
|
||||
. = ..()
|
||||
if (density)
|
||||
balloon_alert(user, "open the door first!")
|
||||
return ITEM_INTERACT_SUCCESS
|
||||
if (!panel_open)
|
||||
balloon_alert(user, "open the panel first!")
|
||||
return ITEM_INTERACT_SUCCESS
|
||||
if (deconstruction != BLASTDOOR_FINISHED)
|
||||
return
|
||||
var/change_id = tgui_input_number(user, "Set the door controllers ID (Current: [id])", "Door Controller ID", isnum(id) ? id : null, 100)
|
||||
if(!change_id || QDELETED(usr) || QDELETED(src) || !usr.can_perform_action(src, FORBID_TELEKINESIS_REACH))
|
||||
return
|
||||
id = change_id
|
||||
to_chat(user, span_notice("You change the ID to [id]."))
|
||||
balloon_alert(user, "id changed")
|
||||
return ITEM_INTERACT_SUCCESS
|
||||
|
||||
/obj/machinery/door/poddoor/crowbar_act(mob/living/user, obj/item/tool)
|
||||
. = ..()
|
||||
if(machine_stat & NOPOWER)
|
||||
@@ -166,6 +169,7 @@
|
||||
if(tool.use_tool(src, user, 10 SECONDS, volume = 50))
|
||||
new /obj/item/electronics/airlock(loc)
|
||||
id = null
|
||||
owner = null
|
||||
deconstruction = BLASTDOOR_NEEDS_ELECTRONICS
|
||||
balloon_alert(user, "removed airlock electronics")
|
||||
return ITEM_INTERACT_SUCCESS
|
||||
|
||||
@@ -212,7 +212,7 @@
|
||||
if(energy_used)
|
||||
use_energy(energy_used)
|
||||
|
||||
for(var/spawnable_item as anything in dispense_type)
|
||||
for(var/spawnable_item in dispense_type)
|
||||
var/atom/spawned_atom = new spawnable_item(loc)
|
||||
spawned_atom.flags_1 |= (flags_1 & ADMIN_SPAWNED_1)
|
||||
|
||||
@@ -237,7 +237,7 @@
|
||||
/obj/machinery/drone_dispenser/proc/count_shells()
|
||||
. = 0
|
||||
for(var/actual_shell in loc)
|
||||
for(var/potential_item as anything in dispense_type)
|
||||
for(var/potential_item in dispense_type)
|
||||
if(istype(actual_shell, potential_item))
|
||||
.++
|
||||
|
||||
|
||||
@@ -69,10 +69,10 @@
|
||||
|
||||
dna.copy_dna(subject.dna, COPY_DNA_SE|COPY_DNA_SPECIES)
|
||||
|
||||
for (var/quirk_type as anything in quirks)
|
||||
for (var/quirk_type in quirks)
|
||||
subject.add_quirk(quirk_type, add_unique = FALSE, announce = FALSE)
|
||||
|
||||
for (var/trauma_type as anything in brain_traumas)
|
||||
for (var/trauma_type in brain_traumas)
|
||||
subject.gain_trauma(trauma_type)
|
||||
|
||||
for (var/obj/item/bodypart/limb as anything in subject.bodyparts)
|
||||
|
||||
@@ -235,7 +235,7 @@
|
||||
inserted_board = attacking_item
|
||||
|
||||
//compute the needed mats from its stock parts
|
||||
for(var/type as anything in inserted_board.req_components)
|
||||
for(var/type in inserted_board.req_components)
|
||||
//these don't count to the final cost as they have to inserted manually
|
||||
if(type in inserted_board.flatpack_components)
|
||||
continue
|
||||
|
||||
@@ -577,19 +577,19 @@ Possible to do for anyone motivated enough:
|
||||
|
||||
/*This is the proc for special two-way communication between AI and holopad/people talking near holopad.
|
||||
For the other part of the code, check silicon say.dm. Particularly robot talk.*/
|
||||
/obj/machinery/holopad/Hear(message, atom/movable/speaker, datum/language/message_language, raw_message, radio_freq, radio_freq_name, radio_freq_color, list/spans, list/message_mods = list(), message_range)
|
||||
/obj/machinery/holopad/Hear(atom/movable/speaker, datum/language/message_language, raw_message, radio_freq, radio_freq_name, radio_freq_color, list/spans, list/message_mods = list(), message_range)
|
||||
. = ..()
|
||||
if(speaker && LAZYLEN(masters) && !radio_freq)//Master is mostly a safety in case lag hits or something. Radio_freq so AIs dont hear holopad stuff through radios.
|
||||
for(var/mob/living/silicon/ai/master in masters)
|
||||
if(masters[master] && speaker != master)
|
||||
master.relay_speech(message, speaker, message_language, raw_message, radio_freq, spans, message_mods)
|
||||
master.relay_speech(speaker, message_language, raw_message, radio_freq, spans, message_mods)
|
||||
|
||||
for(var/datum/holocall/holocall_to_update as anything in holo_calls)
|
||||
if(holocall_to_update.connected_holopad == src)//if we answered this call originating from another holopad
|
||||
if(speaker == holocall_to_update.hologram && holocall_to_update.user.client?.prefs.read_preference(/datum/preference/toggle/enable_runechat))
|
||||
holocall_to_update.user.create_chat_message(speaker, message_language, raw_message, spans)
|
||||
else
|
||||
holocall_to_update.user.Hear(message, speaker, message_language, raw_message, radio_freq, radio_freq_name, radio_freq_color, spans, message_mods, message_range = INFINITY)
|
||||
holocall_to_update.user.Hear(speaker, message_language, raw_message, radio_freq, radio_freq_name, radio_freq_color, spans, message_mods, message_range = INFINITY)
|
||||
|
||||
if(outgoing_call?.hologram && speaker == outgoing_call.user)
|
||||
outgoing_call.hologram.say(raw_message, spans = spans, sanitize = FALSE, language = message_language, message_mods = message_mods)
|
||||
|
||||
@@ -92,8 +92,10 @@
|
||||
return ..()
|
||||
|
||||
/obj/machinery/quantumpad/interact(mob/user, obj/machinery/quantumpad/target_pad = linked_pad)
|
||||
if(!target_pad || QDELETED(target_pad))
|
||||
if(!map_pad_link_id || !initMappedLink())
|
||||
if(QDELETED(target_pad))
|
||||
if(map_pad_link_id && initMappedLink())
|
||||
target_pad = linked_pad
|
||||
else
|
||||
to_chat(user, span_warning("Target pad not found!"))
|
||||
return
|
||||
//SKYRAT EDIT ADDITION
|
||||
|
||||
@@ -174,14 +174,13 @@
|
||||
// Always call this on the virtualspeaker to avoid issues.
|
||||
var/spans = data["spans"]
|
||||
var/list/message_mods = data["mods"]
|
||||
var/rendered = virt.compose_message(virt, language, message, frequency, data["frequency_name"], data["frequency_color"], spans)
|
||||
|
||||
for(var/atom/movable/hearer as anything in receive)
|
||||
if(!hearer)
|
||||
stack_trace("null found in the hearers list returned by the spatial grid. this is bad")
|
||||
continue
|
||||
spans -= blacklisted_spans
|
||||
hearer.Hear(rendered, virt, language, message, frequency, data["frequency_name"], data["frequency_color"], spans, message_mods, message_range = INFINITY)
|
||||
hearer.Hear(virt, language, message, frequency, data["frequency_name"], data["frequency_color"], spans, message_mods, message_range = INFINITY)
|
||||
|
||||
// This following recording is intended for research and feedback in the use of department radio channels
|
||||
if(length(receive))
|
||||
|
||||
@@ -27,8 +27,8 @@
|
||||
new /obj/effect/temp_visual/circle_wave/bluespace(get_turf(src))
|
||||
playsound(src, 'sound/effects/magic/cosmic_energy.ogg', vol = 50)
|
||||
|
||||
var/turf/T = pick(get_area_turfs(impact_area))
|
||||
if(!T)
|
||||
var/turf/impact_turf = pick(get_area_turfs(impact_area))
|
||||
if(!impact_turf)
|
||||
return
|
||||
|
||||
// Calculate new position (searches through beacons in world)
|
||||
@@ -51,39 +51,31 @@
|
||||
return
|
||||
|
||||
// Calculate previous position for transition
|
||||
var/turf/FROM = T // the turf of origin we're travelling FROM
|
||||
var/turf/TO = get_turf(chosen) // the turf of origin we're travelling TO
|
||||
var/turf/beacon_turf = get_turf(chosen) // the turf of origin we're travelling TO
|
||||
|
||||
playsound(TO, 'sound/effects/phasein.ogg', 100, TRUE)
|
||||
playsound(beacon_turf, 'sound/effects/phasein.ogg', 100, TRUE)
|
||||
priority_announce("Massive bluespace translocation detected.", "Anomaly Alert")
|
||||
|
||||
var/list/flashers = list()
|
||||
for(var/mob/living/carbon/C in viewers(TO, null))
|
||||
if(C.flash_act())
|
||||
flashers += C
|
||||
for(var/mob/living/living in viewers(beacon_turf, null))
|
||||
if(living.flash_act(affect_silicon = TRUE, visual = TRUE, type = /atom/movable/screen/fullscreen/bluespace_sparkle, length = 2 SECONDS))
|
||||
flashers += living
|
||||
|
||||
var/y_distance = TO.y - FROM.y
|
||||
var/x_distance = TO.x - FROM.x
|
||||
for (var/atom/movable/A in urange(12, FROM )) // iterate thru list of mobs in the area
|
||||
if(istype(A, /obj/item/beacon))
|
||||
continue // don't teleport beacons because that's just insanely stupid
|
||||
if(iseyemob(A))
|
||||
continue // Don't mess with AI eye, blob eye, xenobio or advanced cameras
|
||||
if(A.anchored)
|
||||
continue
|
||||
var/y_distance = beacon_turf.y - impact_turf.y
|
||||
var/x_distance = beacon_turf.x - impact_turf.x
|
||||
var/list/available_turfs = RANGE_TURFS(12, beacon_turf)
|
||||
for (var/atom/movable/movable in urange(12, impact_turf )) // iterate thru list of mobs in the area
|
||||
if(istype(movable, /obj/item/beacon) || iseffect(movable) || iseyemob(movable))
|
||||
continue // Don't mess with beacons, effects or camera mobs (blob, AI eye etc...)
|
||||
if(movable.anchored)
|
||||
continue // do_teleport doesn't check if the item is anchored or not.
|
||||
|
||||
var/turf/newloc = locate(A.x + x_distance, A.y + y_distance, TO.z) // calculate the new place
|
||||
if(!A.Move(newloc) && newloc) // if the atom, for some reason, can't move, FORCE them to move! :) We try Move() first to invoke any movement-related checks the atom needs to perform after moving
|
||||
A.forceMove(newloc)
|
||||
var/turf/newloc = locate(movable.x + x_distance, movable.y + y_distance, beacon_turf.z) || pick(available_turfs) // calculate the new place, or pick a random one as fallback
|
||||
do_teleport(movable, newloc, no_effects = TRUE)
|
||||
|
||||
if(ismob(A) && !(A in flashers)) // don't flash if we're already doing an effect
|
||||
var/mob/give_sparkles = A
|
||||
if(give_sparkles.client)
|
||||
blue_effect(give_sparkles)
|
||||
|
||||
/obj/effect/anomaly/bluespace/proc/blue_effect(mob/make_sparkle)
|
||||
make_sparkle.overlay_fullscreen("bluespace_flash", /atom/movable/screen/fullscreen/bluespace_sparkle, 1)
|
||||
addtimer(CALLBACK(make_sparkle, TYPE_PROC_REF(/mob/, clear_fullscreen), "bluespace_flash"), 2 SECONDS)
|
||||
if(isliving(movable) && !(movable in flashers)) // don't flash if we're already doing an effect
|
||||
var/mob/living/give_sparkles = movable
|
||||
give_sparkles.flash_act(affect_silicon = TRUE, visual = TRUE, type = /atom/movable/screen/fullscreen/bluespace_sparkle, length = 2 SECONDS)
|
||||
|
||||
/obj/effect/anomaly/bluespace/stabilize(anchor, has_core)
|
||||
. = ..()
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
/obj/effect/spawner/random/sakhno/ammo
|
||||
name = ".310 Strilka stripper clip spawner"
|
||||
loot = list(
|
||||
/obj/item/ammo_box/strilka310/surplus = 80,
|
||||
/obj/item/ammo_box/strilka310 = 10,
|
||||
/obj/item/ammo_box/speedloader/strilka310/surplus = 80,
|
||||
/obj/item/ammo_box/speedloader/strilka310 = 10,
|
||||
/obj/item/food/rationpack = 1,
|
||||
)
|
||||
|
||||
@@ -102,6 +102,9 @@
|
||||
/obj/item/radio/intercom/attack_ai(mob/user)
|
||||
interact(user)
|
||||
|
||||
/obj/item/radio/intercom/attack_robot(mob/user)
|
||||
interact(user)
|
||||
|
||||
/obj/item/radio/intercom/attack_hand(mob/user, list/modifiers)
|
||||
. = ..()
|
||||
if(.)
|
||||
@@ -123,7 +126,7 @@
|
||||
|
||||
return TRUE
|
||||
|
||||
/obj/item/radio/intercom/Hear(message, atom/movable/speaker, message_langs, raw_message, radio_freq, radio_freq_name, radio_freq_color, list/spans, list/message_mods = list(), message_range)
|
||||
/obj/item/radio/intercom/Hear(atom/movable/speaker, message_langs, raw_message, radio_freq, radio_freq_name, radio_freq_color, list/spans, list/message_mods = list(), message_range)
|
||||
if(message_mods[RADIO_EXTENSION] == MODE_INTERCOM)
|
||||
return // Avoid hearing the same thing twice
|
||||
return ..()
|
||||
|
||||
@@ -381,7 +381,7 @@
|
||||
signal.levels = SSmapping.get_connected_levels(T)
|
||||
signal.broadcast()
|
||||
|
||||
/obj/item/radio/Hear(message, atom/movable/speaker, message_language, raw_message, radio_freq, radio_freq_name, radio_freq_color, list/spans, list/message_mods = list(), message_range)
|
||||
/obj/item/radio/Hear(atom/movable/speaker, message_language, raw_message, radio_freq, radio_freq_name, radio_freq_color, list/spans, list/message_mods = list(), message_range)
|
||||
. = ..()
|
||||
if(radio_freq || !broadcasting || get_dist(src, speaker) > canhear_range || message_mods[MODE_RELAY])
|
||||
return
|
||||
|
||||
@@ -190,7 +190,17 @@
|
||||
render_list += "<span class='alert ml-1'>Fatigue level: [target.getStaminaLoss()]%.</span><br>"
|
||||
else
|
||||
render_list += "<span class='alert ml-1'>Subject appears to be suffering from fatigue.</span><br>"
|
||||
if (!target.get_organ_slot(ORGAN_SLOT_BRAIN)) // kept exclusively for soul purposes
|
||||
|
||||
// Check for brain - both organic (carbon) and synthetic (cyborg MMI)
|
||||
var/has_brain = FALSE
|
||||
if(target.get_organ_slot(ORGAN_SLOT_BRAIN))
|
||||
has_brain = TRUE
|
||||
else if(iscyborg(target))
|
||||
var/mob/living/silicon/robot/cyborg_target = target
|
||||
if(cyborg_target.mmi?.brain)
|
||||
has_brain = TRUE
|
||||
|
||||
if(!has_brain) // kept exclusively for soul purposes
|
||||
render_list += "<span class='alert ml-1'>Subject lacks a brain.</span><br>"
|
||||
|
||||
if(iscarbon(target))
|
||||
|
||||
@@ -153,7 +153,7 @@
|
||||
return ..()
|
||||
|
||||
|
||||
/obj/item/taperecorder/Hear(message, atom/movable/speaker, message_langs, raw_message, radio_freq, radio_freq_name, radio_freq_color, spans, list/message_mods = list(), message_range)
|
||||
/obj/item/taperecorder/Hear(atom/movable/speaker, message_langs, raw_message, radio_freq, radio_freq_name, radio_freq_color, spans, list/message_mods = list(), message_range)
|
||||
. = ..()
|
||||
if(message_mods[MODE_RELAY] || !mytape || istype(speaker, /obj/item/taperecorder))
|
||||
return
|
||||
|
||||
@@ -165,8 +165,8 @@
|
||||
|
||||
//check if we can build our window on the grill
|
||||
if(target_turf.is_blocked_turf(exclude_mobs = !is_full_tile, source_atom = null, ignore_atoms = structures_to_ignore, type_list = TRUE))
|
||||
playsound(get_turf(user), SFX_TOOL_SWITCH, 20, TRUE)
|
||||
balloon_alert(user, "something is blocking the turf")
|
||||
playsound(user, SFX_TOOL_SWITCH, 20, TRUE)
|
||||
balloon_alert(user, "tile is blocked!")
|
||||
return FALSE
|
||||
|
||||
/**
|
||||
@@ -344,7 +344,7 @@
|
||||
data["selected_root"] = root_category
|
||||
|
||||
data["categories"] = list()
|
||||
for(var/sub_category as anything in GLOB.rcd_designs[root_category])
|
||||
for(var/sub_category in GLOB.rcd_designs[root_category])
|
||||
var/list/target_category = GLOB.rcd_designs[root_category][sub_category]
|
||||
if(!length(target_category))
|
||||
continue
|
||||
@@ -529,15 +529,10 @@
|
||||
/obj/item/construction/rcd/ce
|
||||
name = "professional RCD"
|
||||
desc = "A higher-end model of the rapid construction device, prefitted with improved cooling and disruption prevention. Provided to the chief engineer."
|
||||
icon_state = "cercd"
|
||||
inhand_icon_state = "cercd"
|
||||
construction_upgrades = RCD_UPGRADE_ANTI_INTERRUPT | RCD_UPGRADE_NO_FREQUENT_USE_COOLDOWN
|
||||
matter = 160
|
||||
color = list(
|
||||
0.3, 0.3, 0.7, 0.0,
|
||||
1.0, 1.0, 0.2, 0.0,
|
||||
-0.2, 0.0, 1.0, 0.0,
|
||||
0.0, 0.0, 0.0, 1.0,
|
||||
0.0, 0.0, 0.0, 0.0,
|
||||
)
|
||||
|
||||
/obj/item/construction/rcd/combat
|
||||
name = "industrial RCD"
|
||||
|
||||
@@ -206,13 +206,13 @@
|
||||
var/is_allowed = TRUE
|
||||
if(!checkResource(cost, user) || !(is_allowed = canPlace(destination)))
|
||||
if(!is_allowed)
|
||||
balloon_alert(user, "turf is blocked!")
|
||||
balloon_alert(user, "tile is blocked!")
|
||||
return FALSE
|
||||
if(!build_delay(user, cost, target = destination))
|
||||
return FALSE
|
||||
if(!checkResource(cost, user) || !(is_allowed = canPlace(destination)))
|
||||
if(!is_allowed)
|
||||
balloon_alert(user, "turf is blocked!")
|
||||
balloon_alert(user, "tile is blocked!")
|
||||
return FALSE
|
||||
|
||||
if(!useResource(cost, user))
|
||||
|
||||
@@ -160,7 +160,7 @@
|
||||
data["selected_root"] = root_category
|
||||
|
||||
data["categories"] = list()
|
||||
for(var/sub_category as anything in GLOB.floor_designs[root_category])
|
||||
for(var/sub_category in GLOB.floor_designs[root_category])
|
||||
var/list/target_category = GLOB.floor_designs[root_category][sub_category]
|
||||
|
||||
var/list/designs = list() //initialize all designs under this category
|
||||
|
||||
@@ -22,16 +22,6 @@
|
||||
icon_state = "securityhudnight"
|
||||
sight_mode = BORGXRAY
|
||||
|
||||
/obj/item/borg/sight/thermal
|
||||
name = "\proper thermal vision"
|
||||
sight_mode = BORGTHERM
|
||||
icon_state = "thermal"
|
||||
|
||||
/obj/item/borg/sight/meson
|
||||
name = "\proper meson vision"
|
||||
sight_mode = BORGMESON
|
||||
icon_state = "meson"
|
||||
|
||||
/obj/item/borg/sight/material
|
||||
name = "\proper material vision"
|
||||
sight_mode = BORGMATERIAL
|
||||
|
||||
@@ -132,7 +132,7 @@
|
||||
|
||||
/obj/item/borg/projectile_dampen/proc/process_usage(seconds_per_tick)
|
||||
var/usage = 0
|
||||
for(var/projectile as anything in tracked_bullet_cost)
|
||||
for(var/projectile in tracked_bullet_cost)
|
||||
usage += projectile_tick_speed_ecost * seconds_per_tick
|
||||
usage += tracked_bullet_cost[projectile] * projectile_damage_tick_ecost_coefficient * seconds_per_tick
|
||||
energy = clamp(energy - usage, 0, maxenergy)
|
||||
|
||||
@@ -57,7 +57,7 @@
|
||||
|
||||
/obj/item/storage/belt/holster/detective/full/PopulateContents()
|
||||
generate_items_inside(list(
|
||||
/obj/item/ammo_box/c38 = 2,
|
||||
/obj/item/ammo_box/speedloader/c38 = 2,
|
||||
/obj/item/gun/ballistic/revolver/c38/detective = 1,
|
||||
), src)
|
||||
|
||||
@@ -99,7 +99,7 @@
|
||||
|
||||
/obj/item/storage/belt/holster/nukie/cowboy/full/PopulateContents()
|
||||
generate_items_inside(list(
|
||||
/obj/item/ammo_box/a357 = 2,
|
||||
/obj/item/ammo_box/speedloader/c357 = 2,
|
||||
/obj/item/gun/ballistic/revolver/cowboy/nuclear = 1,
|
||||
), src)
|
||||
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user