Merge remote-tracking branch 'origin/master' into what-should-i-name-this-branch

This commit is contained in:
LetterN
2022-01-11 09:49:38 +08:00
84 changed files with 5101 additions and 3151 deletions
@@ -54,7 +54,10 @@
/area/ruin/lavaland/unpowered)
"m" = (
/obj/structure/mineral_door/wood,
/obj/effect/decal/cleanable/trail_holder,
/obj/effect/decal/cleanable/trail_holder{
color = "#dc0000";
dir = 8
},
/turf/open/floor/wood,
/area/ruin/lavaland/unpowered)
"n" = (
@@ -68,7 +71,10 @@
/obj/machinery/light/broken{
dir = 4
},
/obj/effect/decal/cleanable/trail_holder,
/obj/effect/decal/cleanable/trail_holder{
color = "#dc0000";
dir = 6
},
/turf/open/floor/wood,
/area/ruin/lavaland/unpowered)
"q" = (
@@ -93,13 +99,33 @@
/turf/open/floor/wood,
/area/ruin/lavaland/unpowered)
"s" = (
/obj/effect/decal/cleanable/trail_holder,
/obj/effect/decal/cleanable/trail_holder{
color = "#dc0000";
dir = 9
},
/turf/open/floor/wood,
/area/ruin/lavaland/unpowered)
"x" = (
/obj/effect/decal/cleanable/trail_holder{
color = "#dc0000";
dir = 8
},
/turf/open/floor/wood,
/area/ruin/lavaland/unpowered)
"N" = (
/obj/effect/decal/cleanable/trail_holder,
/obj/effect/decal/cleanable/trail_holder{
color = "#dc0000";
dir = 8
},
/turf/open/floor/plating/asteroid/basalt/lava_land_surface,
/area/lavaland/surface/outdoors)
"Q" = (
/obj/effect/decal/cleanable/trail_holder{
color = "#dc0000";
dir = 6
},
/turf/open/floor/wood,
/area/ruin/lavaland/unpowered)
(1,1,1) = {"
i
@@ -440,7 +466,7 @@ f
f
f
f
s
x
b
b
i
@@ -467,7 +493,7 @@ g
f
f
f
s
x
b
b
i
@@ -494,7 +520,7 @@ f
f
f
f
s
x
b
b
i
@@ -521,7 +547,7 @@ j
f
f
f
s
x
b
b
i
@@ -548,7 +574,7 @@ k
f
f
f
s
x
b
b
i
@@ -575,7 +601,7 @@ l
f
f
s
s
Q
b
b
i
@@ -627,7 +653,7 @@ i
b
b
b
s
x
b
b
b
@@ -654,7 +680,7 @@ i
i
i
b
s
x
b
i
i
@@ -681,7 +707,7 @@ i
i
i
b
s
x
b
i
i
@@ -708,7 +734,7 @@ i
i
i
b
s
x
b
i
i
File diff suppressed because it is too large Load Diff
+170 -124
View File
@@ -19429,6 +19429,10 @@
/obj/machinery/atmospherics/pipe/simple/orange/hidden{
dir = 4
},
/obj/machinery/firealarm{
dir = 8;
pixel_x = 24
},
/turf/open/floor/plasteel/dark/corner,
/area/hallway/primary/starboard)
"bzi" = (
@@ -21200,10 +21204,6 @@
/obj/machinery/atmospherics/pipe/simple/supply/hidden{
dir = 5
},
/obj/machinery/firealarm{
dir = 8;
pixel_x = 24
},
/obj/effect/turf_decal/tile/yellow{
dir = 4
},
@@ -24661,14 +24661,14 @@
/turf/closed/wall,
/area/maintenance/disposal/incinerator)
"bZD" = (
/obj/machinery/door/airlock/maintenance{
name = "Incinerator Access";
req_access_txt = "12"
},
/obj/machinery/atmospherics/pipe/simple/supply/hidden,
/obj/structure/cable/yellow{
icon_state = "1-2"
},
/obj/machinery/door/airlock/atmos{
name = "Turbine Access";
req_access_txt = "32"
},
/turf/open/floor/plating,
/area/maintenance/disposal/incinerator)
"bZE" = (
@@ -25285,7 +25285,10 @@
icon_state = "1-4"
},
/obj/machinery/atmospherics/pipe/simple/supply/hidden,
/turf/open/floor/plasteel,
/obj/effect/turf_decal/stripes/line{
dir = 1
},
/turf/open/floor/plating,
/area/maintenance/disposal/incinerator)
"caZ" = (
/obj/structure/cable/yellow{
@@ -25300,7 +25303,7 @@
c_tag = "Atmospherics - Incinerator";
name = "atmospherics camera"
},
/turf/open/floor/plasteel,
/turf/open/floor/plating,
/area/maintenance/disposal/incinerator)
"cba" = (
/obj/machinery/power/smes{
@@ -25310,7 +25313,7 @@
/obj/structure/cable/yellow{
icon_state = "0-8"
},
/turf/open/floor/plasteel,
/turf/open/floor/plating,
/area/maintenance/disposal/incinerator)
"cbp" = (
/obj/machinery/atmospherics/pipe/simple/supply/hidden{
@@ -25905,7 +25908,7 @@
/obj/machinery/atmospherics/pipe/simple/dark/visible{
dir = 6
},
/turf/open/floor/plasteel,
/turf/open/floor/plating,
/area/maintenance/disposal/incinerator)
"ccU" = (
/obj/structure/table/wood/poker,
@@ -44716,9 +44719,6 @@
/turf/open/floor/plasteel/dark,
/area/hallway/primary/central)
"cVp" = (
/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden{
dir = 4
},
/obj/effect/turf_decal/tile/yellow{
dir = 4
},
@@ -44812,12 +44812,8 @@
/turf/open/floor/carpet,
/area/service/theater)
"cWn" = (
/obj/machinery/door/airlock/atmos/glass{
name = "Atmospherics Monitoring";
req_access_txt = "24"
},
/obj/structure/cable/yellow{
icon_state = "4-8"
/obj/structure/disposalpipe/segment{
dir = 6
},
/turf/open/floor/plasteel,
/area/engineering/atmos)
@@ -47801,24 +47797,11 @@
/turf/open/floor/plasteel/dark,
/area/ai_monitored/aisat/exterior)
"dtk" = (
/obj/machinery/disposal/bin,
/obj/structure/disposalpipe/trunk{
dir = 8
},
/obj/effect/turf_decal/tile/yellow{
dir = 4
},
/obj/effect/turf_decal/tile/yellow{
dir = 8
},
/obj/machinery/button/door{
id = "atmos";
name = "Atmospherics Lockdown";
pixel_x = 26;
pixel_y = -26;
req_access_txt = "24"
},
/turf/open/floor/plasteel,
/obj/machinery/suit_storage_unit/atmos,
/turf/open/floor/plasteel/dark/corner,
/area/engineering/atmos)
"dtl" = (
/obj/machinery/atmospherics/pipe/simple/supply/hidden,
@@ -49353,12 +49336,8 @@
/area/maintenance/port)
"dRb" = (
/obj/machinery/atmospherics/pipe/simple/supply/hidden,
/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden{
dir = 4
},
/obj/machinery/door/airlock/atmos/glass{
name = "Atmospherics Monitoring";
req_access_txt = "24"
/obj/structure/cable/yellow{
icon_state = "2-8"
},
/turf/open/floor/plasteel,
/area/engineering/atmos)
@@ -50247,13 +50226,6 @@
},
/turf/open/floor/plasteel/dark,
/area/engineering/main)
"erz" = (
/obj/structure/cable/yellow{
icon_state = "4-8"
},
/obj/machinery/atmospherics/pipe/simple/supply/hidden,
/turf/open/floor/plasteel,
/area/engineering/atmos)
"erD" = (
/obj/machinery/reagentgrinder,
/obj/structure/table/glass,
@@ -52060,7 +52032,9 @@
dir = 8
},
/obj/machinery/pipedispenser/disposal,
/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden,
/obj/machinery/atmospherics/pipe/manifold/scrubbers/hidden{
dir = 4
},
/turf/open/floor/plasteel,
/area/engineering/atmos)
"fpr" = (
@@ -52546,12 +52520,8 @@
/turf/open/floor/plasteel/white,
/area/science/circuit)
"fFR" = (
/obj/structure/closet/crate,
/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden,
/obj/machinery/camera{
c_tag = "Atmospherics - Entrance"
},
/turf/open/floor/plasteel,
/turf/closed/wall,
/area/engineering/atmos)
"fFY" = (
/obj/structure/cable,
@@ -52799,7 +52769,12 @@
/obj/structure/cable/yellow{
icon_state = "2-4"
},
/obj/machinery/light/small,
/obj/structure/cable/yellow{
icon_state = "2-8"
},
/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden{
dir = 4
},
/turf/open/floor/plasteel,
/area/engineering/atmos)
"fNh" = (
@@ -52807,6 +52782,9 @@
dir = 4
},
/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden,
/obj/machinery/camera{
c_tag = "Atmospherics - Entrance"
},
/turf/open/floor/plasteel,
/area/engineering/atmos)
"fNk" = (
@@ -53119,6 +53097,12 @@
},
/turf/open/floor/plasteel,
/area/service/hydroponics)
"fYL" = (
/obj/structure/cable/yellow{
icon_state = "4-8"
},
/turf/open/floor/plating,
/area/engineering/atmos)
"fZR" = (
/obj/machinery/seed_extractor,
/obj/effect/turf_decal/stripes/line{
@@ -53158,9 +53142,6 @@
/obj/machinery/firealarm{
pixel_y = 24
},
/obj/effect/turf_decal/stripes/line{
dir = 8
},
/obj/machinery/pipedispenser,
/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden,
/obj/machinery/camera{
@@ -53170,6 +53151,9 @@
/obj/machinery/atmospherics/pipe/simple/orange/hidden{
dir = 4
},
/obj/effect/turf_decal/stripes/line{
dir = 9
},
/turf/open/floor/plasteel,
/area/engineering/atmos)
"gbt" = (
@@ -53738,7 +53722,7 @@
dir = 6
},
/obj/structure/cable/yellow{
icon_state = "1-2"
icon_state = "2-4"
},
/turf/open/floor/plasteel,
/area/engineering/atmos)
@@ -54301,14 +54285,20 @@
/turf/open/floor/plasteel,
/area/commons/dorms)
"gGc" = (
/obj/structure/cable/yellow{
icon_state = "1-2"
/obj/machinery/disposal/bin,
/obj/structure/disposalpipe/trunk{
dir = 8
},
/obj/structure/cable/yellow{
icon_state = "1-8"
/obj/effect/turf_decal/tile/yellow{
dir = 4
},
/obj/effect/landmark/event_spawn,
/turf/open/floor/plasteel,
/obj/machinery/button/door{
id = "atmos";
name = "Atmospherics Lockdown";
pixel_x = 26;
req_access_txt = "24"
},
/turf/open/floor/plasteel/dark/corner,
/area/engineering/atmos)
"gGH" = (
/obj/structure/cable/yellow{
@@ -54897,8 +54887,11 @@
/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden{
dir = 10
},
/obj/effect/turf_decal/tile/yellow{
dir = 4
},
/obj/machinery/suit_storage_unit/atmos,
/turf/open/floor/plasteel,
/turf/open/floor/plasteel/dark/corner,
/area/engineering/atmos)
"hdR" = (
/obj/structure/chair/stool{
@@ -55730,6 +55723,12 @@
/area/ai_monitored/aisat/exterior)
"hAI" = (
/obj/machinery/atmospherics/pipe/simple/supply/hidden,
/obj/structure/cable/yellow{
icon_state = "4-8"
},
/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden{
dir = 4
},
/turf/open/floor/plasteel,
/area/engineering/atmos)
"hAL" = (
@@ -56917,6 +56916,7 @@
/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden{
dir = 4
},
/obj/machinery/light/small,
/turf/open/floor/plasteel,
/area/engineering/atmos)
"iiE" = (
@@ -57457,11 +57457,11 @@
/turf/open/floor/plating,
/area/service/chapel/main)
"ixJ" = (
/obj/effect/spawner/structure/window/reinforced,
/obj/machinery/atmospherics/pipe/simple/yellow/visible,
/obj/machinery/atmospherics/pipe/simple/cyan/visible{
dir = 4
},
/obj/effect/spawner/structure/window/reinforced,
/turf/open/floor/plating,
/area/engineering/atmos)
"ixL" = (
@@ -60777,7 +60777,12 @@
/obj/machinery/atmospherics/pipe/simple/supply/hidden{
dir = 10
},
/turf/closed/wall,
/obj/machinery/door/airlock/atmos/glass{
name = "Atmospherics Monitoring";
req_access_txt = "24"
},
/obj/machinery/door/firedoor,
/turf/open/floor/plasteel,
/area/engineering/atmos)
"kuk" = (
/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden,
@@ -61962,12 +61967,13 @@
/area/command/bridge)
"kWW" = (
/obj/structure/cable/yellow{
icon_state = "1-2"
icon_state = "1-4"
},
/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden{
dir = 4
/obj/machinery/light/small{
dir = 8
},
/turf/closed/wall,
/obj/structure/closet/crate,
/turf/open/floor/plasteel,
/area/engineering/atmos)
"kXd" = (
/obj/machinery/power/terminal,
@@ -63117,14 +63123,13 @@
/turf/open/floor/plasteel,
/area/commons/locker)
"lFH" = (
/obj/machinery/light/small{
dir = 4
},
/obj/machinery/atmospherics/pipe/simple/supply/hidden{
dir = 4
},
/obj/machinery/suit_storage_unit/atmos,
/turf/open/floor/plasteel,
/obj/effect/turf_decal/tile/yellow{
dir = 4
},
/turf/open/floor/plasteel/dark/corner,
/area/engineering/atmos)
"lFQ" = (
/obj/structure/chair/office/dark{
@@ -63624,10 +63629,9 @@
/obj/effect/turf_decal/stripes/line{
dir = 10
},
/obj/machinery/atmospherics/pipe/manifold/scrubbers/hidden{
dir = 4
},
/turf/closed/wall,
/obj/machinery/pipedispenser/disposal/transit_tube,
/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden,
/turf/open/floor/plasteel,
/area/engineering/atmos)
"lUv" = (
/obj/structure/noticeboard{
@@ -63765,10 +63769,7 @@
/area/commons/fitness/recreation)
"lXt" = (
/obj/structure/cable/yellow{
icon_state = "2-8"
},
/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden{
dir = 5
icon_state = "1-8"
},
/turf/open/floor/plasteel,
/area/engineering/atmos)
@@ -65448,6 +65449,10 @@
/obj/structure/cable/yellow{
icon_state = "1-8"
},
/obj/effect/landmark/event_spawn,
/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden{
dir = 4
},
/turf/open/floor/plasteel,
/area/engineering/atmos)
"mSL" = (
@@ -67276,10 +67281,6 @@
/obj/machinery/light_switch{
pixel_x = -26
},
/obj/machinery/pipedispenser/disposal/transit_tube,
/obj/effect/turf_decal/stripes/line{
dir = 6
},
/obj/machinery/atmospherics/pipe/simple/orange/hidden{
dir = 4
},
@@ -67738,6 +67739,13 @@
name = "Atmospherics Monitoring";
req_access_txt = "24"
},
/obj/structure/cable/yellow{
icon_state = "4-8"
},
/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden{
dir = 4
},
/obj/machinery/door/firedoor,
/turf/open/floor/plasteel,
/area/engineering/atmos)
"olW" = (
@@ -68249,9 +68257,6 @@
/turf/open/floor/plasteel,
/area/service/bar)
"oBF" = (
/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden{
dir = 4
},
/obj/machinery/atmospherics/pipe/simple/supply/hidden,
/turf/open/floor/plasteel,
/area/engineering/atmos)
@@ -68954,10 +68959,16 @@
/turf/open/floor/plasteel,
/area/commons/dorms)
"oWF" = (
/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden{
dir = 4
/obj/machinery/atmospherics/pipe/simple/supply/hidden,
/obj/machinery/door/airlock/atmos/glass{
name = "Atmospherics Monitoring";
req_access_txt = "24"
},
/turf/closed/wall,
/obj/structure/cable/yellow{
icon_state = "1-2"
},
/obj/machinery/door/firedoor,
/turf/open/floor/plasteel,
/area/engineering/atmos)
"oWR" = (
/obj/effect/spawner/lootdrop/maintenance,
@@ -72841,6 +72852,12 @@
/obj/effect/turf_decal/tile/yellow{
dir = 4
},
/obj/structure/cable/yellow{
icon_state = "4-8"
},
/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden{
dir = 4
},
/turf/open/floor/plasteel/dark/corner,
/area/engineering/atmos)
"qXd" = (
@@ -73117,12 +73134,9 @@
/obj/machinery/atmospherics/pipe/simple/scrubbers/visible{
dir = 4
},
/obj/machinery/door/airlock/atmos/glass{
name = "Distribution Loop";
req_access_txt = "24"
},
/obj/machinery/atmospherics/pipe/simple/orange/hidden,
/turf/open/floor/plasteel,
/obj/effect/spawner/structure/window/reinforced,
/turf/open/floor/plating,
/area/engineering/atmos)
"rdv" = (
/obj/effect/turf_decal/stripes/line,
@@ -77268,6 +77282,13 @@
/obj/structure/lattice/catwalk,
/turf/open/space,
/area/solars/starboard/fore)
"tzt" = (
/obj/machinery/power/floodlight,
/obj/structure/cable/yellow{
icon_state = "0-8"
},
/turf/open/floor/plating,
/area/engineering/atmos)
"tAp" = (
/obj/machinery/atmospherics/pipe/simple/supply/hidden{
dir = 10
@@ -77390,6 +77411,9 @@
dir = 4
},
/obj/machinery/atmospherics/pipe/simple/supply/hidden,
/obj/structure/cable/yellow{
icon_state = "1-8"
},
/turf/open/floor/plasteel,
/area/engineering/atmos)
"tFJ" = (
@@ -77416,6 +77440,16 @@
},
/turf/open/floor/plasteel/dark,
/area/security/office)
"tGd" = (
/obj/structure/cable/yellow{
icon_state = "1-2"
},
/obj/machinery/atmospherics/pipe/simple/dark/visible,
/obj/structure/cable/yellow{
icon_state = "2-4"
},
/turf/open/floor/plasteel,
/area/engineering/atmos)
"tGD" = (
/obj/structure/closet/crate,
/obj/structure/extinguisher_cabinet{
@@ -78818,8 +78852,11 @@
/turf/open/floor/plasteel/dark,
/area/cargo/office)
"usM" = (
/obj/structure/cable/yellow{
icon_state = "2-4"
},
/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden{
dir = 10
dir = 4
},
/turf/open/floor/plasteel,
/area/engineering/atmos)
@@ -79128,11 +79165,14 @@
/turf/open/floor/wood,
/area/commons/vacant_room/office)
"uED" = (
/obj/effect/spawner/structure/window/reinforced,
/obj/machinery/atmospherics/pipe/manifold/cyan/visible{
dir = 1
},
/turf/open/floor/plating,
/obj/machinery/door/airlock/atmos/glass{
name = "Atmospherics Monitoring";
req_access_txt = "24"
},
/turf/open/floor/plasteel,
/area/engineering/atmos)
"uFM" = (
/obj/machinery/power/emitter,
@@ -80575,6 +80615,12 @@
dir = 4
},
/obj/effect/landmark/start/atmospheric_technician,
/obj/structure/cable/yellow{
icon_state = "4-8"
},
/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden{
dir = 4
},
/turf/open/floor/plasteel,
/area/engineering/atmos)
"vzs" = (
@@ -82840,7 +82886,8 @@
/obj/machinery/atmospherics/pipe/simple/supply/hidden{
dir = 5
},
/turf/closed/wall,
/obj/effect/spawner/structure/window/reinforced,
/turf/open/floor/plating,
/area/engineering/atmos)
"wKo" = (
/obj/effect/turf_decal/stripes/line,
@@ -84685,9 +84732,8 @@
/turf/open/floor/plasteel,
/area/science/mixing)
"xHm" = (
/obj/machinery/holopad,
/obj/structure/cable/yellow{
icon_state = "1-4"
/obj/structure/disposalpipe/segment{
dir = 9
},
/turf/open/floor/plasteel,
/area/engineering/atmos)
@@ -126368,7 +126414,7 @@ qxd
jJw
usM
lXt
xHm
lzQ
tyC
kLr
kdi
@@ -126625,7 +126671,7 @@ odq
ipm
hAI
oBF
erz
oBF
jxI
kLr
qDJ
@@ -126881,9 +126927,9 @@ bvh
qxd
oNX
vzb
iix
woN
tyC
mMn
cWn
xHm
kLr
iix
sKv
@@ -127139,7 +127185,7 @@ qxd
wtG
qWR
cVp
woN
gGc
dtk
lFH
hdJ
@@ -127395,8 +127441,8 @@ iLe
qxd
oBX
olw
oWF
cWn
sKv
sKv
uKL
ktV
wKg
@@ -127653,7 +127699,7 @@ sKv
oay
fNf
kWW
gGc
uKL
grX
hop
ldI
@@ -127663,7 +127709,7 @@ ooB
ibJ
ibJ
ibJ
ibJ
tGd
ibJ
ibJ
omb
@@ -127910,7 +127956,7 @@ hZe
mZD
mSB
dRb
hAI
oWF
tFH
tfk
sfM
@@ -127920,7 +127966,7 @@ eCZ
mMn
mMn
mMn
mMn
fYL
mMn
mMn
eWY
@@ -128177,7 +128223,7 @@ pcs
mMn
mMn
mMn
mMn
fYL
mMn
mMn
mMn
@@ -128424,7 +128470,7 @@ uhB
jiZ
mHn
mHn
fGc
mHn
rdg
fGc
lHN
@@ -128434,7 +128480,7 @@ mMn
mMn
mMn
mMn
mMn
fYL
mMn
mMn
mMn
@@ -128691,7 +128737,7 @@ mMn
mMn
mMn
mMn
mMn
tzt
mMn
mMn
mMn
File diff suppressed because it is too large Load Diff
BIN
View File
Binary file not shown.
BIN
View File
Binary file not shown.
+12
View File
@@ -128,6 +128,7 @@
#define TANK_MAX_RELEASE_PRESSURE (ONE_ATMOSPHERE*3)
#define TANK_MIN_RELEASE_PRESSURE 0
#define TANK_DEFAULT_RELEASE_PRESSURE 17
#define TANK_POST_FRAGMENT_REACTIONS 5
//CANATMOSPASS
#define ATMOS_PASS_YES 1
@@ -160,6 +161,9 @@
//SNOSTATION
#define ICEMOON_DEFAULT_ATMOS "ICEMOON_ATMOS"
//FESTIVESTATION
#define FESTIVE_ATMOS "o2=22;n2=82;TEMP=266" //this goes here right putnam??
//ATMOSIA GAS MONITOR TAGS
#define ATMOS_GAS_MONITOR_INPUT_O2 "o2_in"
#define ATMOS_GAS_MONITOR_OUTPUT_O2 "o2_out"
@@ -257,6 +261,7 @@
#define GAS_HYPERNOB "nob"
#define GAS_NITROUS "n2o"
#define GAS_NITRYL "no2"
#define GAS_HYDROGEN "hydrogen"
#define GAS_TRITIUM "tritium"
#define GAS_BZ "bz"
#define GAS_STIMULUM "stim"
@@ -264,9 +269,16 @@
#define GAS_MIASMA "miasma"
#define GAS_METHANE "methane"
#define GAS_METHYL_BROMIDE "methyl_bromide"
#define GAS_BROMINE "bromine"
#define GAS_AMMONIA "ammonia"
#define GAS_FLUORINE "fluorine"
#define GAS_ETHANOL "ethanol"
#define GAS_GROUP_CHEMICALS "Chemicals"
#define GAS_FLAG_DANGEROUS (1<<0)
#define GAS_FLAG_BREATH_PROC (1<<1)
#define GAS_FLAG_CHEMICAL (1<<2)
//SUPERMATTER DEFINES
#define HEAT_PENALTY "heat penalties"
+3
View File
@@ -31,6 +31,9 @@
#define COMSIG_WEATHER_WINDDOWN(event_type) "!weather_winddown [event_type]"
#define COMSIG_WEATHER_END(event_type) "!weather_end [event_type]"
/// called by auxgm add_gas: (gas_id)
#define COMSIG_GLOB_NEW_GAS "!new_gas"
// signals from globally accessible objects
/// from SSsun when the sun changes position : (primary_sun, suns)
#define COMSIG_SUN_MOVED "sun_moved"
+3 -2
View File
@@ -40,15 +40,16 @@
#define LOG_ASAY (1 << 15)
#define LOG_VIRUS (1 << 16)
#define LOG_SHUTTLE (1 << 18)
#define LOG_VICTIM (1 << 19)
//Individual logging panel pages
#define INDIVIDUAL_ATTACK_LOG (LOG_ATTACK)
#define INDIVIDUAL_ATTACK_LOG (LOG_ATTACK | LOG_VICTIM)
#define INDIVIDUAL_SAY_LOG (LOG_SAY | LOG_WHISPER | LOG_DSAY)
#define INDIVIDUAL_EMOTE_LOG (LOG_EMOTE | LOG_SUBTLER)
#define INDIVIDUAL_COMMS_LOG (LOG_PDA | LOG_CHAT | LOG_COMMENT | LOG_TELECOMMS)
#define INDIVIDUAL_OOC_LOG (LOG_OOC | LOG_ADMIN)
#define INDIVIDUAL_OWNERSHIP_LOG (LOG_OWNERSHIP)
#define INDIVIDUAL_SHOW_ALL_LOG (LOG_ATTACK | LOG_SAY | LOG_WHISPER | LOG_EMOTE | LOG_DSAY | LOG_PDA | LOG_CHAT | LOG_COMMENT | LOG_TELECOMMS | LOG_OOC | LOG_ADMIN | LOG_OWNERSHIP | LOG_GAME)
#define INDIVIDUAL_SHOW_ALL_LOG (LOG_ATTACK | LOG_SAY | LOG_WHISPER | LOG_EMOTE | LOG_DSAY | LOG_PDA | LOG_CHAT | LOG_COMMENT | LOG_TELECOMMS | LOG_OOC | LOG_ADMIN | LOG_OWNERSHIP | LOG_GAME | LOG_VICTIM)
#define LOGSRC_CLIENT "Client"
#define LOGSRC_MOB "Mob"
+1 -1
View File
@@ -295,7 +295,7 @@
#define APPRENTICE_AGE_MIN 29 // youngest an apprentice can be
#define SHOES_SLOWDOWN 0 // How much shoes slow you down by default. Negative values speed you up
#define SHOES_SPEED_SLIGHT SHOES_SLOWDOWN - 1 // slightest speed boost to movement
#define POCKET_STRIP_DELAY 40 // time taken (in deciseconds) to search somebody's pockets
#define POCKET_STRIP_DELAY (4 SECONDS) //time taken to search somebody's pockets
#define DOOR_CRUSH_DAMAGE 15 // the amount of damage that airlocks deal when they crush you
#define HUNGER_FACTOR 0.1 // factor at which mob nutrition decreases
+1 -1
View File
@@ -13,7 +13,7 @@
#define NITRYL_FORMATION_ENERGY 100000
#define TRITIUM_BURN_OXY_FACTOR 100
#define TRITIUM_BURN_TRIT_FACTOR 10
#define TRITIUM_BURN_RADIOACTIVITY_FACTOR 50000 //The neutrons gotta go somewhere. Completely arbitrary number.
#define TRITIUM_BURN_RADIOACTIVITY_FACTOR 5000 //The neutrons gotta go somewhere. Completely arbitrary number.
#define TRITIUM_MINIMUM_RADIATION_ENERGY 0.1 //minimum 0.01 moles trit or 10 moles oxygen to start producing rads
#define SUPER_SATURATION_THRESHOLD 96
#define STIMULUM_HEAT_SCALE 100000
+3 -1
View File
@@ -73,4 +73,6 @@
TECHWEB_POINT_TYPE_GENERIC = "General Research"\
)
#define TECHWEB_BOMB_POINTCAP 50000 //Adjust as needed; Stops toxins from nullifying RND progression mechanics. Current Value Cap Radius: 100
#define BOMB_TARGET_POINTS 50000 //Adjust as needed. Actual hard cap is double this, but will never be reached due to hyperbolic curve.
#define BOMB_TARGET_SIZE 200 // The shockwave radius required for a bomb to get TECHWEB_BOMB_MIDPOINT points.
#define BOMB_SUB_TARGET_EXPONENT 2 // The power of the points curve below the target size. Higher = less points for worse bombs, below target.
+31
View File
@@ -0,0 +1,31 @@
// All of these must be matched in StripMenu.js.
#define STRIPPABLE_ITEM_HEAD "head"
#define STRIPPABLE_ITEM_BACK "back"
#define STRIPPABLE_ITEM_MASK "mask"
#define STRIPPABLE_ITEM_NECK "neck"
#define STRIPPABLE_ITEM_EYES "eyes"
#define STRIPPABLE_ITEM_EARS "ears"
#define STRIPPABLE_ITEM_JUMPSUIT "jumpsuit"
#define STRIPPABLE_ITEM_SUIT "suit"
#define STRIPPABLE_ITEM_GLOVES "gloves"
#define STRIPPABLE_ITEM_FEET "shoes"
#define STRIPPABLE_ITEM_SUIT_STORAGE "suit_storage"
#define STRIPPABLE_ITEM_ID "id"
#define STRIPPABLE_ITEM_BELT "belt"
#define STRIPPABLE_ITEM_LPOCKET "left_pocket"
#define STRIPPABLE_ITEM_RPOCKET "right_pocket"
#define STRIPPABLE_ITEM_LHAND "left_hand"
#define STRIPPABLE_ITEM_RHAND "right_hand"
#define STRIPPABLE_ITEM_HANDCUFFS "handcuffs"
#define STRIPPABLE_ITEM_LEGCUFFS "legcuffs"
#define STRIPPABLE_ITEM_CORGI_COLLAR "corgi_collar"
#define STRIPPABLE_ITEM_PARROT_HEADSET "parrot_headset"
/// This slot is not obscured.
#define STRIPPABLE_OBSCURING_NONE 0
/// This slot is completely obscured, and cannot be accessed.
#define STRIPPABLE_OBSCURING_COMPLETELY 1
/// This slot can't be seen, but can be accessed.
#define STRIPPABLE_OBSCURING_HIDDEN 2
+6
View File
@@ -35,6 +35,12 @@
#define SANITIZE_LIST(L) ( islist(L) ? L : list() )
#define reverseList(L) reverseRange(L.Copy())
/// Performs an insertion on the given lazy list with the given key and value. If the value already exists, a new one will not be made.
#define LAZYORASSOCLIST(lazy_list, key, value) \
LAZYINITLIST(lazy_list); \
LAZYINITLIST(lazy_list[key]); \
lazy_list[key] |= value;
/// Performs an insertion on the given lazy list with the given key and value. If the value already exists, a new one will not be made.
#define LAZYORASSOCLIST(lazy_list, key, value) \
LAZYINITLIST(lazy_list); \
+12
View File
@@ -458,6 +458,18 @@ GLOBAL_LIST_EMPTY(species_datums)
if(!HAS_TRAIT(L, TRAIT_PASSTABLE))
L.pass_flags &= ~PASSTABLE
/proc/dance_rotate(atom/movable/AM, datum/callback/callperrotate, set_original_dir=FALSE)
set waitfor = FALSE
var/originaldir = AM.dir
for(var/i in list(NORTH,SOUTH,EAST,WEST,EAST,SOUTH,NORTH,SOUTH,EAST,WEST,EAST,SOUTH))
if(!AM)
return
AM.setDir(i)
callperrotate?.Invoke()
sleep(1)
if(set_original_dir)
AM.setDir(originaldir)
/// Gets the client of the mob, allowing for mocking of the client.
/// You only need to use this if you know you're going to be mocking clients somewhere else.
#define GET_CLIENT(mob) (##mob.client || ##mob.mock_client)
@@ -347,3 +347,5 @@
default = FALSE
/datum/config_entry/flag/dynamic_config_enabled
/datum/config_entry/flag/station_name_needs_approval
+6 -1
View File
@@ -116,6 +116,11 @@ SUBSYSTEM_DEF(air)
/datum/controller/subsystem/air/proc/auxtools_update_reactions()
/datum/controller/subsystem/air/proc/add_reaction(datum/gas_reaction/r)
gas_reactions += r
sortTim(gas_reactions, /proc/cmp_gas_reaction)
auxtools_update_reactions()
/proc/reset_all_air()
SSair.can_fire = 0
message_admins("Air reset begun.")
@@ -405,7 +410,7 @@ SUBSYSTEM_DEF(air)
eq_cooldown += (1-delay_threshold) * (cost_equalize / total_thread_time) * 2
if(eq_cooldown > 0.5)
equalize_enabled = FALSE
excited_group_pressure_goal = max(0,excited_group_pressure_goal_target * (1 - delay_threshold))
excited_group_pressure_goal = max(0,excited_group_pressure_goal_target * delay_threshold)
/datum/controller/subsystem/air/proc/process_turfs(resumed = 0)
+1 -1
View File
@@ -168,7 +168,7 @@
L.visible_message("<span class='warning'>[held_mob] escapes from [L]!</span>", "<span class='warning'>[held_mob] escapes your grip!</span>")
release()
/obj/item/clothing/head/mob_holder/mob_can_equip(mob/living/M, mob/living/equipper, slot, disable_warning = FALSE, bypass_equip_delay_self = FALSE)
/obj/item/clothing/head/mob_holder/mob_can_equip(M, equipper, slot, disable_warning, bypass_equip_delay_self)
if(M == held_mob || !ishuman(M)) //monkeys holding monkeys holding monkeys...
return FALSE
return ..()
+517
View File
@@ -0,0 +1,517 @@
/// An element for atoms that, when dragged and dropped onto a mob, opens a strip panel.
/datum/element/strippable
element_flags = ELEMENT_BESPOKE | ELEMENT_DETACH
id_arg_index = 2
/// An assoc list of keys to /datum/strippable_item
var/list/items
/// A proc path that returns TRUE/FALSE if we should show the strip panel for this entity.
/// If it does not exist, the strip menu will always show.
/// Will be called with (mob/user).
var/should_strip_proc_path
/// An existing strip menus
var/list/strip_menus
/datum/element/strippable/Attach(datum/target, list/items, should_strip_proc_path)
. = ..()
if (!isatom(target))
return ELEMENT_INCOMPATIBLE
RegisterSignal(target, COMSIG_MOUSEDROP_ONTO, .proc/mouse_drop_onto)
src.items = items
src.should_strip_proc_path = should_strip_proc_path
/datum/element/strippable/Detach(datum/source)
. = ..()
UnregisterSignal(source, COMSIG_MOUSEDROP_ONTO)
if (!isnull(strip_menus))
qdel(strip_menus[source])
strip_menus -= source
/datum/element/strippable/proc/mouse_drop_onto(datum/source, atom/over, mob/user)
SIGNAL_HANDLER
if (user == source)
return
if (over != user)
return
// Cyborgs buckle people by dragging them onto them, unless in combat mode.
if (iscyborg(user))
var/mob/living/silicon/robot/cyborg_user = user
if (cyborg_user.a_intent == INTENT_HARM)
return
if (!isnull(should_strip_proc_path) && !call(source, should_strip_proc_path)(user))
return
var/datum/strip_menu/strip_menu
if (isnull(strip_menu))
strip_menu = new(source, src)
LAZYSET(strip_menus, source, strip_menu)
INVOKE_ASYNC(strip_menu, /datum/.proc/ui_interact, user)
/// A representation of an item that can be stripped down
/datum/strippable_item
/// The STRIPPABLE_ITEM_* key
var/key
/// Should we warn about dangerous clothing?
var/warn_dangerous_clothing = TRUE
/// Gets the item from the given source.
/datum/strippable_item/proc/get_item(atom/source)
/// Tries to equip the item onto the given source.
/// Returns TRUE/FALSE depending on if it is allowed.
/// This should be used for checking if an item CAN be equipped.
/// It should not perform the equipping itself.
/datum/strippable_item/proc/try_equip(atom/source, obj/item/equipping, mob/user)
if (HAS_TRAIT(equipping, TRAIT_NODROP))
to_chat(user, span_warning("You can't put [equipping] on [source], it's stuck to your hand!"))
return FALSE
return TRUE
/// Start the equipping process. This is the proc you should yield in.
/// Returns TRUE/FALSE depending on if it is allowed.
/datum/strippable_item/proc/start_equip(atom/source, obj/item/equipping, mob/user)
if (warn_dangerous_clothing && isclothing(source))
source.visible_message(
span_notice("[user] tries to put [equipping] on [source]."),
span_notice("[user] tries to put [equipping] on you."),
ignored_mobs = user,
)
if(ishuman(source))
var/mob/living/carbon/human/victim_human = source
if(victim_human.key && !victim_human.client) // AKA braindead
if(victim_human.stat <= SOFT_CRIT && LAZYLEN(victim_human.afk_thefts) <= AFK_THEFT_MAX_MESSAGES)
var/list/new_entry = list(list(user.name, "tried equipping you with [equipping]", world.time))
LAZYADD(victim_human.afk_thefts, new_entry)
to_chat(user, span_notice("You try to put [equipping] on [source]..."))
var/log = "[key_name(source)] is having [equipping] put on them by [key_name(user)]"
user.log_message(log, LOG_ATTACK, color="red")
source.log_message(log, LOG_VICTIM, color="red", log_globally=FALSE)
return TRUE
/// The proc that places the item on the source. This should not yield.
/datum/strippable_item/proc/finish_equip(atom/source, obj/item/equipping, mob/user)
SHOULD_NOT_SLEEP(TRUE)
return TRUE
/// Tries to unequip the item from the given source.
/// Returns TRUE/FALSE depending on if it is allowed.
/// This should be used for checking if it CAN be unequipped.
/// It should not perform the unequipping itself.
/datum/strippable_item/proc/try_unequip(atom/source, mob/user)
SHOULD_NOT_SLEEP(TRUE)
var/obj/item/item = get_item(source)
if (isnull(item))
return FALSE
if (ismob(source))
var/mob/mob_source = source
if (!item.canStrip(user, mob_source))
return FALSE
return TRUE
/// Start the unequipping process. This is the proc you should yield in.
/// Returns TRUE/FALSE depending on if it is allowed.
/datum/strippable_item/proc/start_unequip(atom/source, mob/user)
var/obj/item/item = get_item(source)
if (isnull(item))
return FALSE
source.visible_message(
span_warning("[user] tries to remove [source]'s [item.name]."),
span_userdanger("[user] tries to remove your [item.name]."),
ignored_mobs = user,
)
to_chat(user, span_danger("You try to remove [source]'s [item]..."))
user.log_message("[key_name(source)] is being stripped of [item] by [key_name(user)]", LOG_ATTACK, color="red")
source.log_message("[key_name(source)] is being stripped of [item] by [key_name(user)]", LOG_VICTIM, color="red", log_globally=FALSE)
item.add_fingerprint(source)
if(ishuman(source))
var/mob/living/carbon/human/victim_human = source
if(victim_human.key && !victim_human.client) // AKA braindead
if(victim_human.stat <= SOFT_CRIT && LAZYLEN(victim_human.afk_thefts) <= AFK_THEFT_MAX_MESSAGES)
var/list/new_entry = list(list(user.name, "tried unequipping your [item.name]", world.time))
LAZYADD(victim_human.afk_thefts, new_entry)
return TRUE
/// The proc that unequips the item from the source. This should not yield.
/datum/strippable_item/proc/finish_unequip(atom/source, mob/user)
/// Returns a STRIPPABLE_OBSCURING_* define to report on whether or not this is obscured.
/datum/strippable_item/proc/get_obscuring(atom/source)
SHOULD_NOT_SLEEP(TRUE)
return STRIPPABLE_OBSCURING_NONE
/// Returns the ID of this item's strippable action.
/// Return `null` if there is no alternate action.
/// Any return value of this must be in StripMenu.
/datum/strippable_item/proc/get_alternate_action(atom/source, mob/user)
if(get_obscuring(source) == STRIPPABLE_OBSCURING_COMPLETELY)
return FALSE
return null
/// Performs an alternative action on this strippable_item.
/// `has_alternate_action` needs to be TRUE.
/datum/strippable_item/proc/alternate_action(atom/source, mob/user)
if(get_obscuring(source) == STRIPPABLE_OBSCURING_COMPLETELY)
return null
return TRUE
/// Returns whether or not this item should show.
/datum/strippable_item/proc/should_show(atom/source, mob/user)
return TRUE
/// A preset for equipping items onto mob slots
/datum/strippable_item/mob_item_slot
/// The ITEM_SLOT_* to equip to.
var/item_slot
/datum/strippable_item/mob_item_slot/get_item(atom/source)
if (!ismob(source))
return null
var/mob/mob_source = source
return mob_source.get_item_by_slot(item_slot)
/datum/strippable_item/mob_item_slot/try_equip(atom/source, obj/item/equipping, mob/user)
. = ..()
if (!.)
return
if (!ismob(source))
return FALSE
if (!equipping.mob_can_equip(
source,
user,
item_slot,
disable_warning = TRUE,
bypass_equip_delay_self = TRUE,
))
to_chat(user, span_warning("\The [equipping] doesn't fit in that place!"))
return FALSE
return TRUE
/datum/strippable_item/mob_item_slot/start_equip(atom/source, obj/item/equipping, mob/user)
. = ..()
if (!.)
return
if (!ismob(source))
return FALSE
if (!do_mob(user, source, get_equip_delay(equipping)))
return FALSE
if(get_obscuring(source) == STRIPPABLE_OBSCURING_COMPLETELY)
return FALSE
if (!equipping.mob_can_equip(
source,
user,
item_slot,
disable_warning = TRUE,
bypass_equip_delay_self = TRUE,
))
return FALSE
if (!user.temporarilyRemoveItemFromInventory(equipping))
return FALSE
return TRUE
/datum/strippable_item/mob_item_slot/finish_equip(atom/source, obj/item/equipping, mob/user)
if(!..())
return FALSE
if (!ismob(source))
return FALSE
var/mob/mob_source = source
mob_source.equip_to_slot(equipping, item_slot)
/datum/strippable_item/mob_item_slot/get_obscuring(atom/source)
if (iscarbon(source))
var/mob/living/carbon/carbon_source = source
return (item_slot in carbon_source.check_obscured_slots()) \
? STRIPPABLE_OBSCURING_COMPLETELY \
: STRIPPABLE_OBSCURING_NONE
return FALSE
/datum/strippable_item/mob_item_slot/start_unequip(atom/source, mob/user)
. = ..()
if (!.)
return
return start_unequip_mob(get_item(source), source, user)
/datum/strippable_item/mob_item_slot/finish_unequip(atom/source, mob/user)
var/obj/item/item = get_item(source)
if (isnull(item))
return FALSE
if (!ismob(source))
return FALSE
return finish_unequip_mob(item, source, user)
/// Returns the delay of equipping this item to a mob
/datum/strippable_item/mob_item_slot/proc/get_equip_delay(obj/item/equipping)
return equipping.equip_delay_other
/// A utility function for `/datum/strippable_item`s to start unequipping an item from a mob.
/proc/start_unequip_mob(obj/item/item, mob/source, mob/user, strip_delay)
if (!do_mob(user, source, strip_delay || item.strip_delay, ignorehelditem = TRUE))
return FALSE
return TRUE
/// A utility function for `/datum/strippable_item`s to finish unequipping an item from a mob.
/proc/finish_unequip_mob(obj/item/item, mob/source, mob/user)
if (!item.doStrip(user, source))
return FALSE
user.log_message("[key_name(source)] has been stripped of [item] by [key_name(user)]", LOG_ATTACK, color="red")
source.log_message("[key_name(source)] has been stripped of [item] by [key_name(user)]", LOG_VICTIM, color="red", log_globally=FALSE)
// Updates speed in case stripped speed affecting item
source.update_equipment_speed_mods()
/// A representation of the stripping UI
/datum/strip_menu
/// The owner who has the element /datum/element/strippable
var/atom/movable/owner
/// The strippable element itself
var/datum/element/strippable/strippable
/// A lazy list of user mobs to a list of strip menu keys that they're interacting with
var/list/interactions
/datum/strip_menu/New(atom/movable/owner, datum/element/strippable/strippable)
. = ..()
src.owner = owner
src.strippable = strippable
/datum/strip_menu/Destroy()
owner = null
strippable = null
return ..()
/datum/strip_menu/ui_interact(mob/user, datum/tgui/ui)
ui = SStgui.try_update_ui(user, src, ui)
if (!ui)
ui = new(user, src, "StripMenu")
ui.open()
/datum/strip_menu/ui_assets(mob/user)
return list(
get_asset_datum(/datum/asset/simple/inventory),
)
/datum/strip_menu/ui_data(mob/user)
var/list/data = list()
var/list/items = list()
for (var/strippable_key in strippable.items)
var/datum/strippable_item/item_data = strippable.items[strippable_key]
if (!item_data.should_show(owner, user))
continue
var/list/result
if(strippable_key in LAZYACCESS(interactions, user))
LAZYSET(result, "interacting", TRUE)
var/obscuring = item_data.get_obscuring(owner)
if (obscuring != STRIPPABLE_OBSCURING_NONE)
LAZYSET(result, "obscured", obscuring)
items[strippable_key] = result
continue
var/obj/item/item = item_data.get_item(owner)
if (isnull(item))
items[strippable_key] = result
continue
LAZYINITLIST(result)
result["icon"] = icon2base64(icon(item.icon, item.icon_state, SOUTH, 1))
result["name"] = item.name
result["alternate"] = item_data.get_alternate_action(owner, user)
items[strippable_key] = result
data["items"] = items
// While most `\the`s are implicit, this one is not.
// In this case, `\The` would otherwise be used.
// This doesn't match with what it's used for, which is to say "Stripping the alien drone",
// as opposed to "Stripping The alien drone".
// Human names will still show without "the", as they are proper nouns.
data["name"] = "\the [owner]"
/// Customize the strip menu
data["long_strip_menu"] = user.client.prefs.long_strip_menu
return data
/datum/strip_menu/ui_act(action, list/params, datum/tgui/ui, datum/ui_state/state)
. = ..()
if (.)
return
. = TRUE
var/mob/user = usr
switch (action)
if ("use")
var/key = params["key"]
var/datum/strippable_item/strippable_item = strippable.items[key]
if (isnull(strippable_item))
return
if (!strippable_item.should_show(owner, user))
return
if (strippable_item.get_obscuring(owner) == STRIPPABLE_OBSCURING_COMPLETELY)
return
var/item = strippable_item.get_item(owner)
if (isnull(item))
var/obj/item/held_item = user.get_active_held_item()
if (isnull(held_item))
return
if (strippable_item.try_equip(owner, held_item, user))
LAZYORASSOCLIST(interactions, user, key)
// Yielding call
var/should_finish = strippable_item.start_equip(owner, held_item, user)
LAZYREMOVEASSOC(interactions, user, key)
if (!should_finish)
return
if (QDELETED(src) || QDELETED(owner))
return
// They equipped an item in the meantime
if (!isnull(strippable_item.get_item(owner)))
return
if (!user.Adjacent(owner))
return
strippable_item.finish_equip(owner, held_item, user)
else if (strippable_item.try_unequip(owner, user))
LAZYORASSOCLIST(interactions, user, key)
var/should_unequip = strippable_item.start_unequip(owner, user)
LAZYREMOVEASSOC(interactions, user, key)
// Yielding call
if (!should_unequip)
return
if (QDELETED(src) || QDELETED(owner))
return
// They changed the item in the meantime
if (strippable_item.get_item(owner) != item)
return
if (!user.Adjacent(owner))
return
strippable_item.finish_unequip(owner, user)
if ("alt")
var/key = params["key"]
var/datum/strippable_item/strippable_item = strippable.items[key]
if (isnull(strippable_item))
return
if (!strippable_item.should_show(owner, user))
return
if (strippable_item.get_obscuring(owner) == STRIPPABLE_OBSCURING_COMPLETELY)
return
var/item = strippable_item.get_item(owner)
if (isnull(item))
return
if (isnull(strippable_item.get_alternate_action(owner, user)))
return
LAZYORASSOCLIST(interactions, user, key)
// Potentially yielding
strippable_item.alternate_action(owner, user)
LAZYREMOVEASSOC(interactions, user, key)
/datum/strip_menu/ui_host(mob/user)
return owner
/datum/strip_menu/ui_state(mob/user)
return GLOB.always_state
/datum/strip_menu/ui_status(mob/user, datum/ui_state/state)
. = ..()
if(isliving(user))
var/mob/living/living_user = user
if (
living_user.stat == CONSCIOUS \
&& living_user.Adjacent(owner)
)
return UI_INTERACTIVE
if(IsAdminGhost(user))
return UI_INTERACTIVE
if(user.Adjacent(owner))
return UI_UPDATE
else
return UI_DISABLED
/// Creates an assoc list of keys to /datum/strippable_item
/proc/create_strippable_list(types)
var/list/strippable_items = list()
for (var/strippable_type in types)
var/datum/strippable_item/strippable_item = new strippable_type
strippable_items[strippable_item.key] = strippable_item
return strippable_items
+10 -2
View File
@@ -119,12 +119,20 @@
victim.bleed(blood_bled, TRUE)
if(14 to 19)
victim.visible_message("<span class='smalldanger'>[victim] spits out a string of blood from the blow to [victim.p_their()] chest!</span>", "<span class='danger'>You spit out a string of blood from the blow to your chest!</span>", vision_distance=COMBAT_MESSAGE_RANGE)
new /obj/effect/temp_visual/dir_setting/bloodsplatter(victim.loc, victim.dir)
if(ishuman(victim))
var/mob/living/carbon/human/H = victim
new /obj/effect/temp_visual/dir_setting/bloodsplatter(victim.loc, victim.dir, H.dna.species.exotic_blood_color)
else
new /obj/effect/temp_visual/dir_setting/bloodsplatter(victim.loc, victim.dir)
victim.bleed(blood_bled)
if(20 to INFINITY)
victim.visible_message("<span class='danger'>[victim] chokes up a spray of blood from the blow to [victim.p_their()] chest!</span>", "<span class='danger'><b>You choke up on a spray of blood from the blow to your chest!</b></span>", vision_distance=COMBAT_MESSAGE_RANGE)
victim.bleed(blood_bled)
new /obj/effect/temp_visual/dir_setting/bloodsplatter(victim.loc, victim.dir)
if(ishuman(victim))
var/mob/living/carbon/human/H = victim
new /obj/effect/temp_visual/dir_setting/bloodsplatter(victim.loc, victim.dir, H.dna.species.exotic_blood_color)
else
new /obj/effect/temp_visual/dir_setting/bloodsplatter(victim.loc, victim.dir)
victim.add_splatter_floor(get_step(victim.loc, victim.dir))
+10 -2
View File
@@ -39,12 +39,20 @@
victim.bleed(blood_bled, TRUE)
if(14 to 19)
victim.visible_message("<span class='smalldanger'>A small stream of blood spurts from the hole in [victim]'s [limb.name]!</span>", "<span class='danger'>You spit out a string of blood from the blow to your [limb.name]!</span>", vision_distance=COMBAT_MESSAGE_RANGE)
new /obj/effect/temp_visual/dir_setting/bloodsplatter(victim.loc, victim.dir)
if(ishuman(victim))
var/mob/living/carbon/human/H = victim
new /obj/effect/temp_visual/dir_setting/bloodsplatter(victim.loc, victim.dir, H.dna.species.exotic_blood_color)
else
new /obj/effect/temp_visual/dir_setting/bloodsplatter(victim.loc, victim.dir)
victim.bleed(blood_bled)
if(20 to INFINITY)
victim.visible_message("<span class='danger'>A spray of blood streams from the gash in [victim]'s [limb.name]!</span>", "<span class='danger'><b>You choke up on a spray of blood from the blow to your [limb.name]!</b></span>", vision_distance=COMBAT_MESSAGE_RANGE)
victim.bleed(blood_bled)
new /obj/effect/temp_visual/dir_setting/bloodsplatter(victim.loc, victim.dir)
if(ishuman(victim))
var/mob/living/carbon/human/H = victim
new /obj/effect/temp_visual/dir_setting/bloodsplatter(victim.loc, victim.dir, H.dna.species.exotic_blood_color)
else
new /obj/effect/temp_visual/dir_setting/bloodsplatter(victim.loc, victim.dir)
victim.add_splatter_floor(get_step(victim.loc, victim.dir))
/datum/wound/pierce/handle_process()
+8 -11
View File
@@ -194,22 +194,19 @@ GLOBAL_LIST_EMPTY(doppler_arrays)
/*****The Point Calculator*****/
if(orig_light < 10)
if(orig_light < 5)
say("Explosion not large enough for research calculations.")
return
else
point_gain = (100000 * orig_light) / (orig_light + 5000)
else if(orig_light < BOMB_TARGET_SIZE) // we want to give fewer points if below the target; this curve does that
point_gain = (BOMB_TARGET_POINTS * orig_light ** BOMB_SUB_TARGET_EXPONENT) / (BOMB_TARGET_SIZE**BOMB_SUB_TARGET_EXPONENT)
else // once we're at the target, switch to a hyperbolic function so we can't go too far above it, but bigger bombs always get more points
point_gain = (BOMB_TARGET_POINTS * 2 * orig_light) / (orig_light + BOMB_TARGET_SIZE)
/*****The Point Capper*****/
if(point_gain > linked_techweb.largest_bomb_value)
if(point_gain <= TECHWEB_BOMB_POINTCAP || linked_techweb.largest_bomb_value < TECHWEB_BOMB_POINTCAP)
var/old_tech_largest_bomb_value = linked_techweb.largest_bomb_value //held so we can pull old before we do math
linked_techweb.largest_bomb_value = point_gain
point_gain -= old_tech_largest_bomb_value
point_gain = min(point_gain,TECHWEB_BOMB_POINTCAP)
else
linked_techweb.largest_bomb_value = TECHWEB_BOMB_POINTCAP
point_gain = 1000
var/old_tech_largest_bomb_value = linked_techweb.largest_bomb_value //held so we can pull old before we do math
linked_techweb.largest_bomb_value = point_gain
point_gain -= old_tech_largest_bomb_value
var/datum/bank_account/D = SSeconomy.get_dep_account(ACCOUNT_SCI)
if(D)
D.adjust_money(point_gain)
+2 -1
View File
@@ -45,7 +45,8 @@ Buildable meters
if(make_from)
make_from_existing(make_from)
else
pipe_type = _pipe_type
if(!initial(src.pipe_type))
pipe_type = _pipe_type
setDir(_dir)
update()
@@ -130,7 +130,11 @@
if(isalien(target))
new /obj/effect/temp_visual/dir_setting/bloodsplatter/xenosplatter(target.drop_location(), splatter_dir)
else
new /obj/effect/temp_visual/dir_setting/bloodsplatter(target.drop_location(), splatter_dir)
if(ishuman(target))
var/mob/living/carbon/human/H = target
new /obj/effect/temp_visual/dir_setting/bloodsplatter(target.drop_location(), splatter_dir, H.dna.species.exotic_blood_color)
else
new /obj/effect/temp_visual/dir_setting/bloodsplatter(target.drop_location(), splatter_dir)
//organs go everywhere
if(target_part && prob(10 * drill_level))
@@ -4,6 +4,7 @@
duration = 5
randomdir = FALSE
layer = BELOW_MOB_LAYER
color = BLOOD_COLOR_HUMAN // set it to red by default because the actual icons are white
var/splatter_type = "splatter"
/obj/effect/temp_visual/dir_setting/bloodsplatter/Initialize(mapload, set_dir, new_color)
+13
View File
@@ -1091,6 +1091,19 @@ GLOBAL_VAR_INIT(embedpocalypse, FALSE) // if true, all items will be able to emb
. = ..()
if(var_name == NAMEOF(src, slowdown))
set_slowdown(var_value) //don't care if it's a duplicate edit as slowdown'll be set, do it anyways to force normal behavior.
/obj/item/proc/canStrip(mob/stripper, mob/owner)
SHOULD_BE_PURE(TRUE)
return !HAS_TRAIT(src, TRAIT_NODROP) && !(item_flags & ABSTRACT)
/obj/item/proc/doStrip(mob/stripper, mob/owner)
if(owner.dropItemToGround(src))
if(stripper.can_hold_items())
stripper.put_in_hands(src)
return TRUE
else
return FALSE
/**
* Does the current embedding var meet the criteria for being harmless? Namely, does it explicitly define the pain multiplier and jostle pain mult to be 0? If so, return true.
*
+28 -2
View File
@@ -14,6 +14,7 @@
var/response_timer_id = null
var/approval_time = 600
var/allow_unicode = FALSE
var/admin_approved = FALSE
var/static/regex/standard_station_regex
@@ -62,8 +63,32 @@
to_chat(user, "Your name has been sent to your employers for approval.")
// Autoapproves after a certain time
response_timer_id = addtimer(CALLBACK(src, .proc/rename_station, new_name, user.name, user.real_name, key_name(user)), approval_time, TIMER_STOPPABLE)
to_chat(GLOB.admins, "<span class='adminnotice'><b><font color=orange>CUSTOM STATION RENAME:</font></b>[ADMIN_LOOKUPFLW(user)] proposes to rename the [name_type] to [html_encode(new_name)] (will autoapprove in [DisplayTimeText(approval_time)]). [ADMIN_SMITE(user)] (<A HREF='?_src_=holder;[HrefToken(TRUE)];reject_custom_name=[REF(src)]'>REJECT</A>) [ADMIN_CENTCOM_REPLY(user)]</span>")
var/requires_approval = CONFIG_GET(flag/station_name_needs_approval)
response_timer_id = addtimer(CALLBACK(src, .proc/check_state, new_name, user.name, user.real_name, key_name(user)), approval_time, TIMER_STOPPABLE)
to_chat(GLOB.admins, "<span class='adminnotice'><b><font color=orange>CUSTOM STATION RENAME:</font></b>[ADMIN_LOOKUPFLW(user)] proposes to rename the [name_type] to [html_encode(new_name)] ([requires_approval ? "REQUIRES ADMIN APPROVAL and will autodeny" : "will autoapprove"] in [DisplayTimeText(approval_time)]). [ADMIN_SMITE(user)] (<A HREF='?_src_=holder;[HrefToken(TRUE)];reject_custom_name=[REF(src)]'>REJECT</A>)[requires_approval ? " (<A HREF='?_src_=holder;[HrefToken(TRUE)];approve_custom_name=[REF(src)]'>APPROVE</A>)" : ""] [ADMIN_CENTCOM_REPLY(user)]</span>")
/obj/item/station_charter/proc/check_state(designation, uname, ureal_name, ukey)
var/requires_approval = CONFIG_GET(flag/station_name_needs_approval)
if(requires_approval && !admin_approved)
var/turf/T = get_turf(src)
T.visible_message("<span class='warning'>A note appears on [src], stating this sector requires central command approval for its station names, which was not performed in time for this request. Looks like the change has been auto-rejected.</span>")
var/m = "Station rename has been autorejected due to config requiring admin approval."
message_admins(m)
log_admin(m)
else
rename_station(designation, uname, ureal_name, ukey)
response_timer_id = null
admin_approved = FALSE
/obj/item/station_charter/proc/allow_pass(user)
if(!user)
return
if(!response_timer_id)
return
admin_approved = TRUE
var/m = "[key_name(user)] has approved the proposed station name. It can still be denied prior to the timer expiring."
message_admins(m)
log_admin(m)
/obj/item/station_charter/proc/reject_proposed(user)
if(!user)
@@ -80,6 +105,7 @@
deltimer(response_timer_id)
response_timer_id = null
admin_approved = FALSE
/obj/item/station_charter/proc/rename_station(designation, uname, ureal_name, ukey)
set_station_name(designation)
+1 -1
View File
@@ -193,7 +193,7 @@
/obj/item/melee/transforming/energy/sword/saber
possible_colors = list("red" = LIGHT_COLOR_RED, "blue" = LIGHT_COLOR_LIGHT_CYAN, "green" = LIGHT_COLOR_GREEN, "purple" = LIGHT_COLOR_LAVENDER)
unique_reskin = list("Sword" = "sword0", "saber" = "esaber0")
unique_reskin = list("Sword" = "sword0", "Saber" = "esaber0")
var/hacked = FALSE
var/saber = FALSE
+2 -2
View File
@@ -291,8 +291,8 @@
message_admins("Explosive tank rupture! Last key to touch the tank was [src.fingerprintslast].")
log_game("Explosive tank rupture! Last key to touch the tank was [src.fingerprintslast].")
//Give the gas a chance to build up more pressure through reacting
air_contents.react(src)
air_contents.react(src)
for(var/i in 1 to TANK_POST_FRAGMENT_REACTIONS)
air_contents.react(src)
pressure = air_contents.return_pressure()
var/range = (pressure-TANK_FRAGMENT_PRESSURE)/TANK_FRAGMENT_SCALE
+1 -1
View File
@@ -397,7 +397,7 @@
data["owner_name"] = payments_acc.account_holder
if(showpiece)
data["product_name"] = capitalize(showpiece.name)
var/base64 = icon2base64(icon(showpiece.icon, showpiece.icon_state))
var/base64 = icon2base64(icon(showpiece.icon, showpiece.icon_state, SOUTH, 1))
data["product_icon"] = base64
data["registered"] = register
data["product_cost"] = sale_price
@@ -19,3 +19,11 @@
/turf/open/floor/plating/dirt/try_replace_tile(obj/item/stack/tile/T, mob/user, params)
return
/turf/open/floor/plating/dirt/space
baseturfs = /turf/baseturf_bottom
planetary_atmos = FALSE
desc = "Upon closer examination there's plating beneath the dirt."
/turf/open/floor/plating/dirt/space/airless
initial_gas_mix = AIRLESS_ATMOS
+1 -1
View File
@@ -55,7 +55,7 @@
"name" = initial(item.name),
"desc" = initial(item.desc),
// at this point initializing the item is probably faster tbh
"sprite" = icon2base64(icon(initial(item.icon), initial(item.icon_state))),
"sprite" = icon2base64(icon(initial(item.icon), initial(item.icon_state), SOUTH, 1)),
)
return data
+6
View File
@@ -2038,6 +2038,12 @@
var/obj/item/station_charter/charter = locate(href_list["reject_custom_name"])
if(istype(charter))
charter.reject_proposed(usr)
else if(href_list["approve_custom_name"])
if(!check_rights(R_ADMIN))
return
var/obj/item/station_charter/charter = locate(href_list["approve_custom_name"])
if(istype(charter))
charter.allow_pass(usr)
else if(href_list["jumpto"])
if(!isobserver(usr) && !check_rights(R_ADMIN))
return
+1 -1
View File
@@ -242,7 +242,7 @@
var/selectors_used = FALSE
var/list/combined_refs = list()
do
CHECK_TICK
stoplag(2)
finished = TRUE
for(var/i in running)
var/datum/SDQL2_query/query = i
@@ -53,7 +53,7 @@
user.adjustOrganLoss(ORGAN_SLOT_BRAIN, 30)
addtimer(CALLBACK(user, /mob/living.proc/dropItemToGround, src, TRUE), 1) //equipped happens before putting stuff on(but not before picking items up), 1). thus, we need to wait for it to be on before forcing it off.
/obj/item/clothing/head/helmet/clockwork/mob_can_equip(mob/M, mob/equipper, slot, disable_warning = 0)
/obj/item/clothing/head/helmet/clockwork/mob_can_equip(M, equipper, slot, disable_warning, bypass_equip_delay_self)
if(equipper && !is_servant_of_ratvar(equipper))
return 0
return ..()
@@ -98,7 +98,7 @@
max_heat_protection_temperature = initial(max_heat_protection_temperature)
min_cold_protection_temperature = initial(min_cold_protection_temperature)
/obj/item/clothing/suit/armor/clockwork/mob_can_equip(mob/M, mob/equipper, slot, disable_warning = 0)
/obj/item/clothing/suit/armor/clockwork/mob_can_equip(M, equipper, slot, disable_warning, bypass_equip_delay_self)
if(equipper && !is_servant_of_ratvar(equipper))
return 0
return ..()
@@ -158,7 +158,7 @@
max_heat_protection_temperature = initial(max_heat_protection_temperature)
min_cold_protection_temperature = initial(min_cold_protection_temperature)
/obj/item/clothing/gloves/clockwork/mob_can_equip(mob/M, mob/equipper, slot, disable_warning = 0)
/obj/item/clothing/gloves/clockwork/mob_can_equip(M, equipper, slot, disable_warning, bypass_equip_delay_self)
if(equipper && !is_servant_of_ratvar(equipper))
return 0
return ..()
@@ -208,7 +208,7 @@
else
clothing_flags &= ~NOSLIP
/obj/item/clothing/shoes/clockwork/mob_can_equip(mob/M, mob/equipper, slot, disable_warning = 0)
/obj/item/clothing/shoes/clockwork/mob_can_equip(M, equipper, slot, disable_warning, bypass_equip_delay_self)
if(equipper && !is_servant_of_ratvar(equipper))
return 0
return ..()
+51 -11
View File
@@ -43,6 +43,7 @@
)
)
fusion_power = 3
enthalpy = -393500
/datum/gas/plasma
id = GAS_PLASMA
@@ -54,7 +55,10 @@
heat_penalty = 15
transmit_modifier = 4
powermix = 1
// no fire info cause it has its own bespoke reaction for trit generation reasons
fire_burn_rate = OXYGEN_BURN_RATE_BASE // named when plasma fires were the only fires, surely
fire_temperature = FIRE_MINIMUM_TEMPERATURE_TO_EXIST
fire_products = "plasma_fire"
enthalpy = FIRE_PLASMA_ENERGY_RELEASED // 3000000, 3 megajoules, 3000 kj
/datum/gas/water_vapor
id = GAS_H2O
@@ -64,6 +68,7 @@
moles_visible = MOLES_GAS_VISIBLE
fusion_power = 8
heat_penalty = 8
enthalpy = -241800 // FIRE_HYDROGEN_ENERGY_RELEASED is actually what this was supposed to be
powermix = 1
breath_reagent = /datum/reagent/water
@@ -84,6 +89,7 @@
fire_products = list(GAS_N2 = 1)
oxidation_rate = 0.5
oxidation_temperature = FIRE_MINIMUM_TEMPERATURE_TO_EXIST + 100
enthalpy = 81600
heat_resistance = 6
/datum/gas/nitryl
@@ -95,8 +101,22 @@
flags = GAS_FLAG_DANGEROUS
fusion_power = 15
fire_products = list(GAS_N2 = 0.5)
enthalpy = 33200
oxidation_temperature = FIRE_MINIMUM_TEMPERATURE_TO_EXIST - 50
/datum/gas/hydrogen
id = GAS_HYDROGEN
specific_heat = 10
name = "Hydrogen"
flags = GAS_FLAG_DANGEROUS
fusion_power = 0
powermix = 1
heat_penalty = 3
transmit_modifier = 10
fire_products = list(GAS_H2O = 2)
fire_burn_rate = 2
fire_temperature = FIRE_MINIMUM_TEMPERATURE_TO_EXIST - 50
/datum/gas/tritium
id = GAS_TRITIUM
specific_heat = 10
@@ -108,13 +128,10 @@
powermix = 1
heat_penalty = 10
transmit_modifier = 30
/*
these are for when we add hydrogen, trit gets to keep its hardcoded fire for legacy reasons
fire_provides = list(GAS_H2O = 2)
fire_products = list(GAS_H2O = 2)
fire_burn_rate = 2
fire_energy_released = FIRE_HYDROGEN_ENERGY_RELEASED
fire_radiation_released = 50 // arbitrary number, basically 60 moles of trit burning will just barely start to harm you
fire_temperature = FIRE_MINIMUM_TEMPERATURE_TO_EXIST - 50
*/
/datum/gas/bz
id = GAS_BZ
@@ -124,6 +141,7 @@
fusion_power = 8
powermix = 1
heat_penalty = 5
enthalpy = FIRE_CARBON_ENERGY_RELEASED // it is a mystery
transmit_modifier = -2
radioactivity_modifier = 5
@@ -139,7 +157,8 @@
name = "Pluoxium"
fusion_power = 10
oxidation_temperature = FIRE_MINIMUM_TEMPERATURE_TO_EXIST * 1000 // it is VERY stable
oxidation_rate = 8
oxidation_rate = 8 // when it can oxidize, it can oxidize a LOT
enthalpy = -50000 // but it reduces the heat output a bit
powermix = -1
heat_penalty = -1
transmit_modifier = -5
@@ -172,7 +191,7 @@
alert_type = /atom/movable/screen/alert/too_much_ch4
)
)
fire_energy_released = FIRE_CARBON_ENERGY_RELEASED
enthalpy = -74600
fire_temperature = FIRE_MINIMUM_TEMPERATURE_TO_EXIST
/datum/gas/methyl_bromide
@@ -192,7 +211,28 @@
alert_type = /atom/movable/screen/alert/too_much_ch3br
)
)
fire_products = list(GAS_CO2 = 1, GAS_H2O = 1.5, GAS_BZ = 0.5)
fire_energy_released = FIRE_CARBON_ENERGY_RELEASED
fire_burn_rate = 0.5
fire_products = list(GAS_CO2 = 1, GAS_H2O = 1.5, GAS_BROMINE = 0.5)
enthalpy = -35400
fire_burn_rate = 4 / 7 // oh no
fire_temperature = 808 // its autoignition, it apparently doesn't spark readily, so i don't put it lower
/datum/gas/bromine
id = GAS_BROMINE
specific_heat = 76
name = "Bromine"
flags = GAS_FLAG_DANGEROUS
group = GAS_GROUP_CHEMICALS
enthalpy = 193 // yeah it's small but it's good to include it
breath_reagent = /datum/reagent/bromine
/datum/gas/ammonia
id = GAS_AMMONIA
specific_heat = 35
name = "Ammonia"
flags = GAS_FLAG_DANGEROUS
group = GAS_GROUP_CHEMICALS
enthalpy = -45900
breath_reagent = /datum/reagent/ammonia
fire_products = list(GAS_H2O = 1.5, GAS_N2 = 0.5)
fire_burn_rate = 4/3
fire_temperature = 924
+24 -8
View File
@@ -15,6 +15,7 @@ GLOBAL_LIST_INIT(nonreactive_gases, typecacheof(list(GAS_O2, GAS_N2, GAS_CO2, GA
/proc/_auxtools_register_gas(datum/gas/gas) // makes sure auxtools knows stuff about this gas
/datum/auxgm
var/done_initializing = FALSE
var/list/datums = list()
var/list/specific_heats = list()
var/list/names = list()
@@ -32,30 +33,34 @@ GLOBAL_LIST_INIT(nonreactive_gases, typecacheof(list(GAS_O2, GAS_N2, GAS_CO2, GA
var/list/oxidation_temperatures = list()
var/list/oxidation_rates = list()
var/list/fire_temperatures = list()
var/list/fire_enthalpies = list()
var/list/enthalpies = list()
var/list/fire_products = list()
var/list/fire_burn_rates = list()
var/list/supermatter = list()
var/list/groups_by_gas = list()
var/list/groups = list()
/datum/gas
var/id = ""
var/specific_heat = 0
var/name = ""
var/gas_overlay = "" //icon_state in icons/effects/atmospherics.dmi
var/color = "#ffff"
var/moles_visible = null
var/flags = NONE //currently used by canisters
var/group = null // groups for scrubber/filter listing
var/fusion_power = 0 // How much the gas destabilizes a fusion reaction
var/breath_results = GAS_CO2 // what breathing this breathes out
var/breath_reagent = null // what breathing this adds to your reagents
var/breath_reagent_dangerous = null // what breathing this adds to your reagents IF it's above a danger threshold
var/datum/reagent/breath_reagent = null // what breathing this adds to your reagents
var/datum/reagent/breath_reagent_dangerous = null // what breathing this adds to your reagents IF it's above a danger threshold
var/list/breath_alert_info = null // list for alerts that pop up when you have too much/not enough of something
var/oxidation_temperature = null // temperature above which this gas is an oxidizer; null for none
var/oxidation_rate = 1 // how many moles of this can oxidize how many moles of material
var/fire_temperature = null // temperature above which gas may catch fire; null for none
var/list/fire_products = null // what results when this gas is burned (oxidizer or fuel); null for none
var/fire_energy_released = 0 // how much energy is released per mole of fuel burned
var/enthalpy = 0 // Standard enthalpy of formation in joules, used for fires
var/fire_burn_rate = 1 // how many moles are burned per product released
var/fire_radiation_released = 0 // How much radiation is released when this gas burns
var/powermix = 0 // how much this gas contributes to the supermatter's powermix ratio
var/heat_penalty = 0 // heat and waste penalty from having the supermatter crystal surrounded by this gas; negative numbers reduce
var/transmit_modifier = 0 // bonus to supermatter power generation (multiplicative, since it's % based, and divided by 10)
@@ -94,21 +99,31 @@ GLOBAL_LIST_INIT(nonreactive_gases, typecacheof(list(GAS_O2, GAS_N2, GAS_CO2, GA
breath_reagents[g] = gas.breath_reagent
if(gas.breath_reagent_dangerous)
breath_reagents_dangerous[g] = gas.breath_reagent_dangerous
if(gas.oxidation_temperature)
oxidation_temperatures[g] = gas.oxidation_temperature
oxidation_rates[g] = gas.oxidation_rate
if(gas.fire_products)
fire_products[g] = gas.fire_products
fire_enthalpies[g] = gas.fire_energy_released
enthalpies[g] = gas.enthalpy
else if(gas.fire_temperature)
fire_temperatures[g] = gas.fire_temperature
fire_burn_rates[g] = gas.fire_burn_rate
if(gas.fire_products)
fire_products[g] = gas.fire_products
fire_enthalpies[g] = gas.fire_energy_released
enthalpies[g] = gas.enthalpy
if(gas.group)
if(!(gas.group in groups))
groups[gas.group] = list()
groups[gas.group] += gas
groups_by_gas[g] = gas.group
add_supermatter_properties(gas)
_auxtools_register_gas(gas)
if(done_initializing)
for(var/r in SSair.gas_reactions)
var/datum/gas_reaction/R = r
R.init_reqs()
SSair.auxtools_update_reactions()
SEND_GLOBAL_SIGNAL(COMSIG_GLOB_NEW_GAS, g)
/proc/finalize_gas_refs()
@@ -127,6 +142,7 @@ GLOBAL_LIST_INIT(nonreactive_gases, typecacheof(list(GAS_O2, GAS_N2, GAS_CO2, GA
for(var/breathing_class_path in subtypesof(/datum/breathing_class))
var/datum/breathing_class/class = new breathing_class_path
breathing_classes[breathing_class_path] = class
done_initializing = TRUE
finalize_gas_refs()
@@ -53,23 +53,68 @@
id = "vapor"
/datum/gas_reaction/water_vapor/init_reqs()
min_requirements = list(GAS_H2O = MOLES_GAS_VISIBLE)
min_requirements = list(
GAS_H2O = MOLES_GAS_VISIBLE,
"MAX_TEMP" = T0C + 40
)
/datum/gas_reaction/water_vapor/react(datum/gas_mixture/air, datum/holder)
var/turf/open/location = isturf(holder) ? holder : null
. = NO_REACTION
var/turf/open/location = holder
if(!istype(location))
return NO_REACTION
if (air.return_temperature() <= WATER_VAPOR_FREEZE)
if(location && location.freon_gas_act())
. = REACTING
return REACTING
else if(location && location.water_vapor_gas_act())
air.adjust_moles(GAS_H2O,-MOLES_GAS_VISIBLE)
. = REACTING
return REACTING
// no test cause it's entirely based on location
/datum/gas_reaction/condensation
priority = 0
name = "Condensation"
id = "condense"
exclude = TRUE
var/datum/reagent/condensing_reagent
/datum/gas_reaction/condensation/New(datum/reagent/R)
. = ..()
if(!istype(R))
return
min_requirements = list(
"MAX_TEMP" = initial(R.boiling_point)
)
min_requirements[R.get_gas()] = MOLES_GAS_VISIBLE
name = "[R.name] condensation"
id = "[R.type] condensation"
condensing_reagent = R
exclude = FALSE
/datum/gas_reaction/condensation/react(datum/gas_mixture/air, datum/holder)
. = NO_REACTION
var/turf/open/location = holder
if(!istype(location))
return
var/temperature = air.return_temperature()
var/static/datum/reagents/reagents_holder = new
reagents_holder.clear_reagents()
reagents_holder.chem_temp = temperature
var/G = condensing_reagent.get_gas()
var/amt = air.get_moles(G)
air.adjust_moles(G, -min(initial(condensing_reagent.condensation_amount), amt))
reagents_holder.add_reagent(condensing_reagent, amt)
. = REACTING
for(var/atom/movable/AM in location)
if(location.intact && AM.level == 1)
continue
reagents_holder.reaction(AM, TOUCH)
reagents_holder.reaction(location, TOUCH)
//tritium combustion: combustion of oxygen and tritium (treated as hydrocarbons). creates hotspots. exothermic
/datum/gas_reaction/tritfire
priority = -1 //fire should ALWAYS be last, but tritium fires happen before plasma fires
exclude = TRUE // generic fire now takes care of this
name = "Tritium Combustion"
id = "tritfire"
@@ -88,9 +133,9 @@
item.temperature_expose(air, temperature, CELL_VOLUME)
location.temperature_expose(air, temperature, CELL_VOLUME)
/proc/radiation_burn(turf/open/location, energy_released)
/proc/radiation_burn(turf/open/location, rad_power)
if(istype(location) && prob(10))
radiation_pulse(location, energy_released/TRITIUM_BURN_RADIOACTIVITY_FACTOR)
radiation_pulse(location, rad_power)
/datum/gas_reaction/tritfire/react(datum/gas_mixture/air, datum/holder)
var/energy_released = 0
@@ -151,6 +196,7 @@
/datum/gas_reaction/plasmafire
priority = -2 //fire should ALWAYS be last, but plasma fires happen after tritium fires
name = "Plasma Combustion"
exclude = TRUE // generic fire now takes care of this
id = "plasmafire"
/datum/gas_reaction/plasmafire/init_reqs()
@@ -300,7 +346,7 @@
fuels[fuel] *= oxidation_ratio
fuels += oxidizers
var/list/fire_products = GLOB.gas_data.fire_products
var/list/fire_enthalpies = GLOB.gas_data.fire_enthalpies
var/list/fire_enthalpies = GLOB.gas_data.enthalpies
for(var/fuel in fuels + oxidizers)
var/amt = fuels[fuel]
if(!burn_results[fuel])
@@ -535,7 +535,7 @@
for(var/device_id in A.air_scrub_names)
send_signal(device_id, list(
"power" = 1,
"set_filters" = list(GAS_CO2, GAS_MIASMA),
"set_filters" = list(GAS_CO2, GAS_MIASMA, GAS_GROUP_CHEMICALS),
"scrubbing" = 1,
"widenet" = 0,
))
@@ -554,6 +554,7 @@
GAS_MIASMA,
GAS_PLASMA,
GAS_H2O,
GAS_HYDROGEN,
GAS_HYPERNOB,
GAS_NITROUS,
GAS_NITRYL,
@@ -562,7 +563,8 @@
GAS_STIMULUM,
GAS_PLUOXIUM,
GAS_METHANE,
GAS_METHYL_BROMIDE
GAS_METHYL_BROMIDE,
GAS_GROUP_CHEMICALS
),
"scrubbing" = 1,
"widenet" = 1,
@@ -582,9 +584,16 @@
))
for(var/device_id in A.air_vent_names)
send_signal(device_id, list(
"is_pressurizing" = 1,
"power" = 1,
"checks" = 1,
"set_external_pressure" = ONE_ATMOSPHERE*2
"set_external_pressure" = ONE_ATMOSPHERE*1.4
))
send_signal(device_id, list(
"is_siphoning" = 1,
"power" = 1,
"checks" = 1,
"set_external_pressure" = ONE_ATMOSPHERE/1.4
))
if(AALARM_MODE_REFILL)
for(var/device_id in A.air_scrub_names)
@@ -596,10 +605,15 @@
))
for(var/device_id in A.air_vent_names)
send_signal(device_id, list(
"is_pressurizing" = 1,
"power" = 1,
"checks" = 1,
"set_external_pressure" = ONE_ATMOSPHERE * 3
))
send_signal(device_id, list(
"is_siphoning" = 1,
"power" = 0,
))
if(AALARM_MODE_PANIC,
AALARM_MODE_REPLACEMENT)
for(var/device_id in A.air_scrub_names)
@@ -610,8 +624,14 @@
))
for(var/device_id in A.air_vent_names)
send_signal(device_id, list(
"is_pressurizing" = 1,
"power" = 0
))
send_signal(device_id, list(
"is_siphoning" = 1,
"power" = 1,
"checks" = 0
))
if(AALARM_MODE_SIPHON)
for(var/device_id in A.air_scrub_names)
send_signal(device_id, list(
@@ -621,9 +641,14 @@
))
for(var/device_id in A.air_vent_names)
send_signal(device_id, list(
"is_pressurizing" = 1,
"power" = 0
))
send_signal(device_id, list(
"is_siphoning" = 1,
"power" = 1,
"checks" = 0
))
if(AALARM_MODE_OFF)
for(var/device_id in A.air_scrub_names)
send_signal(device_id, list(
@@ -641,8 +666,12 @@
for(var/device_id in A.air_vent_names)
send_signal(device_id, list(
"power" = 1,
"checks" = 2,
"set_internal_pressure" = 0
"checks" = 0,
"is_pressurizing" = 1
))
send_signal(device_id, list(
"power" = 0,
"is_siphoning" = 1
))
/obj/machinery/airalarm/update_icon_state()
@@ -94,7 +94,10 @@
if(transfer_ratio > 0)
if(filter_type && air2.return_pressure() <= 9000)
air1.scrub_into(air2, transfer_ratio, list(filter_type))
if(filter_type in GLOB.gas_data.groups)
air1.scrub_into(air2, transfer_ratio, GLOB.gas_data.groups[filter_type])
else
air1.scrub_into(air2, transfer_ratio, list(filter_type))
if(air3.return_pressure() <= 9000)
air1.transfer_ratio_to(air3, transfer_ratio)
@@ -119,8 +122,10 @@
data["filter_types"] = list()
data["filter_types"] += list(list("name" = "Nothing", "id" = "", "selected" = !filter_type))
for(var/id in GLOB.gas_data.ids)
data["filter_types"] += list(list("name" = GLOB.gas_data.names[id], "id" = id, "selected" = (id == filter_type)))
if(!(id in GLOB.gas_data.groups_by_gas))
data["filter_types"] += list(list("name" = GLOB.gas_data.names[id], "id" = id, "selected" = (id == filter_type)))
for(var/group in GLOB.gas_data.groups)
data["filter_types"] += list(list("name" = group, "id" = group, "selected" = (group == filter_type)))
return data
/obj/machinery/atmospherics/components/trinary/filter/ui_act(action, params)
@@ -178,6 +178,9 @@
var/mob/signal_sender = signal.data["user"]
if((("is_siphoning" in signal.data) && pump_direction == RELEASING) || (("is_pressurizing" in signal.data) && pump_direction == SIPHONING))
return
if("purge" in signal.data)
pressure_checks &= ~EXT_BOUND
pump_direction = SIPHONING
@@ -18,7 +18,8 @@
var/id_tag = null
var/scrubbing = SCRUBBING //0 = siphoning, 1 = scrubbing
var/filter_types = list(GAS_CO2)
var/filter_types = list(GAS_CO2, GAS_MIASMA, GAS_GROUP_CHEMICALS)
var/list/clean_filter_types = null
var/volume_rate = 200
var/widenet = 0 //is this scrubber acting on the 3x3 area around it.
var/list/turf/adjacent_turfs = list()
@@ -34,6 +35,16 @@
..()
if(!id_tag)
id_tag = assign_uid_vents()
generate_clean_filter_types()
RegisterSignal(SSdcs,COMSIG_GLOB_NEW_GAS,.proc/generate_clean_filter_types)
/obj/machinery/atmospherics/components/unary/vent_scrubber/proc/generate_clean_filter_types()
clean_filter_types = list()
for(var/id in filter_types)
if(id in GLOB.gas_data.groups)
clean_filter_types += GLOB.gas_data.groups[id]
else
clean_filter_types += id
/obj/machinery/atmospherics/components/unary/vent_scrubber/Destroy()
var/area/A = get_base_area(src)
@@ -95,7 +106,11 @@
var/list/f_types = list()
for(var/id in GLOB.gas_data.ids)
f_types += list(list("gas_id" = id, "gas_name" = GLOB.gas_data.names[id], "enabled" = (id in filter_types)))
if(!(id in GLOB.gas_data.groups_by_gas))
f_types += list(list("gas_id" = id, "gas_name" = GLOB.gas_data.names[id], "enabled" = (id in filter_types)))
for(var/group in GLOB.gas_data.groups)
f_types += list(list("gas_id" = group, "gas_name" = group, "enabled" = (group in filter_types)))
var/datum/signal/signal = new(list(
"tag" = id_tag,
@@ -147,11 +162,11 @@
var/datum/gas_mixture/environment = tile.return_air()
var/datum/gas_mixture/air_contents = airs[1]
if(air_contents.return_pressure() >= 50*ONE_ATMOSPHERE || !islist(filter_types))
if(air_contents.return_pressure() >= 50*ONE_ATMOSPHERE || !islist(clean_filter_types))
return FALSE
if(scrubbing & SCRUBBING)
environment.scrub_into(air_contents, volume_rate/environment.return_volume(), filter_types)
environment.scrub_into(air_contents, volume_rate/environment.return_volume(), clean_filter_types)
tile.air_update_turf()
@@ -205,11 +220,13 @@
if("toggle_filter" in signal.data)
filter_types ^= signal.data["toggle_filter"]
generate_clean_filter_types()
if("set_filters" in signal.data)
filter_types = list()
for(var/gas in signal.data["set_filters"])
filter_types += gas
generate_clean_filter_types()
if("init" in signal.data)
name = signal.data["init"]
+5
View File
@@ -171,6 +171,8 @@ GLOBAL_LIST_EMPTY(preferences_datums)
var/auto_fit_viewport = FALSE
///Should we be in the widescreen mode set by the config?
var/widescreenpref = TRUE
///Strip menu style
var/long_strip_menu = FALSE
///What size should pixels be displayed as? 0 is strech to fit
var/pixel_size = 0
///What scaling method should we use?
@@ -829,6 +831,7 @@ GLOBAL_LIST_EMPTY(preferences_datums)
dat +="<td width='300px' height='300px' valign='top'>"
dat += "<h2>Citadel Preferences</h2>" //Because fuck me if preferences can't be fucking modularized and expected to update in a reasonable timeframe.
dat += "<b>Widescreen:</b> <a href='?_src_=prefs;preference=widescreenpref'>[widescreenpref ? "Enabled ([CONFIG_GET(string/default_view)])" : "Disabled (15x15)"]</a><br>"
dat += "<b>Long strip menu:</b> <a href='?_src_=prefs;preference=long_strip_menu'>[long_strip_menu ? "Enabled" : "Disabled"]</a><br>"
dat += "<b>Auto stand:</b> <a href='?_src_=prefs;preference=autostand'>[autostand ? "Enabled" : "Disabled"]</a><br>"
dat += "<b>Auto OOC:</b> <a href='?_src_=prefs;preference=auto_ooc'>[auto_ooc ? "Enabled" : "Disabled"]</a><br>"
dat += "<b>Force Slot Storage HUD:</b> <a href='?_src_=prefs;preference=no_tetris_storage'>[no_tetris_storage ? "Enabled" : "Disabled"]</a><br>"
@@ -2591,6 +2594,8 @@ GLOBAL_LIST_EMPTY(preferences_datums)
if("widescreenpref")
widescreenpref = !widescreenpref
user.client.view_size.setDefault(getScreenSize(widescreenpref))
if("long_strip_menu")
long_strip_menu = !long_strip_menu
if("pixel_size")
switch(pixel_size)
@@ -410,6 +410,7 @@ SAVEFILE UPDATING/VERSIONING - 'Simplified', or rather, more coder-friendly ~Car
S["ambientocclusion"] >> ambientocclusion
S["auto_fit_viewport"] >> auto_fit_viewport
S["widescreenpref"] >> widescreenpref
S["long_strip_menu"] >> long_strip_menu
S["pixel_size"] >> pixel_size
S["scaling_method"] >> scaling_method
S["hud_toggle_flash"] >> hud_toggle_flash
@@ -472,6 +473,7 @@ SAVEFILE UPDATING/VERSIONING - 'Simplified', or rather, more coder-friendly ~Car
ambientocclusion = sanitize_integer(ambientocclusion, 0, 1, initial(ambientocclusion))
auto_fit_viewport = sanitize_integer(auto_fit_viewport, 0, 1, initial(auto_fit_viewport))
widescreenpref = sanitize_integer(widescreenpref, 0, 1, initial(widescreenpref))
long_strip_menu = sanitize_integer(long_strip_menu, 0, 1, initial(long_strip_menu))
pixel_size = sanitize_integer(pixel_size, PIXEL_SCALING_AUTO, PIXEL_SCALING_3X, initial(pixel_size))
scaling_method = sanitize_text(scaling_method, initial(scaling_method))
hud_toggle_flash = sanitize_integer(hud_toggle_flash, 0, 1, initial(hud_toggle_flash))
@@ -604,6 +606,7 @@ SAVEFILE UPDATING/VERSIONING - 'Simplified', or rather, more coder-friendly ~Car
WRITE_FILE(S["damagescreenshake"], damagescreenshake)
WRITE_FILE(S["arousable"], arousable)
WRITE_FILE(S["widescreenpref"], widescreenpref)
WRITE_FILE(S["long_strip_menu"], long_strip_menu)
WRITE_FILE(S["autostand"], autostand)
WRITE_FILE(S["cit_toggles"], cit_toggles)
WRITE_FILE(S["preferred_chaos"], preferred_chaos)
+1 -1
View File
@@ -443,7 +443,7 @@ BLIND // can't see anything
..()
//Species-restricted clothing check. - Thanks Oraclestation, BS13, /vg/station etc.
/obj/item/clothing/mob_can_equip(mob/M, slot, disable_warning = TRUE)
/obj/item/clothing/mob_can_equip(M, equipper, slot, disable_warning = TRUE, bypass_equip_delay_self)
//if we can't equip the item anyway, don't bother with species_restricted (also cuts down on spam)
if(!..())
@@ -267,9 +267,15 @@
desc = "A specialized pair of combat boots with a built-in propulsion system for rapid foward movement."
icon_state = "jetboots"
resistance_flags = FIRE_PROOF
cold_protection = FEET|LEGS
min_cold_protection_temperature = SHOES_MIN_TEMP_PROTECT
heat_protection = FEET|LEGS
max_heat_protection_temperature = SHOES_MAX_TEMP_PROTECT
pocket_storage_component_path = /datum/component/storage/concrete/pockets/shoes
actions_types = list(/datum/action/item_action/bhop)
permeability_coefficient = 0.05
unique_reskin = list("Explorer" = "miningjet",
"Jackboot" = "jetboots")
var/jumpdistance = 5 //-1 from to see the actual distance, e.g 4 goes over 3 tiles
var/jumpspeed = 3
var/recharging_rate = 60 //default 6 seconds between each dash
+1 -1
View File
@@ -637,7 +637,7 @@
helmettype = /obj/item/clothing/head/helmet/space/hardsuit/clown
mutantrace_variation = STYLE_DIGITIGRADE
/obj/item/clothing/suit/space/hardsuit/clown/mob_can_equip(mob/M, slot)
/obj/item/clothing/suit/space/hardsuit/clown/mob_can_equip(mob/M, equipper, slot, disable_warning, bypass_equip_delay_self)
if(!..() || !ishuman(M))
return FALSE
if(M.mind && HAS_TRAIT(M.mind, TRAIT_CLOWN_MENTALITY))
@@ -245,6 +245,8 @@
those who wish to spit in the eyes of God. Sacrifices outright damage for \
a reliance on backstabs and the ability to give fauna concussions on a parry."
attack_verb = list("pummeled", "punched", "jabbed", "hammer-fisted", "uppercut", "slammed")
hitsound = 'sound/weapons/resonator_blast.ogg'
sharpness = SHARP_NONE // use your survival dagger or smth
icon_state = "crusher-hands"
item_state = "crusher0-fist"
unique_reskin = list("Gauntlets" = "crusher-hands",
@@ -6,8 +6,6 @@
possible_a_intents = list(INTENT_HELP, INTENT_DISARM, INTENT_GRAB, INTENT_HARM)
limb_destroyer = 1
hud_type = /datum/hud/alien
var/obj/item/r_store = null
var/obj/item/l_store = null
var/caste = ""
var/alt_icon = 'icons/mob/alienleap.dmi' //used to switch between the two alien icon files.
var/leap_on_click = 0
@@ -22,41 +20,26 @@
can_ventcrawl = TRUE
GLOBAL_LIST_INIT(strippable_alien_humanoid_items, create_strippable_list(list(
/datum/strippable_item/hand/left,
/datum/strippable_item/hand/right,
/datum/strippable_item/mob_item_slot/handcuffs,
/datum/strippable_item/mob_item_slot/legcuffs,
)))
//This is fine right now, if we're adding organ specific damage this needs to be updated
/mob/living/carbon/alien/humanoid/Initialize()
AddAbility(new/obj/effect/proc_holder/alien/regurgitate(null))
. = ..()
/mob/living/carbon/alien/humanoid/ComponentInitialize()
. = ..()
AddComponent(/datum/component/footstep, FOOTSTEP_MOB_CLAW, 0.5, -3)
AddElement(/datum/element/strippable, GLOB.strippable_alien_humanoid_items)
/mob/living/carbon/alien/humanoid/restrained(ignore_grab)
return handcuffed
/mob/living/carbon/alien/humanoid/show_inv(mob/user)
user.set_machine(src)
var/list/dat = list()
dat += {"
<HR>
<span class='big bold'>[name]</span>
<HR>"}
for(var/i in 1 to held_items.len)
var/obj/item/I = get_item_for_held_index(i)
dat += "<BR><B>[get_held_index_name(i)]:</B><A href='?src=[REF(src)];item=[SLOT_HANDS];hand_index=[i]'>[(I && !(I.item_flags & ABSTRACT)) ? I : "<font color=grey>Empty</font>"]</a>"
dat += "<BR><A href='?src=[REF(src)];pouches=1'>Empty Pouches</A>"
if(handcuffed)
dat += "<BR><A href='?src=[REF(src)];item=[SLOT_HANDCUFFED]'>Handcuffed</A>"
if(legcuffed)
dat += "<BR><A href='?src=[REF(src)];item=[SLOT_LEGCUFFED]'>Legcuffed</A>"
dat += {"
<BR>
<BR><A href='?src=[REF(user)];mach_close=mob[REF(src)]'>Close</A>
"}
user << browse(dat.Join(), "window=mob[REF(src)];size=325x500")
onclose(user, "mob[REF(src)]")
/mob/living/carbon/alien/humanoid/Topic(href, href_list)
..()
//strip panel & embeds
@@ -70,12 +53,6 @@
return
SEND_SIGNAL(src, COMSIG_CARBON_EMBED_RIP, I, L)
return
if(href_list["pouches"])
visible_message("<span class='danger'>[usr] tries to empty [src]'s pouches.</span>", \
"<span class='userdanger'>[usr] tries to empty [src]'s pouches.</span>")
if(do_mob(usr, src, POCKET_STRIP_DELAY * 0.5))
dropItemToGround(r_store)
dropItemToGround(l_store)
/mob/living/carbon/alien/humanoid/cuff_resist(obj/item/I)
playsound(src, 'sound/voice/hiss5.ogg', 40, 1, 1) //Alien roars when starting to break free
@@ -51,10 +51,6 @@
// new damage icon system
// now constructs damage icon for each organ from mask * damage field
/mob/living/carbon/alien/larva/show_inv(mob/user)
return
/mob/living/carbon/alien/larva/toggle_throw_mode()
return
-53
View File
@@ -229,61 +229,8 @@
/mob/living/carbon/proc/canBeHandcuffed()
return 0
/mob/living/carbon/show_inv(mob/user)
user.set_machine(src)
var/dat = {"
<HR>
<B><FONT size=3>[name]</FONT></B>
<HR>
<BR><B>Head:</B> <A href='?src=[REF(src)];item=[SLOT_HEAD]'> [(head && !(head.item_flags & ABSTRACT)) ? head : "Nothing"]</A>
<BR><B>Mask:</B> <A href='?src=[REF(src)];item=[SLOT_WEAR_MASK]'> [(wear_mask && !(wear_mask.item_flags & ABSTRACT)) ? wear_mask : "Nothing"]</A>
<BR><B>Neck:</B> <A href='?src=[REF(src)];item=[SLOT_NECK]'> [(wear_neck && !(wear_neck.item_flags & ABSTRACT)) ? wear_neck : "Nothing"]</A>"}
for(var/i in 1 to held_items.len)
var/obj/item/I = get_item_for_held_index(i)
dat += "<BR><B>[get_held_index_name(i)]:</B></td><td><A href='?src=[REF(src)];item=[SLOT_HANDS];hand_index=[i]'>[(I && !(I.item_flags & ABSTRACT)) ? I : "Nothing"]</a>"
dat += "<BR><B>Back:</B> <A href='?src=[REF(src)];item=[SLOT_BACK]'>[back ? back : "Nothing"]</A>"
if(!HAS_TRAIT(src, TRAIT_NO_INTERNALS) && istype(wear_mask, /obj/item/clothing/mask) && istype(back, /obj/item/tank))
dat += "<BR><A href='?src=[REF(src)];internal=1'>[internal ? "Disable Internals" : "Set Internals"]</A>"
if(handcuffed)
dat += "<BR><A href='?src=[REF(src)];item=[SLOT_HANDCUFFED]'>Handcuffed</A>"
if(legcuffed)
dat += "<BR><A href='?src=[REF(src)];item=[SLOT_LEGCUFFED]'>Legcuffed</A>"
dat += {"
<BR>
<BR><A href='?src=[REF(user)];mach_close=mob[REF(src)]'>Close</A>
"}
user << browse(dat, "window=mob[REF(src)];size=325x500")
onclose(user, "mob[REF(src)]")
/mob/living/carbon/Topic(href, href_list)
..()
//strip panel
if(usr.canUseTopic(src, BE_CLOSE))
if(href_list["internal"] && !HAS_TRAIT(src, TRAIT_NO_INTERNALS))
var/slot = text2num(href_list["internal"])
var/obj/item/ITEM = get_item_by_slot(slot)
if(ITEM && istype(ITEM, /obj/item/tank) && wear_mask && (wear_mask.clothing_flags & ALLOWINTERNALS))
visible_message("<span class='danger'>[usr] tries to [internal ? "close" : "open"] the valve on [src]'s [ITEM.name].</span>", \
"<span class='userdanger'>[usr] tries to [internal ? "close" : "open"] the valve on your [ITEM.name].</span>", \
target = usr, target_message = "<span class='danger'>You try to [internal ? "close" : "open"] the valve on [src]'s [ITEM.name].</span>")
if(do_mob(usr, src, POCKET_STRIP_DELAY))
if(internal)
internal = null
update_internals_hud_icon(0)
else if(ITEM && istype(ITEM, /obj/item/tank))
if((wear_mask && (wear_mask.clothing_flags & ALLOWINTERNALS)) || getorganslot(ORGAN_SLOT_BREATHING_TUBE))
internal = ITEM
update_internals_hud_icon(1)
visible_message("<span class='danger'>[usr] [internal ? "opens" : "closes"] the valve on [src]'s [ITEM.name].</span>", \
"<span class='userdanger'>[usr] [internal ? "opens" : "closes"] the valve on your [ITEM.name].</span>", \
target = usr, target_message = "<span class='danger'>You [internal ? "opens" : "closes"] the valve on [src]'s [ITEM.name].</span>")
if(href_list["embedded_object"] && usr.canUseTopic(src, BE_CLOSE))
var/obj/item/bodypart/L = locate(href_list["embedded_limb"]) in bodyparts
if(!L)
@@ -0,0 +1,145 @@
/datum/strippable_item/mob_item_slot/head
key = STRIPPABLE_ITEM_HEAD
item_slot = SLOT_HEAD
/datum/strippable_item/mob_item_slot/back
key = STRIPPABLE_ITEM_BACK
item_slot = SLOT_BACK
/datum/strippable_item/mob_item_slot/back/get_alternate_action(atom/source, mob/user)
if(..() == FALSE)
return null
return get_strippable_alternate_action_internals(get_item(source), source)
/datum/strippable_item/mob_item_slot/back/alternate_action(atom/source, mob/user)
if (!..())
return null
return strippable_alternate_action_internals(get_item(source), source, user)
/datum/strippable_item/mob_item_slot/mask
key = STRIPPABLE_ITEM_MASK
item_slot = SLOT_WEAR_MASK
/datum/strippable_item/mob_item_slot/neck
key = STRIPPABLE_ITEM_NECK
item_slot = SLOT_NECK
/datum/strippable_item/mob_item_slot/handcuffs
key = STRIPPABLE_ITEM_HANDCUFFS
item_slot = SLOT_HANDCUFFED
/datum/strippable_item/mob_item_slot/handcuffs/should_show(atom/source, mob/user)
if (!iscarbon(source))
return FALSE
var/mob/living/carbon/carbon_source = source
return !isnull(carbon_source.handcuffed)
// You shouldn't be able to equip things to handcuff slots.
/datum/strippable_item/mob_item_slot/handcuffs/try_equip(atom/source, obj/item/equipping, mob/user)
return FALSE
/datum/strippable_item/mob_item_slot/legcuffs
key = STRIPPABLE_ITEM_LEGCUFFS
item_slot = SLOT_LEGCUFFED
/datum/strippable_item/mob_item_slot/legcuffs/should_show(atom/source, mob/user)
if (!iscarbon(source))
return FALSE
var/mob/living/carbon/carbon_source = source
return !isnull(carbon_source.legcuffed)
// You shouldn't be able to equip things to legcuff slots.
/datum/strippable_item/mob_item_slot/legcuffs/try_equip(atom/source, obj/item/equipping, mob/user)
return FALSE
/// A strippable item for a hand
/datum/strippable_item/hand
// Putting dangerous clothing in our hand is fine.
warn_dangerous_clothing = FALSE
/// Which hand?
var/hand_index
/datum/strippable_item/hand/get_item(atom/source)
if (!ismob(source))
return null
var/mob/mob_source = source
return mob_source.get_item_for_held_index(hand_index)
/datum/strippable_item/hand/try_equip(atom/source, obj/item/equipping, mob/user)
. = ..()
if (!.)
return FALSE
if (!ismob(source))
return FALSE
var/mob/mob_source = source
if (!mob_source.can_put_in_hand(equipping, hand_index))
to_chat(src, "<span class='warning'>\The [equipping] doesn't fit in that place!</span>")
return FALSE
return TRUE
/datum/strippable_item/hand/start_equip(atom/source, obj/item/equipping, mob/user)
. = ..()
if (!.)
return
if (!ismob(source))
return FALSE
var/mob/mob_source = source
if (!do_mob(user, source, equipping.equip_delay_other))
return FALSE
if(get_obscuring(source) == STRIPPABLE_OBSCURING_COMPLETELY)
return FALSE
if (!mob_source.can_put_in_hand(equipping, hand_index))
return FALSE
if (!user.temporarilyRemoveItemFromInventory(equipping))
return FALSE
return TRUE
/datum/strippable_item/hand/finish_equip(atom/source, obj/item/equipping, mob/user)
if(!..())
return FALSE
if (!iscarbon(source))
return FALSE
var/mob/mob_source = source
mob_source.put_in_hand(equipping, hand_index)
/datum/strippable_item/hand/start_unequip(atom/source, mob/user)
. = ..()
if (!.)
return
return start_unequip_mob(get_item(source), source, user)
/datum/strippable_item/hand/finish_unequip(atom/source, mob/user)
..()
var/obj/item/item = get_item(source)
if (isnull(item))
return FALSE
if (!ismob(source))
return FALSE
return finish_unequip_mob(item, source, user)
/datum/strippable_item/hand/left
key = STRIPPABLE_ITEM_LHAND
hand_index = 1
/datum/strippable_item/hand/right
key = STRIPPABLE_ITEM_RHAND
hand_index = 2
+1 -177
View File
@@ -47,6 +47,7 @@
AddElement(/datum/element/flavor_text/carbon, _name = "Flavor Text", _save_key = "flavor_text")
AddElement(/datum/element/flavor_text/carbon/temporary, "", "Set Pose (Temporary Flavor Text)", "This should be used only for things pertaining to the current round!", _save_key = null)
AddElement(/datum/element/flavor_text, _name = "OOC Notes", _addendum = "Put information on ERP/vore/lewd-related preferences here. THIS SHOULD NOT CONTAIN REGULAR FLAVORTEXT!!", _always_show = TRUE, _save_key = "ooc_notes", _examine_no_preview = TRUE)
AddElement(/datum/element/strippable, GLOB.strippable_human_items, /mob/living/carbon/human/.proc/should_strip)
/mob/living/carbon/human/Destroy()
QDEL_NULL(physiology)
@@ -110,106 +111,6 @@
var/datum/disease/D = thing
. += "* [D.name], Type: [D.spread_text], Stage: [D.stage]/[D.max_stages], Possible Cure: [D.cure_text]"
/mob/living/carbon/human/show_inv(mob/user)
user.set_machine(src)
var/has_breathable_mask = istype(wear_mask, /obj/item/clothing/mask)
var/list/obscured = check_obscured_slots()
var/list/dat = list()
dat += "<table>"
for(var/i in 1 to held_items.len)
var/obj/item/I = get_item_for_held_index(i)
dat += "<tr><td><B>[get_held_index_name(i)]:</B></td><td><A href='?src=[REF(src)];item=[SLOT_HANDS];hand_index=[i]'>[(I && !(I.item_flags & ABSTRACT)) ? I : "<font color=grey>Empty</font>"]</a></td></tr>"
dat += "<tr><td>&nbsp;</td></tr>"
dat += "<tr><td><B>Back:</B></td><td><A href='?src=[REF(src)];item=[SLOT_BACK]'>[(back && !(back.item_flags & ABSTRACT)) ? back : "<font color=grey>Empty</font>"]</A>"
if(has_breathable_mask && istype(back, /obj/item/tank))
dat += "&nbsp;<A href='?src=[REF(src)];internal=[SLOT_BACK]'>[internal ? "Disable Internals" : "Set Internals"]</A>"
dat += "</td></tr><tr><td>&nbsp;</td></tr>"
dat += "<tr><td><B>Head:</B></td><td><A href='?src=[REF(src)];item=[SLOT_HEAD]'>[(head && !(head.item_flags & ABSTRACT)) ? head : "<font color=grey>Empty</font>"]</A></td></tr>"
if(SLOT_WEAR_MASK in obscured)
dat += "<tr><td><font color=grey><B>Mask:</B></font></td><td><font color=grey>Obscured</font></td></tr>"
else
dat += "<tr><td><B>Mask:</B></td><td><A href='?src=[REF(src)];item=[SLOT_WEAR_MASK]'>[(wear_mask && !(wear_mask.item_flags & ABSTRACT)) ? wear_mask : "<font color=grey>Empty</font>"]</A></td></tr>"
if(SLOT_NECK in obscured)
dat += "<tr><td><font color=grey><B>Neck:</B></font></td><td><font color=grey>Obscured</font></td></tr>"
else
dat += "<tr><td><B>Neck:</B></td><td><A href='?src=[REF(src)];item=[SLOT_NECK]'>[(wear_neck && !(wear_neck.item_flags & ABSTRACT)) ? wear_neck : "<font color=grey>Empty</font>"]</A></td></tr>"
if(SLOT_GLASSES in obscured)
dat += "<tr><td><font color=grey><B>Eyes:</B></font></td><td><font color=grey>Obscured</font></td></tr>"
else
dat += "<tr><td><B>Eyes:</B></td><td><A href='?src=[REF(src)];item=[SLOT_GLASSES]'>[(glasses && !(glasses.item_flags & ABSTRACT)) ? glasses : "<font color=grey>Empty</font>"]</A></td></tr>"
if(SLOT_EARS in obscured)
dat += "<tr><td><font color=grey><B>Ears:</B></font></td><td><font color=grey>Obscured</font></td></tr>"
else
dat += "<tr><td><B>Ears:</B></td><td><A href='?src=[REF(src)];item=[SLOT_EARS]'>[(ears && !(ears.item_flags & ABSTRACT)) ? ears : "<font color=grey>Empty</font>"]</A></td></tr>"
dat += "<tr><td>&nbsp;</td></tr>"
dat += "<tr><td><B>Exosuit:</B></td><td><A href='?src=[REF(src)];item=[SLOT_WEAR_SUIT]'>[(wear_suit && !(wear_suit.item_flags & ABSTRACT)) ? wear_suit : "<font color=grey>Empty</font>"]</A>"
if(wear_suit)
if(istype(wear_suit, /obj/item/clothing/suit/space/hardsuit))
var/hardsuit_head = head && istype(head, /obj/item/clothing/head/helmet/space/hardsuit)
dat += "&nbsp;<A href='?src=[REF(src)];toggle_helmet=[SLOT_WEAR_SUIT]'>[hardsuit_head ? "Retract Helmet" : "Extend Helmet"]</A>"
dat += "</td></tr>"
dat += "<tr><td>&nbsp;&#8627;<B>Suit Storage:</B></td><td><A href='?src=[REF(src)];item=[SLOT_S_STORE]'>[(s_store && !(s_store.item_flags & ABSTRACT)) ? s_store : "<font color=grey>Empty</font>"]</A>"
if(has_breathable_mask && istype(s_store, /obj/item/tank))
dat += "&nbsp;<A href='?src=[REF(src)];internal=[SLOT_S_STORE]'>[internal ? "Disable Internals" : "Set Internals"]</A>"
dat += "</td></tr>"
else
dat += "<tr><td><font color=grey>&nbsp;&#8627;<B>Suit Storage:</B></font></td></tr>"
if(SLOT_SHOES in obscured)
dat += "<tr><td><font color=grey><B>Shoes:</B></font></td><td><font color=grey>Obscured</font></td></tr>"
else
dat += "<tr><td><B>Shoes:</B></td><td><A href='?src=[REF(src)];item=[SLOT_SHOES]'>[(shoes && !(shoes.item_flags & ABSTRACT)) ? shoes : "<font color=grey>Empty</font>"]</A>"
if(shoes && shoes.can_be_tied && shoes.tied != SHOES_KNOTTED)
dat += "&nbsp;<A href='?src=[REF(src)];shoes=[SLOT_SHOES]'>[shoes.tied ? "Untie shoes" : "Knot shoes"]</A>"
dat += "</td></tr>"
if(SLOT_GLOVES in obscured)
dat += "<tr><td><font color=grey><B>Gloves:</B></font></td><td><font color=grey>Obscured</font></td></tr>"
else
dat += "<tr><td><B>Gloves:</B></td><td><A href='?src=[REF(src)];item=[SLOT_GLOVES]'>[(gloves && !(gloves.item_flags & ABSTRACT)) ? gloves : "<font color=grey>Empty</font>"]</A></td></tr>"
if(SLOT_W_UNIFORM in obscured)
dat += "<tr><td><font color=grey><B>Uniform:</B></font></td><td><font color=grey>Obscured</font></td></tr>"
else
dat += "<tr><td><B>Uniform:</B></td><td><A href='?src=[REF(src)];item=[SLOT_W_UNIFORM]'>[(w_uniform && !(w_uniform.item_flags & ABSTRACT)) ? w_uniform : "<font color=grey>Empty</font>"]</A></td></tr>"
if((w_uniform == null && !(dna && dna.species.nojumpsuit)) || (SLOT_W_UNIFORM in obscured))
dat += "<tr><td><font color=grey>&nbsp;&#8627;<B>Pockets:</B></font></td></tr>"
dat += "<tr><td><font color=grey>&nbsp;&#8627;<B>ID:</B></font></td></tr>"
dat += "<tr><td><font color=grey>&nbsp;&#8627;<B>Belt:</B></font></td></tr>"
else
dat += "<tr><td>&nbsp;&#8627;<B>Belt:</B></td><td><A href='?src=[REF(src)];item=[SLOT_BELT]'>[(belt && !(belt.item_flags & ABSTRACT)) ? belt : "<font color=grey>Empty</font>"]</A>"
if(has_breathable_mask && istype(belt, /obj/item/tank))
dat += "&nbsp;<A href='?src=[REF(src)];internal=[SLOT_BELT]'>[internal ? "Disable Internals" : "Set Internals"]</A>"
dat += "</td></tr>"
dat += "<tr><td>&nbsp;&#8627;<B>Pockets:</B></td><td><A href='?src=[REF(src)];pockets=left'>[(l_store && !(l_store.item_flags & ABSTRACT)) ? "Left (Full)" : "<font color=grey>Left (Empty)</font>"]</A>"
dat += "&nbsp;<A href='?src=[REF(src)];pockets=right'>[(r_store && !(r_store.item_flags & ABSTRACT)) ? "Right (Full)" : "<font color=grey>Right (Empty)</font>"]</A></td></tr>"
dat += "<tr><td>&nbsp;&#8627;<B>ID:</B></td><td><A href='?src=[REF(src)];item=[SLOT_WEAR_ID]'>[(wear_id && !(wear_id.item_flags & ABSTRACT)) ? wear_id : "<font color=grey>Empty</font>"]</A></td></tr>"
if(handcuffed)
dat += "<tr><td><B>Handcuffed:</B> <A href='?src=[REF(src)];item=[SLOT_HANDCUFFED]'>Remove</A></td></tr>"
if(legcuffed)
dat += "<tr><td><A href='?src=[REF(src)];item=[SLOT_LEGCUFFED]'>Legcuffed</A></td></tr>"
dat += {"</table>
<A href='?src=[REF(user)];mach_close=mob[REF(src)]'>Close</A>
"}
var/datum/browser/popup = new(user, "mob[REF(src)]", "[src]", 440, 510)
popup.set_content(dat.Join())
popup.open()
// called when something steps onto a human
// this could be made more general, but for now just handle mulebot
/mob/living/carbon/human/Crossed(atom/movable/AM)
@@ -231,83 +132,6 @@
return
SEND_SIGNAL(src, COMSIG_CARBON_EMBED_RIP, I, L)
return
if(href_list["toggle_helmet"])
if(!istype(head, /obj/item/clothing/head/helmet/space/hardsuit))
return
var/obj/item/clothing/head/helmet/space/hardsuit/hardsuit_head = head
visible_message("<span class='danger'>[usr] tries to [hardsuit_head ? "retract" : "extend"] [src]'s helmet.</span>", \
"<span class='userdanger'>[usr] tries to [hardsuit_head ? "retract" : "extend"] [src]'s helmet.</span>", \
target = usr, target_message = "<span class='danger'>You try to [hardsuit_head ? "retract" : "extend"] [src]'s helmet.</span>")
if(!do_mob(usr, src, hardsuit_head ? head.strip_delay : POCKET_STRIP_DELAY))
return
if(!istype(wear_suit, /obj/item/clothing/suit/space/hardsuit) || (hardsuit_head ? (!head || head != hardsuit_head) : head))
return
var/obj/item/clothing/suit/space/hardsuit/hardsuit = wear_suit //This should be an hardsuit given all our checks
if(hardsuit.ToggleHelmet(FALSE))
visible_message("<span class='danger'>[usr] [hardsuit_head ? "retract" : "extend"] [src]'s helmet</span>", \
"<span class='userdanger'>[usr] [hardsuit_head ? "retract" : "extend"] [src]'s helmet</span>", \
target = usr, target_message = "<span class='danger'>You [hardsuit_head ? "retract" : "extend"] [src]'s helmet.</span>")
return
if(href_list["item"])
var/slot = text2num(href_list["item"])
if(slot in check_obscured_slots())
to_chat(usr, "<span class='warning'>You can't reach that! Something is covering it.</span>")
return
if(href_list["pockets"])
var/strip_mod = 1
var/strip_silence = FALSE
var/obj/item/clothing/gloves/G = gloves
if(istype(G))
strip_mod = G.strip_mod
strip_silence = G.strip_silence
var/pocket_side = href_list["pockets"]
var/pocket_id = (pocket_side == "right" ? SLOT_R_STORE : SLOT_L_STORE)
var/obj/item/pocket_item = (pocket_id == SLOT_R_STORE ? r_store : l_store)
var/obj/item/place_item = usr.get_active_held_item() // Item to place in the pocket, if it's empty
var/delay_denominator = 1
if(pocket_item && !(pocket_item.item_flags & ABSTRACT))
if(HAS_TRAIT(pocket_item, TRAIT_NODROP))
to_chat(usr, "<span class='warning'>You try to empty [src]'s [pocket_side] pocket, it seems to be stuck!</span>")
to_chat(usr, "<span class='notice'>You try to empty [src]'s [pocket_side] pocket.</span>")
else if(place_item && place_item.mob_can_equip(src, usr, pocket_id, 1) && !(place_item.item_flags & ABSTRACT))
to_chat(usr, "<span class='notice'>You try to place [place_item] into [src]'s [pocket_side] pocket.</span>")
delay_denominator = 4
else
return
if(do_mob(usr, src, max(round(POCKET_STRIP_DELAY/(delay_denominator*strip_mod)),1), ignorehelditem = TRUE)) //placing an item into the pocket is 4 times faster (and the strip_mod too)
if(pocket_item)
if(pocket_item == (pocket_id == SLOT_R_STORE ? r_store : l_store)) //item still in the pocket we search
dropItemToGround(pocket_item)
if(!usr.can_hold_items() || !usr.put_in_hands(pocket_item))
pocket_item.forceMove(drop_location())
log_combat(usr, src, "pickpocketed of item: [pocket_item]")
else
if(place_item)
if(place_item.mob_can_equip(src, usr, pocket_id, FALSE, TRUE))
usr.temporarilyRemoveItemFromInventory(place_item, TRUE)
equip_to_slot(place_item, pocket_id, TRUE)
log_combat(usr, src, "placed item [place_item] onto")
//do nothing otherwise
// Update strip window
if(usr.machine == src && in_range(src, usr))
show_inv(usr)
else
// Display a warning if the user mocks up
if(!strip_silence)
to_chat(src, "<span class='warning'>You feel your [pocket_side] pocket being fumbled with!</span>")
log_combat(usr, src, "failed to [pocket_item ? "pickpocket item [pocket_item] from" : "place item [place_item] onto "]")
if(usr.canUseTopic(src, BE_CLOSE, NO_DEXTERY, null, FALSE))
// separate from first canusetopic
var/mob/living/user = usr
if(istype(user) && href_list["shoes"] && (user.mobility_flags & MOBILITY_USE)) // we need to be on the ground, so we'll be a bit looser
shoes.handle_tying(usr)
..() //CITADEL CHANGE - removes a tab from behind this ..() so that flavortext can actually be examined
///////HUDs///////
if(href_list["hud"])
@@ -0,0 +1,306 @@
#define INTERNALS_TOGGLE_DELAY (4 SECONDS)
#define POCKET_EQUIP_DELAY (1 SECONDS)
GLOBAL_LIST_INIT(strippable_human_items, create_strippable_list(list(
/datum/strippable_item/mob_item_slot/head,
/datum/strippable_item/mob_item_slot/back,
/datum/strippable_item/mob_item_slot/mask,
/datum/strippable_item/mob_item_slot/neck,
/datum/strippable_item/mob_item_slot/eyes,
/datum/strippable_item/mob_item_slot/ears,
/datum/strippable_item/mob_item_slot/jumpsuit,
/datum/strippable_item/mob_item_slot/suit,
/datum/strippable_item/mob_item_slot/gloves,
/datum/strippable_item/mob_item_slot/feet,
/datum/strippable_item/mob_item_slot/suit_storage,
/datum/strippable_item/mob_item_slot/id,
/datum/strippable_item/mob_item_slot/belt,
/datum/strippable_item/mob_item_slot/pocket/left,
/datum/strippable_item/mob_item_slot/pocket/right,
/datum/strippable_item/hand/left,
/datum/strippable_item/hand/right,
/datum/strippable_item/mob_item_slot/handcuffs,
/datum/strippable_item/mob_item_slot/legcuffs,
)))
/mob/living/carbon/human/proc/should_strip(mob/user)
if (user.pulling != src || user.grab_state != GRAB_AGGRESSIVE)
return TRUE
if (ishuman(user))
var/mob/living/carbon/human/human_user = user
return !human_user.can_be_firemanned(src)
return TRUE
/datum/strippable_item/mob_item_slot/eyes
key = STRIPPABLE_ITEM_EYES
item_slot = SLOT_GLASSES
/datum/strippable_item/mob_item_slot/ears
key = STRIPPABLE_ITEM_EARS
item_slot = SLOT_EARS
/datum/strippable_item/mob_item_slot/jumpsuit
key = STRIPPABLE_ITEM_JUMPSUIT
item_slot = SLOT_W_UNIFORM
/datum/strippable_item/mob_item_slot/jumpsuit/get_alternate_action(atom/source, mob/user)
if(..() == FALSE)
return null
var/obj/item/clothing/under/jumpsuit = get_item(source)
if (!istype(jumpsuit))
return null
return jumpsuit?.can_adjust ? "adjust_jumpsuit" : null
/datum/strippable_item/mob_item_slot/jumpsuit/alternate_action(atom/source, mob/user)
if (!..())
return null
var/obj/item/clothing/under/jumpsuit = get_item(source)
if (!istype(jumpsuit))
return null
to_chat(source, "<span class='notice'>[user] is trying to adjust your [jumpsuit.name].")
if (!do_mob(user, source, jumpsuit.strip_delay * 0.5, ignorehelditem = TRUE))
return
to_chat(source, "<span class='notice'>[user] successfully adjusted your [jumpsuit.name].")
jumpsuit.toggle_jumpsuit_adjust()
if (!ismob(source))
return null
var/mob/mob_source = source
mob_source.update_inv_w_uniform()
mob_source.update_body()
return TRUE
/datum/strippable_item/mob_item_slot/suit
key = STRIPPABLE_ITEM_SUIT
item_slot = SLOT_WEAR_SUIT
/datum/strippable_item/mob_item_slot/suit/get_alternate_action(atom/source, mob/user)
if(..() == FALSE)
return null
var/obj/item/clothing/suit/space/hardsuit/suit = get_item(source)
if(istype(suit))
if(!suit.helmettype)
return null
return suit?.suittoggled ? "disable_helmet" : "enable_helmet"
return null
/datum/strippable_item/mob_item_slot/suit/alternate_action(mob/living/carbon/human/source, mob/user)
if(!..())
return null
if(ishuman(source))
var/obj/item/clothing/suit/space/hardsuit/hardsuit = get_item(source)
var/obj/item/clothing/head/helmet/space/hardsuit/hardsuit_head = hardsuit.helmet
source.visible_message("<span class='danger'>[user] tries to [hardsuit.suittoggled ? "retract" : "extend"] [source]'s helmet.</span>", \
"<span class='userdanger'>[user] tries to [hardsuit.suittoggled ? "retract" : "extend"] [source]'s helmet.</span>", \
target = user, target_message = "<span class='danger'>You try to [hardsuit.suittoggled ? "retract" : "extend"] [source]'s helmet.</span>")
if(!do_mob(user, source, hardsuit_head ? hardsuit_head.strip_delay : POCKET_STRIP_DELAY, ignorehelditem = TRUE))
return null
if((source.head != hardsuit_head) && source.head)
return null
if(hardsuit.ToggleHelmet(FALSE))
source.visible_message("<span class='danger'>[user] [hardsuit_head ? "retract" : "extend"] [source]'s helmet</span>", \
"<span class='userdanger'>[user] [hardsuit_head ? "retract" : "extend"] [source]'s helmet</span>", \
target = user, target_message = "<span class='danger'>You [hardsuit_head ? "retract" : "extend"] [source]'s helmet.</span>")
return TRUE
/datum/strippable_item/mob_item_slot/gloves
key = STRIPPABLE_ITEM_GLOVES
item_slot = SLOT_GLOVES
/datum/strippable_item/mob_item_slot/feet
key = STRIPPABLE_ITEM_FEET
item_slot = SLOT_SHOES
/datum/strippable_item/mob_item_slot/feet/get_alternate_action(atom/source, mob/user)
if(..() == FALSE)
return null
var/obj/item/clothing/shoes/shoes = get_item(source)
if (!istype(shoes) || !shoes.can_be_tied)
return null
switch (shoes.tied)
if (SHOES_UNTIED)
return "knot"
if (SHOES_TIED)
return "untie"
if (SHOES_KNOTTED)
return "unknot"
/datum/strippable_item/mob_item_slot/feet/alternate_action(atom/source, mob/user)
if(!..())
return null
var/obj/item/clothing/shoes/shoes = get_item(source)
if (!istype(shoes))
return null
shoes.handle_tying(user)
return TRUE
/datum/strippable_item/mob_item_slot/suit_storage
key = STRIPPABLE_ITEM_SUIT_STORAGE
item_slot = SLOT_S_STORE
/datum/strippable_item/mob_item_slot/suit_storage/get_alternate_action(atom/source, mob/user)
if(..() == FALSE)
return null
return get_strippable_alternate_action_internals(get_item(source), source)
/datum/strippable_item/mob_item_slot/suit_storage/alternate_action(atom/source, mob/user)
if (!..())
return null
return strippable_alternate_action_internals(get_item(source), source, user)
/datum/strippable_item/mob_item_slot/id
key = STRIPPABLE_ITEM_ID
item_slot = SLOT_WEAR_ID
/datum/strippable_item/mob_item_slot/belt
key = STRIPPABLE_ITEM_BELT
item_slot = SLOT_BELT
/datum/strippable_item/mob_item_slot/belt/get_alternate_action(atom/source, mob/user)
if(..() == FALSE)
return null
return get_strippable_alternate_action_internals(get_item(source), source)
/datum/strippable_item/mob_item_slot/belt/alternate_action(atom/source, mob/user)
if (!..())
return null
return strippable_alternate_action_internals(get_item(source), source, user)
/datum/strippable_item/mob_item_slot/pocket
/// Which pocket we're referencing. Used for visible text.
var/pocket_side
/datum/strippable_item/mob_item_slot/pocket/get_obscuring(atom/source)
return isnull(get_item(source)) \
? STRIPPABLE_OBSCURING_NONE \
: STRIPPABLE_OBSCURING_HIDDEN
/datum/strippable_item/mob_item_slot/pocket/get_equip_delay(obj/item/equipping)
return POCKET_EQUIP_DELAY
/datum/strippable_item/mob_item_slot/pocket/start_equip(atom/source, obj/item/equipping, mob/user)
. = ..()
if (!.)
warn_owner(source)
/datum/strippable_item/mob_item_slot/pocket/start_unequip(atom/source, mob/user)
var/obj/item/item = get_item(source)
if (isnull(item))
return FALSE
to_chat(user, span_notice("You try to empty [source]'s [pocket_side] pocket."))
var/log_message = "[key_name(source)] is being pickpocketed of [item] by [key_name(user)] ([pocket_side])"
user.log_message(log_message, LOG_ATTACK, color="red")
source.log_message(log_message, LOG_VICTIM, color="red", log_globally=FALSE)
item.add_fingerprint(source)
var/result = start_unequip_mob(item, source, user, POCKET_STRIP_DELAY)
if (!result)
warn_owner(source)
return result
/datum/strippable_item/mob_item_slot/pocket/proc/warn_owner(atom/owner)
to_chat(owner, span_warning("You feel your [pocket_side] pocket being fumbled with!"))
/datum/strippable_item/mob_item_slot/pocket/left
key = STRIPPABLE_ITEM_LPOCKET
item_slot = SLOT_L_STORE
pocket_side = "left"
/datum/strippable_item/mob_item_slot/pocket/right
key = STRIPPABLE_ITEM_RPOCKET
item_slot = SLOT_R_STORE
pocket_side = "right"
/proc/get_strippable_alternate_action_internals(obj/item/item, atom/source)
if (!iscarbon(source))
return null
var/mob/living/carbon/carbon_source = source
var/obj/item/clothing/mask
var/internals = FALSE
for(mask in GET_INTERNAL_SLOTS(carbon_source))
if(istype(mask, /obj/item/clothing/mask))
var/obj/item/clothing/mask/M = mask
if(M.mask_adjusted)
if(M.adjustmask(carbon_source))
internals = TRUE
else
internals = TRUE
if((mask.clothing_flags & ALLOWINTERNALS))
internals = TRUE
if(carbon_source.getorganslot(ORGAN_SLOT_BREATHING_TUBE))
internals = TRUE
if (internals && istype(item, /obj/item/tank))
return isnull(carbon_source.internal) ? "enable_internals" : "disable_internals"
/proc/strippable_alternate_action_internals(obj/item/item, atom/source, mob/user)
var/obj/item/tank/tank = item
if (!istype(tank))
return null
var/mob/living/carbon/carbon_source = source
if (!istype(carbon_source))
return null
var/obj/item/clothing/mask
var/internals = FALSE
for(mask in GET_INTERNAL_SLOTS(carbon_source))
if(istype(mask, /obj/item/clothing/mask))
var/obj/item/clothing/mask/M = mask
if(M.mask_adjusted)
if(M.adjustmask(carbon_source))
internals = TRUE
else
internals = TRUE
if((mask.clothing_flags & ALLOWINTERNALS))
internals = TRUE
if(!internals)
return null
carbon_source.visible_message(
span_danger("[user] tries to [isnull(carbon_source.internal) ? "open": "close"] the valve on [source]'s [item.name]."),
span_userdanger("[user] tries to [isnull(carbon_source.internal) ? "open": "close"] the valve on your [item.name]."),
ignored_mobs = user,
)
to_chat(user, span_notice("You try to [isnull(carbon_source.internal) ? "open": "close"] the valve on [source]'s [item.name]..."))
if(!do_mob(user, carbon_source, INTERNALS_TOGGLE_DELAY, ignorehelditem = TRUE))
return null
if(carbon_source.internal)
carbon_source.internal = null
// This isn't meant to be FALSE, it correlates to the icon's name.
carbon_source.update_internals_hud_icon(0)
else if (!QDELETED(item))
if(internals || carbon_source.getorganslot(ORGAN_SLOT_BREATHING_TUBE))
carbon_source.internal = item
carbon_source.update_internals_hud_icon(1)
carbon_source.visible_message(
span_danger("[user] [isnull(carbon_source.internal) ? "closes": "opens"] the valve on [source]'s [item.name]."),
span_userdanger("[user] [isnull(carbon_source.internal) ? "closes": "opens"] the valve on your [item.name]."),
ignored_mobs = user,
)
to_chat(user, span_notice("You [isnull(carbon_source.internal) ? "close" : "open"] the valve on [source]'s [item.name]."))
return TRUE
#undef INTERNALS_TOGGLE_DELAY
#undef POCKET_EQUIP_DELAY
+2 -4
View File
@@ -573,9 +573,6 @@ GLOBAL_LIST_INIT(ballmer_windows_me_msg, list("Yo man, what if, we like, uh, put
if(druggy)
adjust_drugginess(-1)
if(drunkenness)
drunkenness = max(drunkenness-1,0)
if(silent)
silent = max(silent-1, 0)
@@ -583,7 +580,7 @@ GLOBAL_LIST_INIT(ballmer_windows_me_msg, list("Yo man, what if, we like, uh, put
handle_hallucinations()
if(drunkenness)
drunkenness = max(drunkenness - (drunkenness * 0.04), 0)
drunkenness *= 0.96
if(drunkenness >= 6)
SEND_SIGNAL(src, COMSIG_ADD_MOOD_EVENT, "drunk", /datum/mood_event/drunk)
if(prob(25))
@@ -598,6 +595,7 @@ GLOBAL_LIST_INIT(ballmer_windows_me_msg, list("Yo man, what if, we like, uh, put
SEND_SIGNAL(src, COMSIG_CLEAR_MOOD_EVENT, "drunk")
clear_alert("drunk")
sound_environment_override = SOUND_ENVIRONMENT_NONE
drunkenness = max(drunkenness - 0.2, 0)
if(mind && (mind.assigned_role == "Scientist" || mind.assigned_role == "Research Director"))
if(SSresearch.science_tech)
@@ -16,6 +16,17 @@
/obj/item/bodypart/r_arm/monkey, /obj/item/bodypart/r_leg/monkey, /obj/item/bodypart/l_leg/monkey)
hud_type = /datum/hud/monkey
GLOBAL_LIST_INIT(strippable_monkey_items, create_strippable_list(list(
/datum/strippable_item/mob_item_slot/head,
/datum/strippable_item/mob_item_slot/back,
/datum/strippable_item/mob_item_slot/mask,
/datum/strippable_item/mob_item_slot/neck,
/datum/strippable_item/hand/left,
/datum/strippable_item/hand/right,
/datum/strippable_item/mob_item_slot/handcuffs,
/datum/strippable_item/mob_item_slot/legcuffs,
)))
/mob/living/carbon/monkey/Initialize(mapload, cubespawned=FALSE, mob/spawner)
add_verb(src, /mob/living/proc/mob_sleep)
add_verb(src, /mob/living/proc/lay_down)
@@ -47,6 +58,7 @@
. = ..()
AddElement(/datum/element/mob_holder, worn_state = "monkey", inv_slots = ITEM_SLOT_HEAD)
AddComponent(/datum/component/footstep, FOOTSTEP_MOB_BAREFOOT, 1, 2)
AddElement(/datum/element/strippable, GLOB.strippable_monkey_items)
/mob/living/carbon/monkey/Destroy()
-7
View File
@@ -935,13 +935,6 @@
what.forceMove(drop_location())
log_combat(src, who, "stripped [what] off")
if(Adjacent(who)) //update inventory window
who.show_inv(src)
else
src << browse(null,"window=mob[REF(who)]")
who.update_equipment_speed_mods() // Updates speed in case stripped speed affecting item
// The src mob is trying to place an item on someone
// Override if a certain mob should be behave differently when placing items (can't, for example)
/mob/living/stripPanelEquip(obj/item/what, mob/who, where)
+1 -1
View File
@@ -297,7 +297,7 @@ GLOBAL_LIST_INIT(department_radio_keys, list(
AM.Hear(rendered, src, message_language, message, null, spans, message_mode, source)
SEND_GLOBAL_SIGNAL(COMSIG_GLOB_LIVING_SAY_SPECIAL, src, message)
if(!eavesdrop_range && say_test(message) == "2") // Yell hook
if(client && !eavesdrop_range && say_test(message) == "2") // Yell hook
process_yelling(listening, rendered, src, message_language, message, spans, message_mode, source)
//speech bubble
@@ -24,6 +24,7 @@
. = ..()
AddElement(/datum/element/wuv, "yaps happily!", EMOTE_AUDIBLE, /datum/mood_event/pet_animal, "growls!", EMOTE_AUDIBLE)
AddElement(/datum/element/mob_holder, held_icon)
AddElement(/datum/element/strippable, GLOB.strippable_corgi_items)
//Corgis and pugs are now under one dog subtype
@@ -104,18 +105,175 @@
..(gibbed)
regenerate_icons()
/mob/living/simple_animal/pet/dog/corgi/show_inv(mob/user)
if(!user.canUseTopic(src, BE_CLOSE, FALSE, NO_TK))
GLOBAL_LIST_INIT(strippable_corgi_items, create_strippable_list(list(
/datum/strippable_item/corgi_head,
/datum/strippable_item/corgi_back,
/datum/strippable_item/corgi_collar,
/datum/strippable_item/corgi_id,
)))
/datum/strippable_item/corgi_head
key = STRIPPABLE_ITEM_HEAD
/datum/strippable_item/corgi_head/get_item(atom/source)
var/mob/living/simple_animal/pet/dog/corgi/corgi_source = source
if (!istype(corgi_source))
return
user.set_machine(src)
var/dat = "<div align='center'><b>Inventory of [name]</b></div><p>"
dat += "<br><B>Head:</B> <A href='?src=[REF(src)];[inventory_head ? "remove_inv=head'>[inventory_head]" : "add_inv=head'>Nothing"]</A>"
dat += "<br><B>Back:</B> <A href='?src=[REF(src)];[inventory_back ? "remove_inv=back'>[inventory_back]" : "add_inv=back'>Nothing"]</A>"
dat += "<br><B>Collar:</B> <A href='?src=[REF(src)];[pcollar ? "remove_inv=collar'>[pcollar]" : "add_inv=collar'>Nothing"]</A>"
return corgi_source.inventory_head
user << browse(dat, "window=mob[REF(src)];size=325x500")
onclose(user, "mob[REF(src)]")
/datum/strippable_item/corgi_head/finish_equip(atom/source, obj/item/equipping, mob/user)
if(!..())
return FALSE
var/mob/living/simple_animal/pet/dog/corgi/corgi_source = source
if (!istype(corgi_source))
return FALSE
corgi_source.place_on_head(equipping, user)
/datum/strippable_item/corgi_head/finish_unequip(atom/source, mob/user)
..()
var/mob/living/simple_animal/pet/dog/corgi/corgi_source = source
if (!istype(corgi_source))
return
finish_unequip_mob(corgi_source.inventory_head, corgi_source, user)
corgi_source.inventory_head = null
corgi_source.update_corgi_fluff()
corgi_source.regenerate_icons()
/datum/strippable_item/corgi_back
key = STRIPPABLE_ITEM_BACK
/datum/strippable_item/corgi_back/get_item(atom/source)
var/mob/living/simple_animal/pet/dog/corgi/corgi_source = source
if (!istype(corgi_source))
return
return corgi_source.inventory_back
/datum/strippable_item/corgi_back/try_equip(atom/source, obj/item/equipping, mob/user)
. = ..()
if (!.)
return FALSE
if (!ispath(equipping.dog_fashion, /datum/dog_fashion/back))
to_chat(user, "<span class='warning'>You set [equipping] on [source]'s back, but it falls off!</span>")
equipping.forceMove(source.drop_location())
if (prob(25))
step_rand(equipping)
dance_rotate(source, set_original_dir = TRUE)
return FALSE
return TRUE
/datum/strippable_item/corgi_back/finish_equip(atom/source, obj/item/equipping, mob/user)
if(!..())
return FALSE
var/mob/living/simple_animal/pet/dog/corgi/corgi_source = source
if (!istype(corgi_source))
return FALSE
equipping.forceMove(corgi_source)
corgi_source.inventory_back = equipping
corgi_source.update_corgi_fluff()
corgi_source.regenerate_icons()
/datum/strippable_item/corgi_back/finish_unequip(atom/source, mob/user)
..()
var/mob/living/simple_animal/pet/dog/corgi/corgi_source = source
if (!istype(corgi_source))
return
finish_unequip_mob(corgi_source.inventory_back, corgi_source, user)
corgi_source.inventory_back = null
corgi_source.update_corgi_fluff()
corgi_source.regenerate_icons()
/datum/strippable_item/corgi_collar
key = STRIPPABLE_ITEM_CORGI_COLLAR
/datum/strippable_item/corgi_collar/get_item(atom/source)
var/mob/living/simple_animal/pet/dog/corgi/corgi_source = source
if (!istype(corgi_source))
return
return corgi_source.pcollar
/datum/strippable_item/corgi_collar/try_equip(atom/source, obj/item/equipping, mob/user)
. = ..()
if (!.)
return FALSE
if (!istype(equipping, /obj/item/clothing/neck/petcollar))
to_chat(user, "<span class='warning'>That's not a collar.</span>")
return FALSE
return TRUE
/datum/strippable_item/corgi_collar/finish_equip(atom/source, obj/item/equipping, mob/user)
if(!..())
return FALSE
var/mob/living/simple_animal/pet/dog/corgi/corgi_source = source
if (!istype(corgi_source))
return FALSE
corgi_source.add_collar(equipping, user)
corgi_source.update_corgi_fluff()
/datum/strippable_item/corgi_collar/finish_unequip(atom/source, mob/user)
..()
var/mob/living/simple_animal/pet/dog/corgi/corgi_source = source
if (!istype(corgi_source))
return
finish_unequip_mob(corgi_source.pcollar, corgi_source, user)
corgi_source.pcollar = null
corgi_source.update_corgi_fluff()
corgi_source.regenerate_icons()
/datum/strippable_item/corgi_id
key = STRIPPABLE_ITEM_ID
/datum/strippable_item/corgi_id/get_item(atom/source)
var/mob/living/simple_animal/pet/dog/corgi/corgi_source = source
if (!istype(corgi_source))
return
return corgi_source.access_card
/datum/strippable_item/corgi_id/try_equip(atom/source, obj/item/equipping, mob/user)
. = ..()
if (!.)
return FALSE
if (!istype(equipping, /obj/item/card/id))
to_chat(user, "<span class='warning'>You can't pin [equipping] to [source]!</span>")
return FALSE
return TRUE
/datum/strippable_item/corgi_id/finish_equip(atom/source, obj/item/equipping, mob/user)
if(!..())
return FALSE
var/mob/living/simple_animal/pet/dog/corgi/corgi_source = source
if (!istype(corgi_source))
return FALSE
equipping.forceMove(source)
corgi_source.access_card = equipping
/datum/strippable_item/corgi_id/finish_unequip(atom/source, mob/user)
..()
var/mob/living/simple_animal/pet/dog/corgi/corgi_source = source
if (!istype(corgi_source))
return
finish_unequip_mob(corgi_source.access_card, corgi_source, user)
corgi_source.access_card = null
corgi_source.update_corgi_fluff()
corgi_source.regenerate_icons()
/mob/living/simple_animal/pet/dog/corgi/getarmor(def_zone, type)
var/armorval = 0
@@ -158,114 +316,12 @@
..()
update_corgi_fluff()
/mob/living/simple_animal/pet/dog/corgi/Topic(href, href_list)
if(!(iscarbon(usr) || iscyborg(usr)) || !usr.canUseTopic(src, BE_CLOSE, FALSE, NO_TK))
usr << browse(null, "window=mob[REF(src)]")
usr.unset_machine()
return
//Removing from inventory
if(href_list["remove_inv"])
var/remove_from = href_list["remove_inv"]
switch(remove_from)
if(BODY_ZONE_HEAD)
if(inventory_head)
usr.put_in_hands(inventory_head)
inventory_head = null
update_corgi_fluff()
regenerate_icons()
else
to_chat(usr, "<span class='danger'>There is nothing to remove from its [remove_from].</span>")
return
if("back")
if(inventory_back)
usr.put_in_hands(inventory_back)
inventory_back = null
update_corgi_fluff()
regenerate_icons()
else
to_chat(usr, "<span class='danger'>There is nothing to remove from its [remove_from].</span>")
return
if("collar")
if(pcollar)
usr.put_in_hands(pcollar)
pcollar = null
update_corgi_fluff()
regenerate_icons()
show_inv(usr)
//Adding things to inventory
else if(href_list["add_inv"])
var/add_to = href_list["add_inv"]
switch(add_to)
if("collar")
var/obj/item/clothing/neck/petcollar/P = usr.get_active_held_item()
if(!istype(P))
to_chat(usr,"<span class='warning'>That's not a collar.</span>")
return
add_collar(P, usr)
update_corgi_fluff()
if(BODY_ZONE_HEAD)
place_on_head(usr.get_active_held_item(),usr)
if("back")
if(inventory_back)
to_chat(usr, "<span class='warning'>It's already wearing something!</span>")
return
else
var/obj/item/item_to_add = usr.get_active_held_item()
if(!item_to_add)
usr.visible_message("[usr] pets [src].","<span class='notice'>You rest your hand on [src]'s back for a moment.</span>")
return
if(!usr.temporarilyRemoveItemFromInventory(item_to_add))
to_chat(usr, "<span class='warning'>\The [item_to_add] is stuck to your hand, you cannot put it on [src]'s back!</span>")
return
if(istype(item_to_add, /obj/item/grenade/plastic)) // last thing he ever wears, I guess
item_to_add.afterattack(src,usr,1)
return
//The objects that corgis can wear on their backs.
var/allowed = FALSE
if(ispath(item_to_add.dog_fashion, /datum/dog_fashion/back))
allowed = TRUE
if(!allowed)
to_chat(usr, "<span class='warning'>You set [item_to_add] on [src]'s back, but it falls off!</span>")
item_to_add.forceMove(drop_location())
if(prob(25))
step_rand(item_to_add)
for(var/i in list(1,2,4,8,4,8,4,dir))
setDir(i)
sleep(1)
return
item_to_add.forceMove(src)
src.inventory_back = item_to_add
update_corgi_fluff()
regenerate_icons()
show_inv(usr)
else
return ..()
//Corgis are supposed to be simpler, so only a select few objects can actually be put
//to be compatible with them. The objects are below.
//Many hats added, Some will probably be removed, just want to see which ones are popular.
// > some will probably be removed
/mob/living/simple_animal/pet/dog/corgi/proc/place_on_head(obj/item/item_to_add, mob/user)
if(istype(item_to_add, /obj/item/grenade/plastic)) // last thing he ever wears, I guess
INVOKE_ASYNC(item_to_add, /obj/item.proc/afterattack, src, user, 1)
return
if(inventory_head)
if(user)
to_chat(user, "<span class='warning'>You can't put more than one hat on [src]!</span>")
@@ -303,9 +359,7 @@
item_to_add.forceMove(drop_location())
if(prob(25))
step_rand(item_to_add)
for(var/i in list(1,2,4,8,4,8,4,dir))
setDir(i)
sleep(1)
dance_rotate(src, set_original_dir = TRUE)
return valid
+89 -76
View File
@@ -124,6 +124,9 @@
/mob/living/simple_animal/parrot/proc/toggle_mode,
/mob/living/simple_animal/parrot/proc/perch_mob_player))
/mob/living/simple_animal/parrot/ComponentInitialize()
. = ..()
AddElement(/datum/element/strippable, GLOB.strippable_parrot_items)
/mob/living/simple_animal/parrot/examine(mob/user)
. = ..()
@@ -183,91 +186,101 @@
return 0
/*
* Inventory
*/
/mob/living/simple_animal/parrot/show_inv(mob/user)
user.set_machine(src)
GLOBAL_LIST_INIT(strippable_parrot_items, create_strippable_list(list(
/datum/strippable_item/parrot_headset,
)))
var/dat = "<div align='center'><b>Inventory of [name]</b></div><p>"
dat += "<br><B>Headset:</B> <A href='?src=[REF(src)];[ears ? "remove_inv=ears'>[ears]" : "add_inv=ears'>Nothing"]</A>"
/datum/strippable_item/parrot_headset
key = STRIPPABLE_ITEM_PARROT_HEADSET
user << browse(dat, "window=mob[REF(src)];size=325x500")
onclose(user, "window=mob[REF(src)]")
/datum/strippable_item/parrot_headset/get_item(atom/source)
var/mob/living/simple_animal/parrot/parrot_source = source
return istype(parrot_source) ? parrot_source.ears : null
/datum/strippable_item/parrot_headset/try_equip(atom/source, obj/item/equipping, mob/user)
. = ..()
if (!.)
return FALSE
/mob/living/simple_animal/parrot/Topic(href, href_list)
if(!(iscarbon(usr) || iscyborg(usr)) || !usr.canUseTopic(src, BE_CLOSE, FALSE, NO_TK))
usr << browse(null, "window=mob[REF(src)]")
usr.unset_machine()
if (!istype(equipping, /obj/item/radio/headset))
to_chat(user, "<span class='warning'>[equipping] won't fit!</span>")
return FALSE
return TRUE
// There is no delay for putting a headset on a parrot.
/datum/strippable_item/parrot_headset/start_equip(atom/source, obj/item/equipping, mob/user)
if(get_obscuring(source) == STRIPPABLE_OBSCURING_COMPLETELY)
return FALSE
return TRUE
/datum/strippable_item/parrot_headset/finish_equip(atom/source, obj/item/equipping, mob/user)
if(!..())
return FALSE
var/obj/item/radio/headset/radio = equipping
if (!istype(radio))
return FALSE
var/mob/living/simple_animal/parrot/parrot_source = source
if (!istype(parrot_source))
return FALSE
if (!user.transferItemToLoc(radio, source))
return FALSE
parrot_source.ears = radio
to_chat(user, "<span class='notice'>You fit [radio] onto [source].</span>")
parrot_source.available_channels.Cut()
for (var/channel in radio.channels)
var/channel_to_add
switch (channel)
if (RADIO_CHANNEL_ENGINEERING)
channel_to_add = RADIO_TOKEN_ENGINEERING
if (RADIO_CHANNEL_COMMAND)
channel_to_add = RADIO_TOKEN_COMMAND
if (RADIO_CHANNEL_SECURITY)
channel_to_add = RADIO_TOKEN_SECURITY
if (RADIO_CHANNEL_SCIENCE)
channel_to_add = RADIO_TOKEN_SCIENCE
if (RADIO_CHANNEL_MEDICAL)
channel_to_add = RADIO_TOKEN_MEDICAL
if (RADIO_CHANNEL_SUPPLY)
channel_to_add = RADIO_TOKEN_SUPPLY
if (RADIO_CHANNEL_SERVICE)
channel_to_add = RADIO_TOKEN_SERVICE
if (channel_to_add)
parrot_source.available_channels += channel_to_add
if (radio.translate_binary)
parrot_source.available_channels.Add(MODE_TOKEN_BINARY)
/datum/strippable_item/parrot_headset/start_unequip(atom/source, mob/user)
. = ..()
if (!.)
return FALSE
var/mob/living/simple_animal/parrot/parrot_source = source
if (!istype(parrot_source))
return
//Removing from inventory
if(href_list["remove_inv"])
var/remove_from = href_list["remove_inv"]
switch(remove_from)
if("ears")
if(!ears)
to_chat(usr, "<span class='warning'>There is nothing to remove from its [remove_from]!</span>")
return
if(!stat)
say("[available_channels.len ? "[pick(available_channels)] " : null]BAWWWWWK LEAVE THE HEADSET BAWKKKKK!")
ears.forceMove(drop_location())
ears = null
for(var/possible_phrase in speak)
if(copytext_char(possible_phrase, 2, 3) in GLOB.department_radio_keys)
possible_phrase = copytext_char(possible_phrase, 3)
if (!parrot_source.stat)
parrot_source.say("[parrot_source.available_channels.len ? "[pick(parrot_source.available_channels)] " : null]BAWWWWWK LEAVE THE HEADSET BAWKKKKK!")
//Adding things to inventory
else if(href_list["add_inv"])
var/add_to = href_list["add_inv"]
if(!usr.get_active_held_item())
to_chat(usr, "<span class='warning'>You have nothing in your hand to put on its [add_to]!</span>")
return
switch(add_to)
if("ears")
if(ears)
to_chat(usr, "<span class='warning'>It's already wearing something!</span>")
return
else
var/obj/item/item_to_add = usr.get_active_held_item()
if(!item_to_add)
return
return TRUE
if( !istype(item_to_add, /obj/item/radio/headset) )
to_chat(usr, "<span class='warning'>This object won't fit!</span>")
return
var/obj/item/radio/headset/headset_to_add = item_to_add
if(!usr.transferItemToLoc(headset_to_add, src))
return
ears = headset_to_add
to_chat(usr, "<span class='notice'>You fit the headset onto [src].</span>")
clearlist(available_channels)
for(var/ch in headset_to_add.channels)
switch(ch)
if(RADIO_CHANNEL_ENGINEERING)
available_channels.Add(RADIO_TOKEN_ENGINEERING)
if(RADIO_CHANNEL_COMMAND)
available_channels.Add(RADIO_TOKEN_COMMAND)
if(RADIO_CHANNEL_SECURITY)
available_channels.Add(RADIO_TOKEN_SECURITY)
if(RADIO_CHANNEL_SCIENCE)
available_channels.Add(RADIO_TOKEN_SCIENCE)
if(RADIO_CHANNEL_MEDICAL)
available_channels.Add(RADIO_TOKEN_MEDICAL)
if(RADIO_CHANNEL_SUPPLY)
available_channels.Add(RADIO_TOKEN_SUPPLY)
if(RADIO_CHANNEL_SERVICE)
available_channels.Add(RADIO_TOKEN_SERVICE)
if(headset_to_add.translate_binary)
available_channels.Add(MODE_TOKEN_BINARY)
else
return ..()
/datum/strippable_item/parrot_headset/finish_unequip(atom/source, mob/user)
..()
var/mob/living/simple_animal/parrot/parrot_source = source
if (!istype(parrot_source))
return
finish_unequip_mob(parrot_source.ears, parrot_source, user)
parrot_source.ears = null
/*
* Attack responces
-19
View File
@@ -289,9 +289,6 @@
SEND_SIGNAL(src, COMSIG_MOB_RESET_PERSPECTIVE, A)
return TRUE
/mob/proc/show_inv(mob/user)
return
//view() but with a signal, to allow blacklisting some of the otherwise visible atoms.
/mob/proc/fov_view(dist = world.view)
. = view(dist, src)
@@ -508,10 +505,6 @@ GLOBAL_VAR_INIT(exploit_warn_spam_prevention, 0)
unset_machine()
src << browse(null, t1)
if(href_list["refresh"])
if(machine && in_range(src, usr))
show_inv(machine)
if(usr.canUseTopic(src, BE_CLOSE, NO_DEXTERY))
if(href_list["item"])
var/slot = text2num(href_list["item"])
@@ -528,12 +521,6 @@ GLOBAL_VAR_INIT(exploit_warn_spam_prevention, 0)
else
usr.stripPanelEquip(what,src,slot)
if(usr.machine == src)
if(Adjacent(usr))
show_inv(usr)
else
usr << browse(null,"window=mob[REF(src)]")
// The src mob is trying to strip an item from someone
// Defined in living.dm
/mob/proc/stripPanelUnequip(obj/item/what, mob/who)
@@ -555,12 +542,6 @@ GLOBAL_VAR_INIT(exploit_warn_spam_prevention, 0)
if(isAI(M))
return
/mob/MouseDrop_T(atom/dropping, atom/user)
. = ..()
if(ismob(dropping) && dropping != user)
var/mob/M = dropping
M.show_inv(user)
/mob/proc/is_muzzled()
return FALSE
+6 -7
View File
@@ -825,7 +825,7 @@
pH = REAGENT_NORMAL_PH
return 0
/datum/reagents/proc/reaction(atom/A, method = TOUCH, volume_modifier = 1, show_message = 1)
/datum/reagents/proc/reaction(atom/A, method = TOUCH, volume_modifier = 1, show_message = 1, from_gas = 0)
var/react_type
if(isliving(A))
react_type = "LIVING"
@@ -849,7 +849,7 @@
touch_protection = L.get_permeability_protection()
R.reaction_mob(A, method, R.volume * volume_modifier, show_message, touch_protection)
if("TURF")
R.reaction_turf(A, R.volume * volume_modifier, show_message)
R.reaction_turf(A, R.volume * volume_modifier, show_message, from_gas)
if("OBJ")
R.reaction_obj(A, R.volume * volume_modifier, show_message)
@@ -859,17 +859,16 @@
return FALSE
//Returns the average specific heat for all reagents currently in this holder.
/datum/reagents/proc/specific_heat()
/datum/reagents/proc/heat_capacity()
. = 0
var/cached_amount = total_volume //cache amount
var/list/cached_reagents = reagent_list //cache reagents
for(var/I in cached_reagents)
var/datum/reagent/R = I
. += R.specific_heat * (R.volume / cached_amount)
. += R.specific_heat * R.volume
/datum/reagents/proc/adjust_thermal_energy(J, min_temp = 2.7, max_temp = 1000)
var/S = specific_heat()
chem_temp = clamp(chem_temp + (J / (S * total_volume)), min_temp, max_temp)
var/S = heat_capacity()
chem_temp = clamp(chem_temp + (J / S), min_temp, max_temp)
if(istype(my_atom, /obj/item/reagent_containers))
var/obj/item/reagent_containers/RC = my_atom
RC.temp_check()
@@ -390,11 +390,11 @@
var/datum/reagent/R = GLOB.chemical_reagents_list[reagent]
if(R)
var/state = "Unknown"
if(initial(R.reagent_state) == 1)
if(initial(R.reagent_state) == SOLID)
state = "Solid"
else if(initial(R.reagent_state) == 2)
else if(initial(R.reagent_state) == LIQUID)
state = "Liquid"
else if(initial(R.reagent_state) == 3)
else if(initial(R.reagent_state) == GAS)
state = "Gas"
var/const/P = 3 //The number of seconds between life ticks
var/T = initial(R.metabolization_rate) * (60 / P)
@@ -53,10 +53,10 @@
return
beaker = new /obj/item/reagent_containers/glass/beaker/bluespace(src)
visible_message("<span class='notice'>[src] dispenses a bluespace beaker.</span>")
if("amount")
var/input = text2num(params["amount"])
if("synth_amount")
var/input = text2num(params["synth_amount"])
if(input)
amount = input
amount = max(input, 0)
update_icon()
/obj/machinery/chem_dispenser/chem_synthesizer/proc/find_reagent(input)
+58 -3
View File
@@ -53,6 +53,10 @@ GLOBAL_LIST_INIT(name2reagent, build_name2reagent())
var/chemical_flags = REAGENT_ORGANIC_PROCESS // See fermi/readme.dm REAGENT_DEAD_PROCESS, REAGENT_DONOTSPLIT, REAGENT_ONLYINVERSE, REAGENT_ONMOBMERGE, REAGENT_INVISIBLE, REAGENT_FORCEONNEW, REAGENT_SNEAKYNAME, REAGENT_ORGANIC_PROCESS, REAGENT_ROBOTIC_PROCESS
var/value = REAGENT_VALUE_NONE //How much does it sell for in cargo?
var/datum/material/material //are we made of material?
var/gas = null //do we have an associated gas? (expects a string, not a datum typepath!)
var/boiling_point = null // point at which this gas boils; if null, will never boil (and thus not become a gas)
var/condensation_amount = 1
var/molarity = 5 // How many units per mole of this reagent. Technically this is INVERSE molarity, but hey.
/datum/reagent/New()
. = ..()
@@ -77,10 +81,23 @@ GLOBAL_LIST_INIT(name2reagent, build_name2reagent())
return 1
/datum/reagent/proc/reaction_obj(obj/O, volume)
return
if(O && volume && boiling_point)
var/temp = holder ? holder.chem_temp : T20C
if(temp > boiling_point)
O.atmos_spawn_air("[get_gas()]=[volume/molarity];TEMP=[temp]")
/datum/reagent/proc/reaction_turf(turf/T, volume)
return
/datum/reagent/proc/reaction_turf(turf/T, volume, show_message, from_gas)
if(!from_gas && boiling_point)
var/temp = holder?.chem_temp
if(!temp)
if(isopenturf(T))
var/turf/open/O = T
var/datum/gas_mixture/air = O.return_air()
temp = air.return_temperature()
else
temp = T20C
if(temp > boiling_point)
T.atmos_spawn_air("[get_gas()]=[volume/molarity];TEMP=[temp]")
/datum/reagent/proc/on_mob_life(mob/living/carbon/M)
current_cycle++
@@ -235,6 +252,44 @@ GLOBAL_LIST_INIT(name2reagent, build_name2reagent())
return rs.Join(" | ")
/datum/reagent/proc/define_gas()
if(reagent_state == SOLID)
return null // doesn't make that much sense
var/list/cached_reactions = GLOB.chemical_reactions_list
for(var/reaction in cached_reactions[src.type])
var/datum/chemical_reaction/C = reaction
if(!istype(C))
continue
if(C.required_reagents.len < 2) // no reagents that react on their own
return null
var/datum/gas/G = new
G.id = "[src.type]"
G.name = name
G.specific_heat = specific_heat / 10
G.color = color
G.breath_reagent = src.type
G.group = GAS_GROUP_CHEMICALS
return G
/datum/reagent/proc/create_gas()
var/datum/gas/G = define_gas()
if(istype(G)) // if this reagent should never be a gas, define_gas may return null
GLOB.gas_data.add_gas(G)
var/datum/gas_reaction/condensation/condensation_reaction = new(src) // did you know? you can totally just add new reactions at runtime. it's allowed
SSair.add_reaction(condensation_reaction)
return G
/datum/reagent/proc/get_gas()
if(gas)
return gas
else
var/datum/auxgm/cached_gas_data = GLOB.gas_data
. = "[src.type]"
if(!(. in cached_gas_data.ids))
create_gas()
//For easy bloodsucker disgusting and blood removal
/datum/reagent/proc/disgust_bloodsucker(mob/living/carbon/C, disgust, blood_change, blood_puke = TRUE, force)
if(AmBloodsucker(C))
@@ -14,6 +14,7 @@
taste_description = "alcohol"
var/boozepwr = 65 //Higher numbers equal higher hardness, higher hardness equals more intense alcohol poisoning
pH = 7.33
boiling_point = 351.38
value = REAGENT_VALUE_VERY_COMMON //don't bother tweaking all drinks values, way too many can easily be done roundstart or with an upgraded dispenser.
/*
@@ -85,6 +86,31 @@ All effects don't start immediately, but rather get worse over time; the rate is
// +10% success propability on each step, useful while operating in less-than-perfect conditions
return ..()
/datum/reagent/consumable/ethanol/define_gas() // So that all alcohols have the same gas, i.e. "ethanol"
var/datum/gas/G = new
G.id = GAS_ETHANOL
G.name = "Ethanol"
G.enthalpy = -234800
G.specific_heat = 38
G.fire_products = list(GAS_CO2 = 1, GAS_H2O = 1.5)
G.fire_burn_rate = 1 / 3
G.fire_temperature = FIRE_MINIMUM_TEMPERATURE_TO_EXIST
G.color = "#404030"
G.breath_reagent = /datum/reagent/consumable/ethanol
G.group = GAS_GROUP_CHEMICALS
return G
/datum/reagent/consumable/ethanol/get_gas()
var/datum/auxgm/cached_gas_data = GLOB.gas_data
. = GAS_ETHANOL
if(!(. in cached_gas_data.ids))
var/datum/gas/G = define_gas()
if(istype(G))
cached_gas_data.add_gas(G)
else // this codepath should probably not happen at all, since we never use get_gas() on anything with no boiling point
return null
/datum/reagent/consumable/ethanol/beer
name = "Beer"
description = "An alcoholic beverage brewed since ancient times on Old Earth. Still popular today."
@@ -909,20 +909,11 @@
description = "A colorless, odorless gas. Grows on trees but is still pretty valuable."
reagent_state = GAS
color = "#808080" // rgb: 128, 128, 128
gas = GAS_O2
boiling_point = 90.188
taste_mult = 0 // oderless and tasteless
pH = 9.2//It's acutally a huge range and very dependant on the chemistry but pH is basically a made up var in it's implementation anyways
/datum/reagent/oxygen/reaction_obj(obj/O, reac_volume)
if((!O) || (!reac_volume))
return 0
var/temp = holder ? holder.chem_temp : T20C
O.atmos_spawn_air("o2=[reac_volume/2];TEMP=[temp]")
/datum/reagent/oxygen/reaction_turf(turf/open/T, reac_volume)
if(istype(T))
var/temp = holder ? holder.chem_temp : T20C
T.atmos_spawn_air("o2=[reac_volume/2];TEMP=[temp]")
return
molarity = 2
/datum/reagent/copper
name = "Copper"
@@ -943,26 +934,18 @@
name = "Nitrogen"
description = "A colorless, odorless, tasteless gas. A simple asphyxiant that can silently displace vital oxygen."
reagent_state = GAS
gas = GAS_N2
boiling_point = 77.355
color = "#808080" // rgb: 128, 128, 128
taste_mult = 0
/datum/reagent/nitrogen/reaction_obj(obj/O, reac_volume)
if((!O) || (!reac_volume))
return 0
var/temp = holder ? holder.chem_temp : T20C
O.atmos_spawn_air("n2=[reac_volume/2];TEMP=[temp]")
/datum/reagent/nitrogen/reaction_turf(turf/open/T, reac_volume)
if(istype(T))
var/temp = holder ? holder.chem_temp : T20C
T.atmos_spawn_air("n2=[reac_volume/2];TEMP=[temp]")
return
molarity = 2
/datum/reagent/hydrogen
name = "Hydrogen"
description = "A colorless, odorless, nonmetallic, tasteless, highly combustible diatomic gas."
reagent_state = GAS
gas = GAS_HYDROGEN
boiling_point = 20.271
color = "#808080" // rgb: 128, 128, 128
taste_mult = 0
pH = 0.1//Now I'm stuck in a trap of my own design. Maybe I should make -ve pHes? (not 0 so I don't get div/0 errors)
@@ -1015,9 +998,10 @@
name = "Chlorine"
description = "A pale yellow gas that's well known as an oxidizer. While it forms many harmless molecules in its elemental form it is far from harmless."
reagent_state = GAS
color = "#808080" // rgb: 128, 128, 128
color = "#c0c0a0" // rgb: 192, 192, 160
taste_description = "chlorine"
pH = 7.4
boiling_point = 239.11
// You're an idiot for thinking that one of the most corrosive and deadly gasses would be beneficial
/datum/reagent/chlorine/on_hydroponics_apply(obj/item/seeds/myseed, datum/reagents/chems, obj/machinery/hydroponics/mytray, mob/user)
@@ -1291,7 +1275,15 @@
glass_name = "glass of welder fuel"
glass_desc = "Unless you're an industrial tool, this is probably not safe for consumption."
pH = 4
boiling_point = 400
/datum/reagent/fuel/define_gas()
var/datum/gas/G = ..()
G.enthalpy = 227400
G.fire_burn_rate = 2 / 5
G.fire_products = list(GAS_CO2 = 2, GAS_H2O = 1)
G.fire_temperature = T0C+300
return G
/datum/reagent/fuel/reaction_mob(mob/living/M, method=TOUCH, reac_volume)//Splashing people with welding fuel to make them easy to ignite!
if(method == TOUCH || method == VAPOR)
@@ -1309,6 +1301,7 @@
description = "A compound used to clean things. Now with 50% more sodium hypochlorite!"
color = "#A5F0EE" // rgb: 165, 240, 238
taste_description = "sourness"
boiling_point = T0C+50
pH = 5.5
/datum/reagent/space_cleaner/reaction_obj(obj/O, reac_volume)
@@ -1321,6 +1314,7 @@
O.clean_blood()
/datum/reagent/space_cleaner/reaction_turf(turf/T, reac_volume)
..()
if(reac_volume >= 1)
T.remove_atom_colour(WASHABLE_COLOUR_PRIORITY)
SEND_SIGNAL(T, COMSIG_COMPONENT_CLEAN_ACT, CLEAN_WEAK)
@@ -1488,6 +1482,7 @@
name = "Ammonia"
description = "A caustic substance commonly used in fertilizer or household cleaners."
reagent_state = GAS
gas = GAS_AMMONIA
color = "#404030" // rgb: 64, 64, 48
taste_description = "mordant"
pH = 11.6
@@ -1506,8 +1501,17 @@
description = "A secondary amine, mildly corrosive."
color = "#604030" // rgb: 96, 64, 48
taste_description = "iron"
boiling_point = 328
pH = 12
/datum/reagent/diethylamine/define_gas()
var/datum/gas/G = ..()
G.fire_burn_rate = 1 / 6
G.fire_products = list(GAS_H2O = 4, GAS_AMMONIA = 1, GAS_CO2 = 4)
G.enthalpy = -131000
G.fire_temperature = FIRE_MINIMUM_TEMPERATURE_TO_EXIST
return G
// This is more bad ass, and pests get hurt by the corrosive nature of it, not the plant. The new trade off is it culls stability.
/datum/reagent/diethylamine/on_hydroponics_apply(obj/item/seeds/myseed, datum/reagents/chems, obj/machinery/hydroponics/mytray, mob/user)
. = ..()
@@ -1524,40 +1528,23 @@
description = "A gas commonly produced by burning carbon fuels. You're constantly producing this in your lungs."
color = "#B0B0B0" // rgb : 192, 192, 192
taste_description = "something unknowable"
boiling_point = 195.68 // technically sublimation, not boiling, but same deal
molarity = 5
gas = GAS_CO2
pH = 6
/datum/reagent/carbondioxide/reaction_obj(obj/O, reac_volume)
if((!O) || (!reac_volume))
return 0
var/temp = holder ? holder.chem_temp : T20C
O.atmos_spawn_air("co2=[reac_volume/5];TEMP=[temp]")
/datum/reagent/carbondioxide/reaction_turf(turf/open/T, reac_volume)
if(istype(T))
var/temp = holder ? holder.chem_temp : T20C
T.atmos_spawn_air("co2=[reac_volume/5];TEMP=[temp]")
return
/datum/reagent/nitrous_oxide
name = "Nitrous Oxide"
description = "A potent oxidizer used as fuel in rockets and as an anaesthetic during surgery."
reagent_state = LIQUID
metabolization_rate = 1.5 * REAGENTS_METABOLISM
color = "#808080"
boiling_point = 184.67
molarity = 5
gas = GAS_NITROUS
taste_description = "sweetness"
pH = 5.8
/datum/reagent/nitrous_oxide/reaction_obj(obj/O, reac_volume)
if((!O) || (!reac_volume))
return 0
var/temp = holder ? holder.chem_temp : T20C
O.atmos_spawn_air("n2o=[reac_volume/5];TEMP=[temp]")
/datum/reagent/nitrous_oxide/reaction_turf(turf/open/T, reac_volume)
if(istype(T))
var/temp = holder ? holder.chem_temp : T20C
T.atmos_spawn_air("n2o=[reac_volume/5];TEMP=[temp]")
/datum/reagent/nitrous_oxide/reaction_mob(mob/living/M, method=TOUCH, reac_volume)
if(method == VAPOR)
M.drowsyness += max(round(reac_volume, 1), 2)
@@ -1576,9 +1563,11 @@
name = "Stimulum"
description = "An unstable experimental gas that greatly increases the energy of those that inhale it"
reagent_state = GAS
gas = GAS_STIMULUM
metabolization_rate = 1.5 * REAGENTS_METABOLISM
chemical_flags = REAGENT_ALL_PROCESS
color = "E1A116"
boiling_point = 150
taste_description = "sourness"
value = REAGENT_VALUE_EXCEPTIONAL
@@ -1602,9 +1591,11 @@
name = "Nitryl"
description = "A highly reactive gas that makes you feel faster"
reagent_state = GAS
gas = GAS_NITRYL
metabolization_rate = REAGENTS_METABOLISM
color = "90560B"
color = "#90560B"
taste_description = "burning"
boiling_point = 294.3
pH = 2
value = REAGENT_VALUE_VERY_RARE
@@ -1811,6 +1802,8 @@
reagent_state = LIQUID
color = "#b37740"
taste_description = "chemicals"
gas = GAS_BROMINE
boiling_point = 332
pH = 7.8
/datum/reagent/phenol
@@ -2482,6 +2475,7 @@
var/decal_path = /obj/effect/decal/cleanable/semen
/datum/reagent/consumable/semen/reaction_turf(turf/T, reac_volume)
..()
if(!istype(T))
return
if(reac_volume < 10)
@@ -47,6 +47,10 @@
metabolization_rate = 4
chemical_flags = REAGENT_ALL_PROCESS
taste_description = "burning"
/* no gaseous CLF3 until i can think of a good way to get it to burn that doesn't destroy matter in mysterious ways
boiling_point = 289.4
*/
condensation_amount = 2
value = REAGENT_VALUE_COMMON
/datum/reagent/clf3/on_mob_life(mob/living/carbon/M)
@@ -84,6 +88,12 @@
if(!locate(/obj/effect/hotspot) in M.loc)
new /obj/effect/hotspot(M.loc)
/datum/reagent/clf3/define_gas()
var/datum/gas/G = ..()
G.enthalpy = -163200
G.oxidation_temperature = T0C - 50
return G
/datum/reagent/sorium
name = "Sorium"
description = "Sends everything flying from the detonation point."
@@ -152,8 +162,17 @@
reagent_state = LIQUID
color = "#FA00AF"
taste_description = "burning"
boiling_point = T20C-10
value = REAGENT_VALUE_UNCOMMON
/datum/reagent/phlogiston/define_gas()
var/datum/gas/G = ..()
G.enthalpy = FIRE_PLASMA_ENERGY_RELEASED / 100
G.fire_products = list(GAS_O2 = 0.25, GAS_METHANE = 0.75) // meanwhile this is just magic
G.fire_burn_rate = 1
G.fire_temperature = T20C+1
return G
/datum/reagent/phlogiston/reaction_mob(mob/living/M, method=TOUCH, reac_volume)
M.adjust_fire_stacks(1)
var/burndmg = max(0.3*M.fire_stacks, 0.3)
@@ -288,6 +307,9 @@
taste_description = "the inside of a fire extinguisher"
value = REAGENT_VALUE_UNCOMMON
/datum/reagent/firefighting_foam/define_gas()
return null
/datum/reagent/firefighting_foam/reaction_turf(turf/open/T, reac_volume)
if (!istype(T))
return
+1 -1
View File
@@ -248,7 +248,7 @@
for(var/gas in breath.get_gases())
if(gas in breath_reagents)
var/datum/reagent/R = breath_reagents[gas]
H.reagents.add_reagent(R, PP(breath,gas))
H.reagents.add_reagent(R, breath.get_moles(gas) * initial(R.molarity))
mole_adjustments[gas] = (gas in mole_adjustments) ? mole_adjustments[gas] - breath.get_moles(gas) : -breath.get_moles(gas)
for(var/gas in mole_adjustments)
+5 -4
View File
@@ -1,6 +1,7 @@
/datum/unit_test/reactions/Run()
for(var/datum/gas_reaction/G in SSair.gas_reactions)
var/test_info = G.test()
if(!test_info["success"])
var/message = test_info["message"]
Fail("Gas reaction [G.name] is failing its unit test with the following message: [message]")
if(!G.exclude)
var/test_info = G.test()
if(!test_info["success"])
var/message = test_info["message"]
Fail("Gas reaction [G.name] is failing its unit test with the following message: [message]")
+3
View File
@@ -503,3 +503,6 @@ PAI_CUSTOM_HOLOFORMS
## Enables monstermos/"equalization" step in atmos.
# ATMOS_EQUALIZATION_ENABLED
## Do station renames from the station charter require admin approval to pass, as opposed to autoapproving if not denied.
STATION_NAME_NEEDS_APPROVAL
+1 -1
View File
@@ -21,7 +21,7 @@ export SPACEMAN_DMM_VERSION=suite-1.7
export PYTHON_VERSION=3.6.8
# Auxmos git tag
export AUXMOS_VERSION=v0.2.3
export AUXMOS_VERSION=v0.3.0
# Extools git tag
export EXTOOLS_VERSION=v0.0.7
+86 -100
View File
@@ -50,6 +50,92 @@
-->
<div class="commit sansserif">
<h2 class="date">10 January 2022</h2>
<h3 class="author">Linzolle updated:</h3>
<ul class="changes bgimages16">
<li class="bugfix">bloodsplatter effects no longer white in certain cases</li>
<li class="bugfix">the blood in the BDM ruin is no longer white</li>
</ul>
<h3 class="author">Putnam3145 updated:</h3>
<ul class="changes bgimages16">
<li class="bugfix">Alcohol works again</li>
</ul>
<h2 class="date">07 January 2022</h2>
<h3 class="author">MrJWhit updated:</h3>
<ul class="changes bgimages16">
<li class="rscadd">Adds an airlock between atmos and engineering on omega.</li>
</ul>
<h2 class="date">04 January 2022</h2>
<h3 class="author">Hatterhat updated:</h3>
<ul class="changes bgimages16">
<li class="imageadd">Jumpboots now have a mining sprite. Alt-click, as usual, to change 'em.</li>
</ul>
<h3 class="author">MrJWhit updated:</h3>
<ul class="changes bgimages16">
<li class="rscadd">Adds pipes to the SM to make omega better</li>
<li class="bugfix">Various omega fixes</li>
</ul>
<h3 class="author">Putnam3145 updated:</h3>
<ul class="changes bgimages16">
<li class="rscadd">Hydrogen gas (no way to get yet)</li>
<li class="rscadd">Gas groups, such as...</li>
<li class="rscadd">Chemical gases, starting with ethanol, bromine, diethylamine, ammonia, phlogiston</li>
<li class="rscadd">Bromine gas (can make it by tossing hot bromine on the ground OR by burning methyl bromide)</li>
<li class="rscadd">Ammonia gas (toss hot ammonia on the ground OR burn diethylamine)</li>
<li class="rscdel">Snowflake trit/plasma fires fires tweak: Generic fires are now more accurate energy-wise tweak: Water vapor condensation no longer happens below 40 C tweak: Methyl bromide now burns properly</li>
<li class="balance">Massive fusion nerf</li>
<li class="balance">Due to the removal of snowflake trit fires, trit fires are much, much less hot</li>
<li class="balance">Due to the previous, bombs are now easier to reach 50,000 points on (2 : 1 plasma : oxy at 160 kelvins cold side should be fine)</li>
</ul>
<h2 class="date">03 January 2022</h2>
<h3 class="author">TripleShades updated:</h3>
<ul class="changes bgimages16">
<li class="rscadd">(Meta) Floodlight to Atmospherics tweak: (Meta) Atmospherics Entryway layout change tweak: (Meta) Atmospherics Monitoring room layout tweak tweak: (Meta) Atmospherics Supply Line room airlock location change</li>
<li class="bugfix">(Meta) Incinerator Access airlock now has the correct access</li>
</ul>
<h2 class="date">02 January 2022</h2>
<h3 class="author">DeltaFire15 updated:</h3>
<ul class="changes bgimages16">
<li class="admin">Station names now require admin approval instead of autoaccepting.</li>
</ul>
<h3 class="author">Putnam3145 updated:</h3>
<ul class="changes bgimages16">
<li class="bugfix">Bluespace pipes</li>
</ul>
<h2 class="date">31 December 2021</h2>
<h3 class="author">SandPoot updated:</h3>
<ul class="changes bgimages16">
<li class="bugfix">You also no longer get every animation sprite and direction sprite of items on the menus.</li>
</ul>
<h2 class="date">29 December 2021</h2>
<h3 class="author">TripleShades updated:</h3>
<ul class="changes bgimages16">
<li class="rscadd">(Festive Station) Fixes</li>
<li class="rscadd">Readds the cold to Festive Station tweak: (Festive Station) Fixes</li>
<li class="rscadd">(Pubby) Cautery??? I think this is leftover but nobody has touched Pubby since me so it's fine probably</li>
</ul>
<h2 class="date">23 December 2021</h2>
<h3 class="author">Putnam3145 updated:</h3>
<ul class="changes bgimages16">
<li class="bugfix">Atmos group processing heuristic no longer does opposite of intent</li>
</ul>
<h2 class="date">21 December 2021</h2>
<h3 class="author">ShizCalev updated:</h3>
<ul class="changes bgimages16">
<li class="bugfix">Fixed an issue where you were able to remove flashlights/bayonets that were supposed to be permanently attached to a gun.</li>
<li class="bugfix">Fixed an issue where you were unable to remove flashlights & bayonets from certain weapons.</li>
<li class="bugfix">Fixed a potential issue where adding a flashlight to your helmet would've caused you to lose other action buttons.</li>
<li class="bugfix">Fixed a issue where guns with multiple action buttons would break all but one of those action buttons. tweak: If you have both a bayonet and a flashlight attached to your gun, you'll now be given a prompt on which you'd like to remove when using a screwdriver on it. tweak: Hacking a firing pin out of a gun is no longer done via a crafting menu - you can now do it by simply holding the gun in your hand and clicking it with a welder/screwdriver/wirecutters.</li>
</ul>
<h2 class="date">17 December 2021</h2>
<h3 class="author">DeltaFire15 updated:</h3>
<ul class="changes bgimages16">
@@ -320,106 +406,6 @@
<ul class="changes bgimages16">
<li class="rscadd">Crayon precision mode.</li>
</ul>
<h2 class="date">08 November 2021</h2>
<h3 class="author">timothyteakettle updated:</h3>
<ul class="changes bgimages16">
<li class="bugfix">fixes party pod sprite</li>
<li class="bugfix">fixes red panda head marking</li>
</ul>
<h2 class="date">06 November 2021</h2>
<h3 class="author">Putnam3145 updated:</h3>
<ul class="changes bgimages16">
<li class="bugfix">Ashwalkers should no longer suffocate on lavaland (and hypothetical other future problems)</li>
<li class="bugfix">A gas mix with 0 oxygen should now properly suffocate you (or 0 plasma, for ashwalkers)</li>
</ul>
<h2 class="date">05 November 2021</h2>
<h3 class="author">keronshb updated:</h3>
<ul class="changes bgimages16">
<li class="balance">removes required enemies</li>
<li class="balance">Lowers assassination threat threshold</li>
</ul>
<h2 class="date">31 October 2021</h2>
<h3 class="author">DeltaFire15 updated:</h3>
<ul class="changes bgimages16">
<li class="bugfix">You can now drag things over prone people again.</li>
</ul>
<h3 class="author">DrPainis updated:</h3>
<ul class="changes bgimages16">
<li class="bugfix">Walking no longer makes you fat.</li>
</ul>
<h3 class="author">keronshb updated:</h3>
<ul class="changes bgimages16">
<li class="balance">Christmas trees are now indestructible</li>
</ul>
<h2 class="date">30 October 2021</h2>
<h3 class="author">keronshb updated:</h3>
<ul class="changes bgimages16">
<li class="balance">Jacq can't burn in the cremator anymore</li>
<li class="balance">Jacq also can't be cheesed off station</li>
<li class="balance">Barth also cannot be destroyed</li>
</ul>
<h2 class="date">28 October 2021</h2>
<h3 class="author">Hatterhat updated:</h3>
<ul class="changes bgimages16">
<li class="rscadd">Proto-kinetic gauntlets! Less straight damage, extra damage on backstabs, slows Lavaland fauna on counterhit. tweak: The glaive kit has been renamed to the premium kinetic melee kit, and now has a voucher for either a glaive or gauntlets.</li>
<li class="rscadd">NanoTrasen is rolling out a prototype Autoloom, hidden behind Botanical Engineering. It only processes cotton and logs. Despite its visual similarity to the recycler, it is entirely tamperproof.</li>
</ul>
<h3 class="author">Linzolle updated:</h3>
<ul class="changes bgimages16">
<li class="bugfix">plasmamen now spawn in their proper outfit in the ghostcafe</li>
</ul>
<h3 class="author">Putnam3145 updated:</h3>
<ul class="changes bgimages16">
<li class="rscdel">Removed minesweeper</li>
</ul>
<h3 class="author">keronshb updated:</h3>
<ul class="changes bgimages16">
<li class="balance">-40 wound bonus for DSword</li>
<li class="balance">-20 Wound bonus for Hyper Eu</li>
<li class="bugfix">Fixes hyper eu's slowdown when it's not wielded</li>
</ul>
<h2 class="date">26 October 2021</h2>
<h3 class="author">WanderingFox95 updated:</h3>
<ul class="changes bgimages16">
<li class="rscadd">bone anvils and bone ingots</li>
<li class="imageadd">bone anvil sprites</li>
</ul>
<h2 class="date">25 October 2021</h2>
<h3 class="author">Putnam3145 updated:</h3>
<ul class="changes bgimages16">
<li class="rscadd">Vent pumps can now be set to siphoning via the air alarm UI</li>
</ul>
<h3 class="author">keronshb updated:</h3>
<ul class="changes bgimages16">
<li class="balance">10k pirate spending money</li>
</ul>
<h2 class="date">22 October 2021</h2>
<h3 class="author">Putnam3145 updated:</h3>
<ul class="changes bgimages16">
<li class="bugfix">Ashwalker lungs more aggressively attempt to be safe on lavaland</li>
</ul>
<h3 class="author">WanderingFox95 updated:</h3>
<ul class="changes bgimages16">
<li class="bugfix">fixed the wielded sprites not showing up properly.</li>
<li class="bugfix">fixed a runtime in the bark box vendor</li>
<li class="imageadd">added a missing tennis ball sprite</li>
</ul>
<h2 class="date">20 October 2021</h2>
<h3 class="author">Putnam3145 updated:</h3>
<ul class="changes bgimages16">
<li class="bugfix">Removed a panic from auxmos</li>
<li class="bugfix">Properly implemented hysteresis on heat exchanger processing</li>
</ul>
</div>
<b>GoonStation 13 Development Team</b>
+69
View File
@@ -30403,3 +30403,72 @@ DO NOT EDIT THIS FILE BY HAND! AUTOMATICALLY GENERATED BY ss13_genchangelog.py.
- bugfix: The time for admins to cancel events is 30 seconds again.
SandPoot:
- bugfix: Fixes assembly holders.
2021-12-21:
ShizCalev:
- bugfix: Fixed an issue where you were able to remove flashlights/bayonets that
were supposed to be permanently attached to a gun.
- bugfix: Fixed an issue where you were unable to remove flashlights & bayonets
from certain weapons.
- bugfix: Fixed a potential issue where adding a flashlight to your helmet would've
caused you to lose other action buttons.
- bugfix: 'Fixed a issue where guns with multiple action buttons would break all
but one of those action buttons. tweak: If you have both a bayonet and a flashlight
attached to your gun, you''ll now be given a prompt on which you''d like to
remove when using a screwdriver on it. tweak: Hacking a firing pin out of a
gun is no longer done via a crafting menu - you can now do it by simply holding
the gun in your hand and clicking it with a welder/screwdriver/wirecutters.'
2021-12-23:
Putnam3145:
- bugfix: Atmos group processing heuristic no longer does opposite of intent
2021-12-29:
TripleShades:
- rscadd: (Festive Station) Fixes
- rscadd: 'Readds the cold to Festive Station tweak: (Festive Station) Fixes'
- rscadd: (Pubby) Cautery??? I think this is leftover but nobody has touched Pubby
since me so it's fine probably
2021-12-31:
SandPoot:
- bugfix: You also no longer get every animation sprite and direction sprite of
items on the menus.
2022-01-02:
DeltaFire15:
- admin: Station names now require admin approval instead of autoaccepting.
Putnam3145:
- bugfix: Bluespace pipes
2022-01-03:
TripleShades:
- rscadd: '(Meta) Floodlight to Atmospherics tweak: (Meta) Atmospherics Entryway
layout change tweak: (Meta) Atmospherics Monitoring room layout tweak tweak:
(Meta) Atmospherics Supply Line room airlock location change'
- bugfix: (Meta) Incinerator Access airlock now has the correct access
2022-01-04:
Hatterhat:
- imageadd: Jumpboots now have a mining sprite. Alt-click, as usual, to change 'em.
MrJWhit:
- rscadd: Adds pipes to the SM to make omega better
- bugfix: Various omega fixes
Putnam3145:
- rscadd: Hydrogen gas (no way to get yet)
- rscadd: Gas groups, such as...
- rscadd: Chemical gases, starting with ethanol, bromine, diethylamine, ammonia,
phlogiston
- rscadd: Bromine gas (can make it by tossing hot bromine on the ground OR by burning
methyl bromide)
- rscadd: Ammonia gas (toss hot ammonia on the ground OR burn diethylamine)
- rscdel: 'Snowflake trit/plasma fires fires tweak: Generic fires are now more accurate
energy-wise tweak: Water vapor condensation no longer happens below 40 C tweak:
Methyl bromide now burns properly'
- balance: Massive fusion nerf
- balance: Due to the removal of snowflake trit fires, trit fires are much, much
less hot
- balance: 'Due to the previous, bombs are now easier to reach 50,000 points on
(2 : 1 plasma : oxy at 160 kelvins cold side should be fine)'
2022-01-07:
MrJWhit:
- rscadd: Adds an airlock between atmos and engineering on omega.
2022-01-10:
Linzolle:
- bugfix: bloodsplatter effects no longer white in certain cases
- bugfix: the blood in the BDM ruin is no longer white
Putnam3145:
- bugfix: Alcohol works again
@@ -1,9 +0,0 @@
author: "ShizCalev"
delete-after: True
changes:
- bugfix: "Fixed an issue where you were able to remove flashlights/bayonets that were supposed to be permanently attached to a gun."
- bugfix: "Fixed an issue where you were unable to remove flashlights & bayonets from certain weapons."
- bugfix: "Fixed a potential issue where adding a flashlight to your helmet would've caused you to lose other action buttons."
- bugfix: "Fixed a issue where guns with multiple action buttons would break all but one of those action buttons.
tweak: If you have both a bayonet and a flashlight attached to your gun, you'll now be given a prompt on which you'd like to remove when using a screwdriver on it.
tweak: Hacking a firing pin out of a gun is no longer done via a crafting menu - you can now do it by simply holding the gun in your hand and clicking it with a welder/screwdriver/wirecutters."
Binary file not shown.

Before

Width:  |  Height:  |  Size: 30 KiB

After

Width:  |  Height:  |  Size: 30 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 23 KiB

After

Width:  |  Height:  |  Size: 24 KiB

+28 -1
View File
@@ -9,7 +9,9 @@
light_color = "#00111a" //The light can technically cycle on a timer worldwide, but no daynight cycle.
baseturfs = /turf/open/floor/grass/snow/edina //If we explode or die somehow, we just make more! Ahahaha!!!
tiled_dirt = 0 //NO TILESMOOTHING DIRT/DIRT SPAWNS OR SOME SHIT
initial_gas_mix = OPENTURF_DEFAULT_ATMOS //DO NOT FREEZE EVERYONE TO DEATH ON CHRISTMAS
//initial_gas_mix = OPENTURF_DEFAULT_ATMOS //DO NOT FREEZE EVERYONE TO DEATH ON CHRISTMAS
initial_gas_mix = FESTIVE_ATMOS
planetary_atmos = 1 //Uses new!!! planetmos wow!!! maybe?
//lets people build
/turf/open/floor/grass/snow/edina/attackby(obj/item/C, mob/user, params)
@@ -38,6 +40,13 @@
icon_state = "unsmooth"
smooth = SMOOTH_MORE | SMOOTH_BORDER
canSmoothWith = list(/turf/open/floor/festive/cobblestone)
initial_gas_mix = FESTIVE_ATMOS
planetary_atmos = 1
/turf/open/floor/festive/cobblestone/safe //this is literally cobblestone but safe for inside use because I don't want to fuck with aesthetics
baseturfs = /turf/open/floor/festive/cobblestone/safe
initial_gas_mix = OPENTURF_DEFAULT_ATMOS
planetary_atmos = FALSE
/turf/open/floor/festive/sidewalk
name = "sidewalk"
@@ -46,6 +55,8 @@
icon_state = "unsmooth"
smooth = SMOOTH_MORE | SMOOTH_BORDER
canSmoothWith = list(/turf/open/floor/festive/sidewalk)
initial_gas_mix = FESTIVE_ATMOS
planetary_atmos = 1
/turf/open/floor/festive/alleyway
name = "alleyway bricks"
@@ -54,6 +65,13 @@
icon_state = "unsmooth"
smooth = SMOOTH_MORE | SMOOTH_BORDER
canSmoothWith = list(/turf/open/floor/festive/alleyway, /turf/open/floor/festive/white_alleyway)
initial_gas_mix = FESTIVE_ATMOS
planetary_atmos = 1
/turf/open/floor/festive/alleyway/safe //this is literally alleyway but safe for inside use because I don't want to fuck with aesthetics
baseturfs = /turf/open/floor/festive/alleyway/safe
initial_gas_mix = OPENTURF_DEFAULT_ATMOS
planetary_atmos = FALSE
/turf/open/floor/festive/white_alleyway
name = "alleyway bricks"
@@ -62,6 +80,8 @@
icon_state = "unsmooth"
smooth = SMOOTH_MORE | SMOOTH_BORDER
canSmoothWith = list(/turf/open/floor/festive/alleyway, /turf/open/floor/festive/white_alleyway)
initial_gas_mix = FESTIVE_ATMOS
planetary_atmos = 1
/turf/open/floor/festive/trainplatform
name = "trainplatform"
@@ -70,6 +90,13 @@
icon_state = "unsmooth"
smooth = SMOOTH_MORE | SMOOTH_BORDER
canSmoothWith = list(/turf/open/floor/festive/trainplatform)
initial_gas_mix = FESTIVE_ATMOS
planetary_atmos = 1
/turf/open/floor/festive/trainplatform/safe //this is literally train platform but safe for inside use because I don't want to remap the strip club
baseturfs = /turf/open/floor/festive/trainplatform/safe
initial_gas_mix = OPENTURF_DEFAULT_ATMOS
planetary_atmos = FALSE
/turf/open/floor/festive/stairs/stairsnorth
name = "stairs north"
+4
View File
@@ -117,6 +117,7 @@
#include "code\__DEFINES\stat.dm"
#include "code\__DEFINES\stat_tracking.dm"
#include "code\__DEFINES\status_effects.dm"
#include "code\__DEFINES\strippable.dm"
#include "code\__DEFINES\subsystems.dm"
#include "code\__DEFINES\text.dm"
#include "code\__DEFINES\tgs.config.dm"
@@ -662,6 +663,7 @@
#include "code\datums\elements\snail_crawl.dm"
#include "code\datums\elements\spellcasting.dm"
#include "code\datums\elements\squish.dm"
#include "code\datums\elements\strippable.dm"
#include "code\datums\elements\swimming.dm"
#include "code\datums\elements\sword_point.dm"
#include "code\datums\elements\tactical.dm"
@@ -2618,6 +2620,7 @@
#include "code\modules\mob\living\carbon\carbon_defines.dm"
#include "code\modules\mob\living\carbon\carbon_movement.dm"
#include "code\modules\mob\living\carbon\carbon_sprint.dm"
#include "code\modules\mob\living\carbon\carbon_stripping.dm"
#include "code\modules\mob\living\carbon\damage_procs.dm"
#include "code\modules\mob\living\carbon\death.dm"
#include "code\modules\mob\living\carbon\emote.dm"
@@ -2673,6 +2676,7 @@
#include "code\modules\mob\living\carbon\human\human_helpers.dm"
#include "code\modules\mob\living\carbon\human\human_mobility.dm"
#include "code\modules\mob\living\carbon\human\human_movement.dm"
#include "code\modules\mob\living\carbon\human\human_stripping.dm"
#include "code\modules\mob\living\carbon\human\inventory.dm"
#include "code\modules\mob\living\carbon\human\life.dm"
#include "code\modules\mob\living\carbon\human\login.dm"
@@ -1 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 437.4 434.4" style="enable-background:new 0 0 437.4 434.4" xml:space="preserve"><style>.st0{fill:none;stroke:#000;stroke-width:.57;stroke-miterlimit:10}</style><g id="Layer_1"><path class="st0" d="m41.18 306.18 84.43 84.43-19.53 20.8c-11.26 11.99-26.1 17.98-40.93 17.98-14.84 0-29.68-5.99-40.93-17.98-22.52-23.97-22.52-63.2 0-87.18l16.96-18.05zm310.48-156.3L139.65 375.65l-84.43-84.43L269.8 62.7c22.51-23.98 59.34-23.98 81.86 0 22.51 23.97 22.51 63.2 0 87.18z"/><path d="M426.11 88.46c-24.57-26.71-49.15-53.42-73.72-80.13a93.834 93.834 0 0 1-30.93-4.39c-6.96 7.41-6.96 19.53 0 26.94l79.36 84.52c6.96 7.41 18.34 7.41 25.29 0 6.96-7.41 6.96-19.53 0-26.94zM248.07 35.83c13.66 16.01 4.9 48.19-19.57 71.87-24.47 23.68-33.21 29.27-46.88 13.25-13.66-16.01-2.33-26.15 22.14-49.83 24.47-23.67 30.65-51.3 44.31-35.29z" style="stroke-width:.5;fill:none;stroke:#000;stroke-miterlimit:10"/><path class="st0" d="m139.93 375.93-.28-.28m-13.72 15.28-.32-.32"/><path transform="rotate(-45.001 211.427 209.932)" style="stroke:#000;stroke-width:18;stroke-miterlimit:10" d="M191.43-6.09h40v432.04h-40z"/></g></svg>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 437.4 434.4" style="enable-background:new 0 0 437.4 434.4" xml:space="preserve"><style>.st0{fill:none;stroke:#000;stroke-width:.57;stroke-miterlimit:10}</style><g id="Layer_1"><path class="st0" d="m41.18 306.18 84.43 84.43-19.53 20.8c-11.26 11.99-26.1 17.98-40.93 17.98-14.84 0-29.68-5.99-40.93-17.98-22.52-23.97-22.52-63.2 0-87.18l16.96-18.05zm310.48-156.3L139.65 375.65l-84.43-84.43L269.8 62.7c22.51-23.98 59.34-23.98 81.86 0 22.51 23.97 22.51 63.2 0 87.18z"/><path d="M426.11 88.46c-24.57-26.71-49.15-53.42-73.72-80.13a93.834 93.834 0 0 1-30.93-4.39c-6.96 7.41-6.96 19.53 0 26.94l79.36 84.52c6.96 7.41 18.34 7.41 25.29 0 6.96-7.41 6.96-19.53 0-26.94zM248.07 35.83c13.66 16.01 4.9 48.19-19.57 71.87-24.47 23.68-33.21 29.27-46.88 13.25-13.66-16.01-2.33-26.15 22.14-49.83 24.47-23.67 30.65-51.3 44.31-35.29z" style="stroke-width:.5;fill:none;stroke:#000;stroke-miterlimit:10"/><path class="st0" d="m139.93 375.93-.28-.28m-13.72 15.28-.32-.32"/><path transform="rotate(-45.001 211.427 209.932)" style="stroke:#000;stroke-width:18;stroke-miterlimit:10" d="M191.43-6.09h40v432.04h-40z"/></g></svg>

Before

Width:  |  Height:  |  Size: 1.1 KiB

After

Width:  |  Height:  |  Size: 1.1 KiB

@@ -33,8 +33,8 @@ export const ChemDebugSynthesizer = (props, context) => {
maxValue={beakerMaxVolume}
step={1}
stepPixelSize={2}
onChange={(e, value) => act('amount', {
amount: value,
onChange={(e, value) => act('synth_amount', {
synth_amount: value,
})} />
<Button
icon="plus"
+167 -15
View File
@@ -8,6 +8,9 @@ import { Window } from "../layouts";
const ROWS = 5;
const COLUMNS = 6;
const ROWS_LONG = 4;
const COLUMNS_LONG = 11;
const BUTTON_DIMENSIONS = "50px";
type GridSpotKey = string;
@@ -71,6 +74,14 @@ const ALTERNATE_ACTIONS: Record<string, AlternateAction> = {
icon: "tshirt",
text: "Adjust jumpsuit",
},
enable_helmet: {
icon: "toggle-off",
text: "Extend helmet",
},
disable_helmet: {
icon: "toggle-on",
text: "Retract helmet",
},
};
const SLOTS: Record<
@@ -209,6 +220,142 @@ const SLOTS: Record<
},
};
const SLOTS_LONG: Record<
string,
{
displayName: string;
gridSpot: GridSpotKey;
image?: string;
additionalComponent?: JSX.Element;
}
> = {
eyes: {
displayName: "eyewear",
gridSpot: getGridSpotKey([0, 0]),
image: "inventory-glasses.png",
},
head: {
displayName: "headwear",
gridSpot: getGridSpotKey([0, 1]),
image: "inventory-head.png",
},
neck: {
displayName: "neckwear",
gridSpot: getGridSpotKey([1, 0]),
image: "inventory-neck.png",
},
mask: {
displayName: "mask",
gridSpot: getGridSpotKey([1, 1]),
image: "inventory-mask.png",
},
corgi_collar: {
displayName: "collar",
gridSpot: getGridSpotKey([1, 1]),
image: "inventory-collar.png",
},
ears: {
displayName: "earwear",
gridSpot: getGridSpotKey([1, 2]),
image: "inventory-ears.png",
},
parrot_headset: {
displayName: "headset",
gridSpot: getGridSpotKey([1, 2]),
image: "inventory-ears.png",
},
jumpsuit: {
displayName: "uniform",
gridSpot: getGridSpotKey([2, 0]),
image: "inventory-uniform.png",
},
suit: {
displayName: "suit",
gridSpot: getGridSpotKey([2, 1]),
image: "inventory-suit.png",
},
gloves: {
displayName: "gloves",
gridSpot: getGridSpotKey([2, 2]),
image: "inventory-gloves.png",
},
handcuffs: {
displayName: "handcuffs",
gridSpot: getGridSpotKey([2, 8]),
},
shoes: {
displayName: "shoes",
gridSpot: getGridSpotKey([3, 1]),
image: "inventory-shoes.png",
},
legcuffs: {
displayName: "legcuffs",
gridSpot: getGridSpotKey([3, 2]),
},
suit_storage: {
displayName: "suit storage item",
gridSpot: getGridSpotKey([3, 3]),
image: "inventory-suit_storage.png",
},
id: {
displayName: "ID",
gridSpot: getGridSpotKey([3, 4]),
image: "inventory-id.png",
},
belt: {
displayName: "belt",
gridSpot: getGridSpotKey([3, 5]),
image: "inventory-belt.png",
},
back: {
displayName: "backpack",
gridSpot: getGridSpotKey([3, 6]),
image: "inventory-back.png",
},
right_hand: {
displayName: "right hand",
gridSpot: getGridSpotKey([3, 7]),
image: "inventory-hand_r.png",
additionalComponent: <CornerText align="left">R</CornerText>,
},
left_hand: {
displayName: "left hand",
gridSpot: getGridSpotKey([3, 8]),
image: "inventory-hand_l.png",
additionalComponent: <CornerText align="right">L</CornerText>,
},
left_pocket: {
displayName: "left pocket",
gridSpot: getGridSpotKey([3, 9]),
image: "inventory-pocket.png",
},
right_pocket: {
displayName: "right pocket",
gridSpot: getGridSpotKey([3, 10]),
image: "inventory-pocket.png",
},
};
enum ObscuringLevel {
Completely = 1,
Hidden = 2,
@@ -246,24 +393,35 @@ type StripMenuItem =
type StripMenuData = {
items: Record<keyof typeof SLOTS, StripMenuItem>;
name: string;
long_strip_menu: boolean;
};
export const StripMenu = (props, context) => {
const { act, data } = useBackend<StripMenuData>(context);
const gridSpots = new Map<GridSpotKey, string>();
for (const key of Object.keys(data.items)) {
gridSpots.set(SLOTS[key].gridSpot, key);
if (data.long_strip_menu) {
for (const key of Object.keys(data.items)) {
gridSpots.set(SLOTS_LONG[key].gridSpot, key);
}
} else {
for (const key of Object.keys(data.items)) {
gridSpots.set(SLOTS[key].gridSpot, key);
}
}
return (
<Window title={`Stripping ${data.name}`} width={400} height={400}>
<Window
title={`Stripping ${data.name}`}
width={data.long_strip_menu ? 620 : 400}
height={data.long_strip_menu ? 300 : 400}>
<Window.Content>
<Stack fill vertical>
{range(0, ROWS).map(row => (
{range(0, data.long_strip_menu ? ROWS_LONG : ROWS).map(row => (
<Stack.Item key={row}>
<Stack fill>
{range(0, COLUMNS).map(column => {
{range(0, data.long_strip_menu ? COLUMNS_LONG
: COLUMNS).map(column => {
const key = getGridSpotKey([row, column]);
const keyAtSpot = gridSpots.get(key);
@@ -290,7 +448,9 @@ export const StripMenu = (props, context) => {
if (item === null) {
tooltip = slot.displayName;
} else if ("name" in item) {
alternateAction = ALTERNATE_ACTIONS[item.alternate];
if (item.alternate) {
alternateAction = ALTERNATE_ACTIONS[item.alternate];
}
content = (
<Box
@@ -364,17 +524,9 @@ export const StripMenu = (props, context) => {
{slot.image && (
<Box
as="img"
className="centered-image"
src={resolveAsset(slot.image)}
opacity={0.7}
style={{
position: "absolute",
width: "32px",
height: "32px",
left: "50%",
top: "50%",
transform:
"translateX(-50%) translateY(-50%) scale(0.8)",
}}
/>
)}
@@ -0,0 +1,7 @@
.centered-image {
position: absolute;
height: 100%;
left: 50%;
top: 50%;
transform: translateX(-50%) translateY(-50%) scale(0.8);
}
+1
View File
@@ -11,6 +11,7 @@
// Atomic classes
@include meta.load-css('./atomic/candystripe.scss');
@include meta.load-css('./atomic/centered-image.scss');
@include meta.load-css('./atomic/color.scss');
@include meta.load-css('./atomic/debug-layout.scss');
@include meta.load-css('./atomic/links.scss');