Merge remote-tracking branch 'citadel/master' into combat_v7

This commit is contained in:
silicons
2021-06-07 16:47:11 -07:00
247 changed files with 7302 additions and 2875 deletions

12
.vscode/launch.json vendored Normal file
View File

@@ -0,0 +1,12 @@
{
"version": "0.2.0",
"configurations": [
{
"type": "byond",
"request": "launch",
"name": "Launch DreamSeeker",
"preLaunchTask": "Build All",
"dmb": "${workspaceFolder}/${command:CurrentDMB}"
}
]
}

18
.vscode/settings.json vendored
View File

@@ -6,8 +6,11 @@
"typescript.tsdk": "./tgui/.yarn/sdks/typescript/lib",
"typescript.enablePromptUseWorkspaceTsdk": true,
"search.exclude": {
"tgui/.yarn": true,
"tgui/.pnp.*": true
"**/.yarn": true,
"**/.pnp.*": true
},
"editor.codeActionsOnSave": {
"source.fixAll.eslint": true
},
"workbench.editorAssociations": [
{
@@ -17,5 +20,14 @@
],
"files.eol": "\n",
"gitlens.advanced.blame.customArguments": ["-w"],
"tgstationTestExplorer.project.resultsType": "json"
"tgstationTestExplorer.project.resultsType": "json",
"[javascript]": {
"editor.rulers": [80]
},
"[typescript]": {
"editor.rulers": [80]
},
"[scss]": {
"editor.rulers": [80]
}
}

55
.vscode/tasks.json vendored Normal file
View File

@@ -0,0 +1,55 @@
{
"version": "2.0.0",
"tasks": [
{
"type": "process",
"command": "tools/build/build",
"windows": {
"command": ".\\tools\\build\\build.bat"
},
"options": {
"env": {
"DM_EXE": "${config:dreammaker.byondPath}"
}
},
"problemMatcher": [
"$dreammaker",
"$tsc",
"$eslint-stylish"
],
"group": {
"kind": "build",
"isDefault": true
},
"dependsOn": "dm: reparse",
"label": "Build All"
},
{
"type": "dreammaker",
"dme": "tgstation.dme",
"problemMatcher": [
"$dreammaker"
],
"group": "build",
"label": "dm: build - tgstation.dme"
},
{
"type": "shell",
"command": "tgui/bin/tgui",
"windows": {
"command": ".\\tgui\\bin\\tgui.bat"
},
"problemMatcher": [
"$tsc",
"$eslint-stylish"
],
"group": "build",
"label": "tgui: build"
},
{
"command": "${command:dreammaker.reparse}",
"group": "build",
"label": "dm: reparse"
}
]
}

View File

@@ -499,10 +499,6 @@
/mob/living/simple_animal/hostile/alien,
/turf/open/floor/plating/asteroid/basalt/lava_land_surface,
/area/ruin/unpowered/xenonest)
"bD" = (
/obj/structure/alien/weeds,
/turf/template_noop,
/area/ruin/unpowered/xenonest)
"dE" = (
/obj/structure/alien/weeds,
/obj/structure/bed/nest,
@@ -1573,8 +1569,8 @@ aa
aa
aa
ac
bD
bD
ag
ag
aa
"}
(20,1,1) = {"
@@ -1625,7 +1621,7 @@ aa
aa
aa
ac
bD
ag
aa
"}
(21,1,1) = {"
@@ -1676,8 +1672,8 @@ ac
aa
aa
ac
bD
bD
ag
ag
"}
(22,1,1) = {"
ab
@@ -1727,8 +1723,8 @@ ac
ac
ac
aW
bD
bD
ag
ag
"}
(23,1,1) = {"
ab
@@ -1778,8 +1774,8 @@ ag
aw
ar
ag
bD
bD
ag
ag
"}
(24,1,1) = {"
ab
@@ -1829,8 +1825,8 @@ ag
aw
ar
ag
bD
bD
ag
ag
"}
(25,1,1) = {"
ab
@@ -1880,8 +1876,8 @@ ac
ac
ac
ac
bD
bD
ag
ag
"}
(26,1,1) = {"
ab

View File

@@ -23919,11 +23919,11 @@
dir = 4
},
/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden,
/obj/structure/reagent_dispensers/fueltank,
/turf/open/floor/plating,
/area/maintenance/port)
"bfe" = (
/obj/machinery/atmospherics/pipe/manifold/supply/hidden,
/obj/structure/reagent_dispensers/watertank,
/turf/open/floor/plating,
/area/maintenance/port)
"bff" = (
@@ -25957,7 +25957,7 @@
/area/medical/paramedic)
"bkd" = (
/obj/machinery/camera{
c_tag = "Medbay Morgue";
c_tag = "Paramedic Disbatch";
dir = 8;
network = list("ss13","medbay")
},
@@ -26360,7 +26360,7 @@
req_access_txt = "6"
},
/turf/open/floor/plasteel/dark,
/area/medical/morgue)
/area/maintenance/department/medical/morgue)
"blb" = (
/obj/machinery/door/airlock/command{
name = "Captain's Quarters";
@@ -27606,13 +27606,13 @@
/obj/structure/sign/warning/radiation/rad_area{
pixel_x = 32
},
/obj/structure/cable{
icon_state = "0-2"
},
/obj/structure/cable{
icon_state = "0-8"
},
/obj/effect/spawner/structure/window/reinforced,
/obj/structure/cable{
icon_state = "1-8"
},
/turf/open/floor/plating,
/area/engineering/gravity_generator)
"bnX" = (
@@ -33974,12 +33974,12 @@
},
/obj/machinery/bloodbankgen,
/obj/machinery/camera{
c_tag = "Medbay Recovery Room";
c_tag = "Medbay Surgery Storage";
dir = 6;
network = list("ss13","medbay")
},
/turf/open/floor/plasteel/white,
/area/medical/medbay/central)
/area/medical/storage)
"bCD" = (
/obj/machinery/computer/operating,
/turf/open/floor/plasteel/white/side,
@@ -34354,11 +34354,14 @@
/area/engineering/storage/tech)
"bDA" = (
/obj/structure/disposalpipe/segment,
/obj/machinery/atmospherics/pipe/simple/supply/hidden{
dir = 4
/obj/structure/cable{
icon_state = "4-8"
},
/obj/machinery/atmospherics/pipe/manifold/supply/hidden{
dir = 1
},
/turf/open/floor/plasteel/white,
/area/medical/medbay/central)
/area/medical/storage)
"bDB" = (
/obj/machinery/atmospherics/pipe/simple/supply/hidden{
dir = 4
@@ -34366,6 +34369,9 @@
/obj/structure/cable{
icon_state = "1-4"
},
/obj/structure/cable{
icon_state = "4-8"
},
/turf/open/floor/plasteel/white/side{
dir = 4
},
@@ -35118,7 +35124,7 @@
dir = 4
},
/turf/closed/wall,
/area/medical/medbay/central)
/area/medical/storage)
"bFn" = (
/obj/structure/disposalpipe/segment{
dir = 5
@@ -35130,12 +35136,12 @@
/obj/structure/disposalpipe/segment{
dir = 10
},
/obj/machinery/light/small{
dir = 1
},
/obj/effect/decal/cleanable/blood/old,
/obj/machinery/airalarm{
pixel_y = 23
},
/turf/open/floor/plasteel/white,
/area/medical/medbay/central)
/area/medical/storage)
"bFp" = (
/obj/structure/closet/crate/freezer,
/obj/item/reagent_containers/blood/random,
@@ -35162,8 +35168,11 @@
dir = 8;
sortType = 6
},
/obj/machinery/light/small{
dir = 1
},
/turf/open/floor/plasteel/white,
/area/medical/medbay/central)
/area/medical/storage)
"bFq" = (
/obj/machinery/atmospherics/pipe/simple/supply/hidden,
/obj/effect/turf_decal/tile/yellow,
@@ -35187,8 +35196,11 @@
/obj/structure/disposalpipe/segment,
/obj/structure/closet/crate/freezer/surplus_limbs,
/obj/item/reagent_containers/glass/beaker/synthflesh,
/obj/machinery/atmospherics/components/unary/vent_pump/on{
dir = 1
},
/turf/open/floor/plasteel/white,
/area/medical/medbay/central)
/area/medical/storage)
"bFu" = (
/obj/machinery/atmospherics/pipe/simple/supply/hidden{
dir = 4
@@ -35222,8 +35234,9 @@
"bFx" = (
/obj/structure/disposalpipe/segment,
/obj/machinery/limbgrower,
/obj/machinery/atmospherics/components/unary/vent_scrubber/on,
/turf/open/floor/plasteel/white,
/area/medical/medbay/central)
/area/medical/storage)
"bFy" = (
/obj/machinery/atmospherics/components/unary/vent_pump/on{
dir = 1
@@ -35809,7 +35822,7 @@
dir = 4
},
/turf/closed/wall,
/area/medical/medbay/central)
/area/medical/storage)
"bGR" = (
/obj/structure/table,
/obj/item/storage/belt/medical{
@@ -35860,11 +35873,9 @@
/area/medical/medbay/central)
"bGW" = (
/obj/structure/disposalpipe/segment,
/obj/machinery/atmospherics/pipe/manifold/scrubbers/hidden{
dir = 1
},
/obj/machinery/atmospherics/pipe/manifold4w/scrubbers,
/turf/closed/wall,
/area/medical/medbay/central)
/area/medical/storage)
"bGX" = (
/obj/machinery/light{
dir = 8
@@ -37012,7 +37023,7 @@
dir = 9
},
/turf/closed/wall,
/area/medical/medbay/central)
/area/medical/storage)
"bJB" = (
/obj/machinery/atmospherics/pipe/manifold4w/scrubbers,
/turf/open/floor/plasteel,
@@ -40879,8 +40890,8 @@
/turf/open/floor/plasteel,
/area/engineering/atmos)
"bTT" = (
/obj/machinery/atmospherics/pipe/manifold/yellow/visible{
dir = 8
/obj/machinery/atmospherics/pipe/manifold/general/visible{
dir = 1
},
/obj/machinery/meter,
/turf/open/floor/plasteel,
@@ -52309,7 +52320,7 @@
dir = 4
},
/turf/open/floor/plating,
/area/science/robotics/mechbay)
/area/maintenance/department/medical/morgue)
"cHF" = (
/obj/machinery/button/door{
id = "Skynet_launch";
@@ -54428,7 +54439,7 @@
"fvk" = (
/obj/structure/disposalpipe/segment,
/turf/closed/wall,
/area/medical/medbay/central)
/area/medical/storage)
"fvY" = (
/obj/machinery/computer/cryopod{
pixel_y = 26
@@ -55768,6 +55779,9 @@
req_access_txt = "45"
},
/obj/machinery/door/firedoor,
/obj/structure/cable{
icon_state = "4-8"
},
/turf/open/floor/plasteel,
/area/medical/surgery)
"iVJ" = (
@@ -56031,7 +56045,7 @@
/obj/machinery/atmospherics/pipe/simple/supply/hidden{
dir = 4
},
/obj/structure/reagent_dispensers/fueltank,
/obj/structure/reagent_dispensers/watertank,
/turf/open/floor/plating,
/area/maintenance/port)
"jyO" = (
@@ -56248,6 +56262,7 @@
/obj/structure/cable{
icon_state = "1-2"
},
/obj/effect/mapping_helpers/airlock/cyclelink_helper,
/turf/open/floor/plasteel,
/area/engineering/engine_smes)
"jLv" = (
@@ -56560,7 +56575,7 @@
dir = 6
},
/obj/structure/cable{
icon_state = "0-8"
icon_state = "0-2"
},
/turf/open/floor/plasteel,
/area/engineering/gravity_generator)
@@ -57358,6 +57373,7 @@
/area/service/bar)
"moS" = (
/obj/machinery/atmospherics/pipe/manifold4w/yellow/visible,
/obj/machinery/meter,
/turf/open/floor/plasteel,
/area/engineering/atmos)
"mps" = (
@@ -57521,6 +57537,19 @@
/obj/structure/falsewall,
/turf/open/floor/plating,
/area/security/prison)
"mJf" = (
/obj/structure/cable{
icon_state = "0-8"
},
/obj/structure/cable{
icon_state = "0-4"
},
/obj/effect/spawner/structure/window/reinforced,
/obj/structure/cable{
icon_state = "1-4"
},
/turf/open/floor/plating,
/area/engineering/gravity_generator)
"mJo" = (
/obj/structure/door_assembly/door_assembly_mai,
/obj/item/electronics/airlock,
@@ -57562,9 +57591,6 @@
name = "Gravity Generator";
req_access_txt = "11"
},
/obj/structure/cable{
icon_state = "1-8"
},
/turf/open/floor/plasteel/dark,
/area/engineering/gravity_generator)
"mOG" = (
@@ -58231,9 +58257,6 @@
/obj/effect/turf_decal/stripes/line{
dir = 4
},
/obj/structure/cable{
icon_state = "4-8"
},
/obj/machinery/light{
dir = 4;
light_color = "#c1caff"
@@ -60411,6 +60434,9 @@
/obj/effect/spawner/structure/window/reinforced,
/turf/open/floor/plating,
/area/engineering/atmos)
"tBV" = (
/turf/closed/wall,
/area/medical/storage)
"tCa" = (
/obj/structure/table/wood,
/obj/item/instrument/guitar{
@@ -60524,6 +60550,9 @@
/obj/structure/cable{
icon_state = "1-2"
},
/obj/effect/mapping_helpers/airlock/cyclelink_helper{
dir = 1
},
/turf/open/floor/plasteel,
/area/engineering/gravity_generator)
"tJS" = (
@@ -60754,10 +60783,10 @@
/turf/open/floor/plating,
/area/maintenance/port/fore)
"ugu" = (
/obj/structure/cable{
icon_state = "1-4"
},
/obj/effect/turf_decal/stripes/line,
/obj/structure/cable{
icon_state = "1-2"
},
/turf/open/floor/plasteel,
/area/engineering/gravity_generator)
"uhm" = (
@@ -61009,8 +61038,17 @@
dir = 4
},
/obj/structure/disposalpipe/segment,
/obj/machinery/power/apc{
areastring = "/area/medical/storage";
name = "Medbay Surgery Storage";
pixel_x = 1;
pixel_y = -24
},
/obj/structure/cable{
icon_state = "0-4"
},
/turf/open/floor/plasteel/white,
/area/medical/medbay/central)
/area/medical/storage)
"uFZ" = (
/obj/structure/closet/emcloset,
/obj/effect/turf_decal/stripes/line{
@@ -61117,10 +61155,6 @@
/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden{
dir = 5
},
/obj/structure/cable{
icon_state = "0-8"
},
/obj/machinery/power/terminal,
/turf/closed/wall/r_wall,
/area/engineering/gravity_generator)
"uRn" = (
@@ -61327,15 +61361,24 @@
/turf/open/floor/plating,
/area/maintenance/port)
"vob" = (
/obj/structure/cable{
icon_state = "1-4"
},
/obj/machinery/atmospherics/pipe/simple/yellow/visible,
/obj/machinery/meter,
/turf/open/floor/plasteel,
/area/engineering/gravity_generator)
/area/engineering/atmos)
"voW" = (
/obj/structure/pool/Lboard,
/turf/open/pool,
/area/commons/fitness/pool)
"voZ" = (
/obj/structure/disposalpipe/segment,
/obj/machinery/atmospherics/pipe/simple/supply/hidden{
dir = 4
},
/obj/structure/cable{
icon_state = "4-8"
},
/turf/open/floor/plasteel/white,
/area/medical/storage)
"vpY" = (
/obj/structure/closet/lasertag/blue,
/obj/item/clothing/under/misc/pj/blue,
@@ -61527,10 +61570,13 @@
/turf/open/floor/plating,
/area/maintenance/starboard/fore)
"vFr" = (
/obj/structure/cable{
icon_state = "4-8"
},
/obj/effect/turf_decal/stripes/line,
/obj/machinery/power/terminal{
dir = 4
},
/obj/structure/cable{
icon_state = "0-8"
},
/turf/open/floor/plasteel,
/area/engineering/gravity_generator)
"vGn" = (
@@ -62156,9 +62202,6 @@
/turf/open/floor/carpet/royalblue,
/area/maintenance/starboard/aft)
"xgC" = (
/obj/structure/cable{
icon_state = "0-4"
},
/obj/machinery/power/apc{
areastring = "/area/engineering/gravity_generator";
dir = 8;
@@ -62172,13 +62215,13 @@
/obj/effect/turf_decal/stripes/line{
dir = 8
},
/obj/structure/cable{
icon_state = "0-2"
},
/obj/machinery/light{
dir = 8;
light_color = "#e8eaff"
},
/obj/structure/cable{
icon_state = "0-2"
},
/turf/open/floor/plasteel,
/area/engineering/gravity_generator)
"xgF" = (
@@ -62188,13 +62231,10 @@
},
/area/maintenance/bar)
"xhS" = (
/obj/structure/cable{
icon_state = "2-4"
},
/obj/structure/cable{
icon_state = "4-8"
},
/obj/effect/turf_decal/stripes/line,
/obj/structure/cable{
icon_state = "1-4"
},
/turf/open/floor/plasteel,
/area/engineering/gravity_generator)
"xhV" = (
@@ -81844,7 +81884,7 @@ aQN
aQN
aZA
aPA
aWv
jxF
aYb
aZE
aZE
@@ -82615,7 +82655,7 @@ aQW
aQW
xDM
aPA
jxF
aWv
aYb
aZE
bjp
@@ -84992,7 +85032,7 @@ btG
rXl
xgC
ugu
bnV
mJf
bph
bih
big
@@ -85247,7 +85287,7 @@ xTy
xTy
tJK
xTy
vob
xTy
xhS
mOB
bph
@@ -86153,7 +86193,7 @@ aaa
aaa
gXs
gXs
aaH
gXs
abc
abu
abu
@@ -87036,11 +87076,11 @@ bCq
bSs
ceY
ccw
ccw
cjJ
cnR
cgT
cjJ
ccw
cjJ
ccw
ccw
ccw
@@ -95226,10 +95266,10 @@ aJq
bHt
bBz
bzs
bof
tBV
bFm
bGI
bof
tBV
cBD
bKD
bLO
@@ -95483,7 +95523,7 @@ bwu
kPj
bBB
eBX
bof
tBV
bFp
uFV
fvk
@@ -95740,7 +95780,7 @@ aJq
bAj
aJq
aKG
bof
tBV
bFo
bDA
bFt
@@ -95997,9 +96037,9 @@ byX
aXh
bmE
bCA
bof
tBV
bCC
bDA
voZ
bFx
bGW
bKI
@@ -96267,7 +96307,7 @@ bPc
bQs
cez
ceA
daq
bTT
bUN
bOd
bOd
@@ -97299,9 +97339,9 @@ moS
kGv
bUS
cCE
bTT
bUS
bXU
bUS
vob
bUS
bXU
bUS

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -705,7 +705,7 @@
icon_state = "4-8"
},
/turf/open/floor/plating,
/area/commons/fitness/pool)
/area/maintenance/department/crew_quarters/dorms)
"abG" = (
/obj/structure/cable{
icon_state = "1-2"
@@ -3392,6 +3392,10 @@
/obj/vehicle/ridden/secway,
/obj/item/key/security,
/obj/effect/turf_decal/bot,
/obj/machinery/airalarm{
dir = 1;
pixel_y = -22
},
/turf/open/floor/plasteel/showroomfloor,
/area/security/office)
"ais" = (
@@ -4891,6 +4895,10 @@
/obj/effect/turf_decal/tile/red{
dir = 8
},
/obj/machinery/airalarm{
dir = 4;
pixel_x = -23
},
/turf/open/floor/plasteel,
/area/security/brig)
"alz" = (
@@ -10747,6 +10755,11 @@
name = "Port Solar APC";
pixel_y = 23
},
/obj/machinery/camera{
c_tag = "Port Bow Solar";
dir = 9;
name = "solar camera"
},
/turf/open/floor/plating,
/area/maintenance/solars/port)
"ayD" = (
@@ -24639,6 +24652,12 @@
},
/turf/open/space,
/area/solars/starboard)
"beW" = (
/obj/machinery/atmospherics/pipe/simple/general/visible{
dir = 5
},
/turf/open/floor/plasteel,
/area/engineering/atmos)
"beY" = (
/obj/machinery/camera{
c_tag = "Arrivals Central";
@@ -37279,7 +37298,7 @@
dir = 4
},
/turf/open/floor/plating,
/area/science/mixing)
/area/maintenance/department/science)
"bGB" = (
/obj/machinery/light/small,
/obj/machinery/atmospherics/pipe/simple/supply/hidden{
@@ -37809,6 +37828,10 @@
/obj/effect/turf_decal/tile/purple{
dir = 8
},
/obj/item/radio/intercom{
pixel_x = 30;
pixel_y = -2
},
/turf/open/floor/plasteel,
/area/science/mixing)
"bHI" = (
@@ -40347,15 +40370,9 @@
/obj/structure/cable{
icon_state = "1-2"
},
/obj/machinery/atmospherics/components/binary/pump{
/obj/machinery/atmospherics/components/binary/pump/on{
dir = 8;
name = "Mix to Ports"
},
/turf/open/floor/plasteel,
/area/engineering/atmos)
"bNk" = (
/obj/machinery/atmospherics/pipe/manifold/green/visible{
dir = 1
name = "Unfiltered to Mix"
},
/turf/open/floor/plasteel,
/area/engineering/atmos)
@@ -40364,8 +40381,9 @@
/obj/effect/turf_decal/tile/yellow{
dir = 4
},
/obj/machinery/atmospherics/pipe/manifold/green/visible{
dir = 1
/obj/machinery/atmospherics/components/binary/pump/on{
dir = 4;
name = "Unfiltered & Air to Mix"
},
/turf/open/floor/plasteel,
/area/engineering/atmos)
@@ -40801,23 +40819,19 @@
},
/turf/open/floor/plasteel,
/area/engineering/atmos)
"bOo" = (
/obj/machinery/atmospherics/pipe/manifold/general/visible,
/turf/open/floor/plasteel,
/area/engineering/atmos)
"bOp" = (
/obj/structure/cable{
icon_state = "1-2"
},
/obj/machinery/atmospherics/pipe/simple/general/visible{
dir = 10
/obj/machinery/atmospherics/components/binary/pump{
dir = 8;
name = "Pure to Mix"
},
/turf/open/floor/plasteel,
/area/engineering/atmos)
"bOq" = (
/obj/machinery/atmospherics/components/binary/pump{
dir = 1;
name = "Pure to Mix"
/obj/machinery/atmospherics/pipe/manifold/green/visible{
dir = 1
},
/turf/open/floor/plasteel,
/area/engineering/atmos)
@@ -40836,7 +40850,7 @@
/turf/open/floor/engine/vacuum,
/area/science/mixing)
"bOu" = (
/obj/machinery/atmospherics/components/unary/outlet_injector/on{
/obj/machinery/atmospherics/components/unary/outlet_injector/atmos/toxins_mixing_input{
dir = 4
},
/turf/open/floor/plating/airless,
@@ -41081,13 +41095,6 @@
},
/turf/open/floor/plasteel,
/area/engineering/atmos)
"bPa" = (
/obj/machinery/portable_atmospherics/canister,
/obj/machinery/atmospherics/components/unary/portables_connector/visible{
dir = 1
},
/turf/open/floor/plasteel,
/area/engineering/atmos)
"bPd" = (
/obj/machinery/atmospherics/pipe/manifold/yellow/visible{
dir = 8
@@ -41399,7 +41406,6 @@
/obj/structure/cable{
icon_state = "1-2"
},
/obj/machinery/atmospherics/pipe/simple/general/visible,
/turf/open/floor/plasteel,
/area/engineering/atmos)
"bPW" = (
@@ -41777,14 +41783,16 @@
/turf/open/floor/plasteel,
/area/engineering/atmos)
"bQK" = (
/obj/machinery/atmospherics/pipe/simple/cyan/visible,
/obj/machinery/atmospherics/pipe/simple/general/visible{
dir = 4
},
/obj/machinery/atmospherics/pipe/simple/cyan/visible,
/turf/open/floor/plasteel,
/area/engineering/atmos)
"bQL" = (
/obj/machinery/atmospherics/pipe/manifold4w/general/visible,
/obj/machinery/atmospherics/pipe/manifold/green/visible{
dir = 8
},
/turf/open/floor/plasteel,
/area/engineering/atmos)
"bQM" = (
@@ -41792,9 +41800,8 @@
/obj/effect/turf_decal/tile/yellow{
dir = 4
},
/obj/machinery/atmospherics/components/binary/pump/on{
dir = 1;
name = "Unfiltered to Mix"
/obj/machinery/atmospherics/pipe/simple/green/visible{
dir = 10
},
/turf/open/floor/plasteel,
/area/engineering/atmos)
@@ -42101,8 +42108,7 @@
/turf/open/floor/plasteel,
/area/engineering/atmos)
"bRw" = (
/obj/machinery/atmospherics/pipe/manifold4w/general/visible,
/obj/machinery/meter,
/obj/machinery/atmospherics/pipe/simple/general/visible,
/turf/open/floor/plasteel,
/area/engineering/atmos)
"bRx" = (
@@ -45936,14 +45942,8 @@
/turf/open/floor/engine,
/area/maintenance/disposal/incinerator)
"bZV" = (
/obj/effect/mapping_helpers/airlock/cyclelink_helper{
dir = 8
},
/obj/machinery/door/airlock/external{
req_access_txt = "13"
},
/turf/open/floor/plating,
/area/maintenance/department/cargo)
/turf/closed/wall,
/area/hallway/primary/fore)
"bZY" = (
/turf/closed/wall,
/area/service/chapel/office)
@@ -52330,7 +52330,6 @@
/area/service/library)
"czp" = (
/obj/structure/table/wood,
/obj/item/disk/nuclear/fake,
/obj/item/barcodescanner,
/turf/open/floor/plasteel/dark,
/area/service/library)
@@ -53827,6 +53826,12 @@
},
/turf/open/floor/plasteel,
/area/construction/mining/aux_base)
"eEd" = (
/obj/machinery/atmospherics/pipe/simple/green/visible{
dir = 6
},
/turf/open/floor/plasteel,
/area/engineering/atmos)
"eEp" = (
/obj/machinery/atmospherics/components/unary/vent_scrubber/on{
dir = 4
@@ -55196,6 +55201,15 @@
/obj/machinery/atmospherics/pipe/simple/supply/hidden,
/turf/open/floor/plasteel,
/area/construction/mining/aux_base)
"hEi" = (
/obj/structure/cable{
icon_state = "1-2"
},
/obj/machinery/atmospherics/pipe/simple/general/visible{
dir = 10
},
/turf/open/floor/plasteel,
/area/engineering/atmos)
"hEX" = (
/obj/machinery/atmospherics/pipe/simple/supply/hidden{
dir = 6
@@ -56737,6 +56751,12 @@
/obj/effect/turf_decal/delivery,
/turf/open/floor/plasteel/dark,
/area/engineering/main)
"kWG" = (
/obj/machinery/atmospherics/pipe/manifold/general/visible{
dir = 4
},
/turf/open/floor/plasteel,
/area/engineering/atmos)
"kWQ" = (
/obj/machinery/atmospherics/pipe/simple/orange/visible,
/obj/structure/cable/yellow{
@@ -57367,6 +57387,11 @@
name = "Starboard Solar APC";
pixel_x = -25
},
/obj/machinery/camera{
c_tag = "Starboard Solar";
dir = 10;
name = "solar camera"
},
/turf/open/floor/plating,
/area/maintenance/solars/starboard)
"mwg" = (
@@ -57441,6 +57466,15 @@
/obj/machinery/atmospherics/pipe/simple/supply/hidden,
/turf/closed/wall,
/area/maintenance/department/engine)
"mAR" = (
/obj/machinery/atmospherics/pipe/simple/green/visible{
dir = 5
},
/obj/machinery/atmospherics/pipe/simple/yellow/visible{
dir = 10
},
/turf/open/floor/plasteel,
/area/engineering/atmos)
"mCe" = (
/obj/effect/spawner/structure/window/reinforced,
/obj/machinery/door/poddoor/preopen{
@@ -58847,6 +58881,10 @@
},
/turf/open/floor/wood,
/area/service/lawoffice)
"pEM" = (
/obj/machinery/atmospherics/pipe/manifold/general/visible,
/turf/open/floor/plasteel,
/area/engineering/atmos)
"pFe" = (
/obj/machinery/atmospherics/pipe/simple/supply/hidden,
/obj/effect/turf_decal/tile/red{
@@ -59368,6 +59406,13 @@
},
/turf/open/floor/plasteel/dark,
/area/maintenance/department/crew_quarters/dorms)
"qQu" = (
/obj/machinery/portable_atmospherics/canister,
/obj/machinery/atmospherics/components/unary/portables_connector/visible{
dir = 4
},
/turf/open/floor/plasteel,
/area/engineering/atmos)
"qRl" = (
/obj/item/radio/intercom{
name = "Station Intercom (General)";
@@ -60108,6 +60153,13 @@
},
/turf/open/floor/plating,
/area/maintenance/department/security/brig)
"sGJ" = (
/obj/structure/cable{
icon_state = "1-2"
},
/obj/machinery/atmospherics/pipe/simple/general/visible,
/turf/open/floor/plasteel,
/area/engineering/atmos)
"sIK" = (
/obj/effect/turf_decal/stripes/line{
dir = 8
@@ -61029,6 +61081,12 @@
},
/turf/open/floor/engine,
/area/engineering/main)
"uST" = (
/obj/machinery/atmospherics/components/binary/pump{
name = "Mix to Ports"
},
/turf/open/floor/plasteel,
/area/engineering/atmos)
"uUQ" = (
/obj/machinery/door/airlock/maintenance{
name = "Engineering Maintenance";
@@ -61261,8 +61319,14 @@
/turf/open/floor/plating,
/area/maintenance/department/science)
"vtT" = (
/obj/effect/mapping_helpers/airlock/cyclelink_helper{
dir = 8
},
/obj/machinery/door/airlock/external{
req_access_txt = "13"
},
/turf/open/floor/plating,
/area/maintenance/solars/port)
/area/maintenance/department/cargo)
"vuP" = (
/obj/machinery/atmospherics/components/unary/vent_scrubber/on{
dir = 4
@@ -62179,7 +62243,7 @@
"xuv" = (
/obj/item/broken_bottle,
/turf/open/floor/plating,
/area/maintenance/solars/port)
/area/maintenance/department/security/brig)
"xvO" = (
/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden,
/obj/machinery/atmospherics/pipe/simple/supply/hidden{
@@ -79788,11 +79852,11 @@ atp
aus
aiu
wxb
axC
aiu
xuv
azN
vtT
vtT
aoe
ajD
ajD
aiu
apB
aiu
@@ -82360,8 +82424,8 @@ apE
avq
apE
ajM
aiu
aiu
bZV
bZV
gSH
xJy
sJr
@@ -99640,7 +99704,7 @@ bJN
bKS
bMe
bNh
bOo
pEM
bOX
bMf
bMf
@@ -100154,9 +100218,9 @@ bHw
bKU
bOr
bPU
kWG
bRw
bPa
bMf
beW
bMf
bMf
bMf
@@ -100410,13 +100474,13 @@ bIF
bHw
bKV
bOX
bUv
eEd
bQL
bPa
bMf
bMf
bMf
uST
pEM
bMf
qQu
qQu
bSU
bTT
bUv
@@ -100670,10 +100734,10 @@ bMg
bNj
bOp
bPV
bPV
bPV
bPV
bPV
hEi
sGJ
bUw
bUw
bUw
bUw
bUw
@@ -100924,8 +100988,8 @@ bIH
bHw
cqG
bOX
bNk
bOq
mAR
bPd
bPW
bPW
@@ -106255,7 +106319,7 @@ aaF
aaF
aaF
abF
aaF
aiS
aiS
atn
awC
@@ -107807,8 +107871,8 @@ aaa
aaa
aaa
aaa
aEl
aFi
aEj
vtT
aEj
aaa
aEj
@@ -108064,9 +108128,9 @@ aaa
aaa
aaa
aaa
aEj
bZV
aEj
cdm
cdm
cdm
aaa
aaa
aaa
@@ -108321,9 +108385,9 @@ aaa
aaa
aaa
aaa
ahi
ahi
ahi
bBW
bBW
bBW
aaa
aaa
aaa

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,191 @@
//MAP CONVERTED BY dmm2tgm.py THIS HEADER COMMENT PREVENTS RECONVERSION, DO NOT REMOVE
"a" = (
/turf/closed/wall/mineral/titanium/survival/pod,
/area/survivalpod/nonpowered)
"j" = (
/turf/open/floor/pod/dark,
/area/survivalpod/nonpowered)
"k" = (
/obj/item/gps/computer,
/turf/open/floor/pod/dark,
/area/survivalpod/nonpowered)
"p" = (
/obj/machinery/light,
/turf/open/floor/pod/dark,
/area/survivalpod/nonpowered)
"x" = (
/obj/machinery/smartfridge/survival_pod,
/turf/open/floor/pod/dark,
/area/survivalpod/nonpowered)
"H" = (
/obj/machinery/light{
dir = 1
},
/obj/structure/table/survival_pod,
/turf/open/floor/pod/dark,
/area/survivalpod/nonpowered)
"J" = (
/obj/machinery/light{
dir = 8
},
/turf/open/floor/pod/dark,
/area/survivalpod/nonpowered)
"P" = (
/obj/machinery/door/airlock/survival_pod,
/obj/machinery/poweredfans,
/turf/open/floor/pod/dark,
/area/survivalpod/nonpowered)
"U" = (
/obj/machinery/light{
dir = 1
},
/turf/open/floor/pod/dark,
/area/survivalpod/nonpowered)
"Y" = (
/obj/machinery/power/apc/auto_name/north,
/turf/open/floor/pod/dark,
/area/survivalpod/nonpowered)
(1,1,1) = {"
a
a
a
a
a
P
a
a
a
a
a
"}
(2,1,1) = {"
a
j
j
J
j
j
j
j
j
j
a
"}
(3,1,1) = {"
a
j
j
j
j
j
j
j
j
j
a
"}
(4,1,1) = {"
a
U
j
j
j
j
j
j
j
p
a
"}
(5,1,1) = {"
a
j
j
j
j
j
j
j
j
j
a
"}
(6,1,1) = {"
P
j
j
j
j
j
j
j
j
j
P
"}
(7,1,1) = {"
a
Y
j
j
j
j
j
j
j
j
a
"}
(8,1,1) = {"
a
H
j
j
j
j
j
j
j
p
a
"}
(9,1,1) = {"
a
x
j
j
j
j
j
j
j
j
a
"}
(10,1,1) = {"
a
k
j
j
j
j
j
j
j
j
a
"}
(11,1,1) = {"
a
a
a
a
a
P
a
a
a
a
a
"}

View File

@@ -51,3 +51,4 @@
#define ORGAN_NO_SPOIL (1<<5) //Do not spoil under any circumstances
#define ORGAN_NO_DISMEMBERMENT (1<<6) //Immune to disembowelment.
#define ORGAN_EDIBLE (1<<7) //is a snack? :D
#define ORGAN_SYNTHETIC_EMP (1<<6) //Synthetic organ affected by an EMP. Deteriorates over time.

View File

@@ -83,6 +83,8 @@
#define COMSIG_ATOM_EXIT "atom_exit" //from base of atom/Exit(): (/atom/movable/exiting, /atom/newloc)
#define COMPONENT_ATOM_BLOCK_EXIT 1
#define COMSIG_ATOM_EXITED "atom_exited" //from base of atom/Exited(): (atom/movable/exiting, atom/newloc)
/// From base of atom/wave_ex_act(): (datum/wave_explosion/explosion, args)
#define COMSIG_ATOM_WAVE_EX_ACT "atom_wave_ex_act"
///from base of atom/ex_act(): (severity, target)
#define COMSIG_ATOM_EX_ACT "atom_ex_act"
///from base of atom/emp_act(): (severity)

View File

@@ -0,0 +1,86 @@
// THIS IS INSANITY
// These are how wave explosions track when there's not only one direction to keep track of (diagonals, etc)
#define WEX_DIR_NORTH NORTH
#define WEX_DIR_SOUTH SOUTH
#define WEX_DIR_EAST EAST
#define WEX_DIR_WEST WEST
#define WEX_ALLDIRS (WEX_DIR_NORTH | WEX_DIR_SOUTH | WEX_DIR_EAST | WEX_DIR_WEST)
/// Default explosion power to consider an explosion over
#define EXPLOSION_POWER_DEAD 2.5
/// Default explosion falloff
#define EXPLOSION_DEFAULT_FALLOFF_MULTIPLY 0.98
/// Default explosion constant falloff
#define EXPLOSION_DEFAULT_FALLOFF_SUBTRACT 5
/// Block amount at which point having 0 block resistance will result in a full block
#define EXPLOSION_POWER_NO_RESIST_THRESHOLD 5
/// Explosion power quantization
#define EXPLOSION_POWER_QUANTIZATION_ACCURACY 0.1
// [explosion_flags] variable on /atom
/// No blocking if we're not dense
#define EXPLOSION_FLAG_DENSITY_DEPENDENT (1<<0)
/// If we survive the explosion, we block ALL the power and ignore the results of wave_ex_act().
#define EXPLOSION_FLAG_HARD_OBSTACLE (1<<1)
// Standardized explosion powers
/// Maxcap
#define EXPLOSION_POWER_MAXCAP 500
/// erases shreds from explosions/item damage
#define EXPLOSION_POWER_ERASE_SHREDS 400
/// Gibs most mobs
#define EXPLOSION_POWER_NORMAL_MOB_GIB 400
// Walls
#define EXPLOSION_POWER_WALL_SCRAPE 400
#define EXPLOSION_POWER_WALL_DISMANTLE 300
#define EXPLOSION_POWER_WALL_MINIMUM_DISMANTLE 200
#define EXPLOSION_POWER_RWALL_SCRAPE 450
#define EXPLOSION_POWER_RWALL_DISMANTLE 400
#define EXPLOSION_POWER_RWALL_MINIMUM_DISMANTLE 300
// Floors
#define EXPLOSION_POWER_FLOOR_TILE_BREAK 50
#define EXPLOSION_POWER_FLOOR_MINIMUM_TURF_BREAK 125
#define EXPLOSION_POWER_FLOOR_TURF_BREAK_BONUS 225
#define EXPLOSION_POWER_FLOOR_TURF_BREAK 350
#define EXPLOSION_POWER_FLOOR_TURF_SCRAPE 425
#define EXPLOSION_POWER_FLOOR_SHIELDED_IMMUNITY 250
// Helpers
/// Explosion power to object damage (without taking into consideration armor)
#define EXPLOSION_POWER_STANDARD_SCALE_OBJECT_DAMAGE(power, multiplier) (power>500)?(10*(power**0.6)*multiplier):(0.1*(power**1.3)*multiplier)
/// Explosion power to object damage for hard obstacles
#define EXPLOSION_POWER_STANDARD_SCALE_HARD_OBSTACLE_DAMAGE(power, multiplier) (power>500)?(10*(power**0.6)*multiplier):(0.15*(power**1.3)*multiplier)
/// Explosion power to object damage for windows
#define EXPLOSION_POWER_STANDARD_SCALE_WINDOW_DAMAGE(power, multiplier) (power>500)?(10*(power**0.6)*multiplier):(0.2*(power**1.3)*multiplier)
/// Default brute damage to do to living things
#define EXPLOSION_POWER_STANDARD_SCALE_MOB_DAMAGE(power, multiplier) ((power / 2) * multiplier)
// Damage factors
/// Factor to multiply damage to a door by if it's open (and therefore not blocking the explosion)
#define EXPLOSION_DAMAGE_OPEN_DOOR_FACTOR 0.25
// Standardized explosion constant blocks
#define EXPLOSION_BLOCK_WINDOW 10
#define EXPLOSION_BLOCK_MACHINE 20
#define EXPLOSION_BLOCK_SPACE 20
#define EXPLOSION_BLOCK_REINFORCED_WINDOW 50
#define EXPLOSION_BLOCK_DENSE_FILLER 50
#define EXPLOSION_BLOCK_WALL 75
#define EXPLOSION_BLOCK_BLAST_PROOF 250
#define EXPLOSION_BLOCK_BOROSILICATE_WINDOW 250
#define EXPLOSION_BLOCK_EXTREME 250
// Standardized explosion factor blocks
#define EXPLOSION_DAMPEN_MACHINE 0.95
#define EXPLOSION_DAMPEN_SPACE 0.95
#define EXPLOSION_DAMPEN_WINDOW 0.95
#define EXPLOSION_DAMPEN_REINFORCED_WINDOW 0.9
#define EXPLOSION_DAMPEN_DENSE_FILLER 0.85
#define EXPLOSION_DAMPEN_WALL 0.8
#define EXPLOSION_DAMPEN_BOROSILICATE_WINDOW 0.65
#define EXPLOSION_DAMPEN_BLAST_PROOF 0.65
#define EXPLOSION_DAMPEN_EXTREME 0.5

View File

@@ -77,6 +77,7 @@
#define PROJECTILE_HIT_THRESHHOLD_LAYER 2.75 //projectiles won't hit objects at or below this layer if possible
#define TABLE_LAYER 2.8
#define TRAY_LAYER 2.85
#define GATEWAY_UNDERLAY_LAYER 2.85
#define BELOW_OBJ_LAYER 2.9
#define LOW_ITEM_LAYER 2.95
//#define OBJ_LAYER 3 //For easy recordkeeping; this is a byond define

View File

@@ -180,6 +180,7 @@
#define FIRE_PRIORITY_PROJECTILES 200
#define FIRE_PRIORITY_TICKER 200
#define FIRE_PRIORITY_ATMOS_ADJACENCY 300
#define FIRE_PRIORITY_EXPLOSIONS 350
#define FIRE_PRIORITY_STATPANEL 390
#define FIRE_PRIORITY_CHAT 400
#define FIRE_PRIORITY_RUNECHAT 410
@@ -219,7 +220,6 @@
A.flags_1 &= ~OVERLAY_QUEUED_1;\
} while(FALSE)
/**
Create a new timer and add it to the queue.
* Arguments:

View File

@@ -165,6 +165,7 @@
#define TRAIT_EXEMPT_HEALTH_EVENTS "exempt-health-events"
#define TRAIT_NO_MIDROUND_ANTAG "no-midround-antag" //can't be turned into an antag by random events
#define TRAIT_PUGILIST "pugilist" //This guy punches people for a living
#define TRAIT_NOPUGILIST "nopugilist" // for preventing ((((((((((extreme)))))))))) punch stacking
#define TRAIT_KI_VAMPIRE "ki-vampire" //when someone with this trait rolls maximum damage on a punch and stuns the target, they regain some stamina and do clone damage
#define TRAIT_MAULER "mauler" // this guy punches the shit out of people to hurt them, not to drain their stamina
#define TRAIT_PASSTABLE "passtable"

View File

@@ -14,7 +14,6 @@
//socks
init_sprite_accessory_subtypes(/datum/sprite_accessory/underwear/socks, GLOB.socks_list)
//bodypart accessories (blizzard intensifies)
init_sprite_accessory_subtypes(/datum/sprite_accessory/body_markings, GLOB.body_markings_list)
init_sprite_accessory_subtypes(/datum/sprite_accessory/tails/lizard, GLOB.tails_list_lizard)
init_sprite_accessory_subtypes(/datum/sprite_accessory/tails_animated/lizard, GLOB.animated_tails_list_lizard)
init_sprite_accessory_subtypes(/datum/sprite_accessory/tails/human, GLOB.tails_list_human)
@@ -68,6 +67,7 @@
for(var/spath in subtypesof(/datum/species))
var/datum/species/S = new spath()
GLOB.species_list[S.id] = spath
GLOB.species_datums[S.id] = S
//Surgeries
for(var/path in subtypesof(/datum/surgery))

View File

@@ -64,8 +64,6 @@
init_sprite_accessory_subtypes(/datum/sprite_accessory/spines, GLOB.spines_list)
if(!GLOB.legs_list.len)
init_sprite_accessory_subtypes(/datum/sprite_accessory/legs, GLOB.legs_list)
if(!GLOB.body_markings_list.len)
init_sprite_accessory_subtypes(/datum/sprite_accessory/body_markings, GLOB.body_markings_list)
if(!GLOB.wings_list.len)
init_sprite_accessory_subtypes(/datum/sprite_accessory/wings, GLOB.wings_list)
if(!GLOB.deco_wings_list.len)
@@ -115,15 +113,6 @@
continue
if(!S.ckeys_allowed)
snowflake_mam_tails_list[S.name] = mtpath
var/list/snowflake_markings_list = list()
for(var/mmpath in GLOB.mam_body_markings_list)
var/datum/sprite_accessory/mam_body_markings/instance = GLOB.mam_body_markings_list[mmpath]
if(istype(instance, /datum/sprite_accessory))
var/datum/sprite_accessory/S = instance
if(intendedspecies && S.recommended_species && !S.recommended_species.Find(intendedspecies))
continue
if(!S.ckeys_allowed)
snowflake_markings_list[S.name] = mmpath
var/list/snowflake_ears_list = list()
for(var/mepath in GLOB.mam_ears_list)
var/datum/sprite_accessory/ears/mam_ears/instance = GLOB.mam_ears_list[mepath]
@@ -177,7 +166,6 @@
"ears" = "None",
"frills" = pick(GLOB.frills_list),
"spines" = pick(GLOB.spines_list),
"body_markings" = pick(GLOB.body_markings_list),
"legs" = pick("Plantigrade","Digitigrade"),
"caps" = pick(GLOB.caps_list),
"insect_wings" = pick(GLOB.insect_wings_list),
@@ -187,7 +175,7 @@
"arachnid_spinneret" = pick(GLOB.arachnid_spinneret_list),
"arachnid_mandibles" = pick(GLOB.arachnid_mandibles_list),
"taur" = "None",
"mam_body_markings" = snowflake_markings_list.len ? pick(snowflake_markings_list) : "None",
"mam_body_markings" = list(),
"mam_ears" = snowflake_ears_list ? pick(snowflake_ears_list) : "None",
"mam_snouts" = snowflake_mam_snouts_list ? pick(snowflake_mam_snouts_list) : "None",
"mam_tail" = snowflake_mam_tails_list ? pick(snowflake_mam_tails_list) : "None",
@@ -320,6 +308,8 @@ GLOBAL_LIST_INIT(nonstandard_skin_tones, list("orange"))
GLOBAL_LIST_EMPTY(species_list)
GLOBAL_LIST_EMPTY(species_datums)
/proc/age2agedescription(age)
switch(age)
if(0 to 1)

View File

@@ -95,3 +95,9 @@
if("I'm feeling lucky")
chosen_id = pick(subtypesof(/datum/reagent))
return chosen_id
/proc/find_reagent_object_from_type(input)
if(GLOB.chemical_reagents_list[input]) //prefer IDs!
return GLOB.chemical_reagents_list[input]
else
return null

View File

@@ -551,8 +551,7 @@
///How many players joined the round.
var/total_players = GLOB.joined_player_list.len
var/list/typecache_bank = typecacheof(list(/datum/bank_account/department, /datum/bank_account/remote))
for(var/i in SSeconomy.generated_accounts)
var/datum/bank_account/current_acc = SSeconomy.generated_accounts[i]
for(var/datum/bank_account/current_acc in SSeconomy.generated_accounts)
if(typecache_bank[current_acc.type])
continue
station_vault += current_acc.account_balance

View File

@@ -17,7 +17,6 @@ GLOBAL_LIST_EMPTY(undershirt_f) //stores only undershirt name
//Socks
GLOBAL_LIST_EMPTY_TYPED(socks_list, /datum/sprite_accessory/underwear/socks) //stores socks indexed by name
//Lizard Bits (all datum lists indexed by name)
GLOBAL_LIST_EMPTY(body_markings_list)
GLOBAL_LIST_EMPTY(tails_list_lizard)
GLOBAL_LIST_EMPTY(animated_tails_list_lizard)
GLOBAL_LIST_EMPTY(snouts_list)
@@ -55,7 +54,6 @@ GLOBAL_LIST_INIT(mutant_reference_list, list(
"frills" = GLOB.frills_list,
"horns" = GLOB.horns_list,
"ears" = GLOB.ears_list,
"body_markings" = GLOB.body_markings_list,
"wings" = GLOB.wings_list,
"wingsopen" = GLOB.wings_open_list,
"deco_wings" = GLOB.deco_wings_list,
@@ -299,7 +297,7 @@ GLOBAL_LIST_INIT(roundstart_languages, get_roundstart_languages())
//locked parts are those that your picked species requires to have
//unlocked parts are those that anyone can choose on customisation regardless
//parts not in unlocked, but in all, are thus locked
GLOBAL_LIST_INIT(all_mutant_parts, list("tail_lizard" = "Tail", "mam_tail" = "Tail", "tail_human" = "Tail", "snout" = "Snout", "frills" = "Frills", "spines" = "Spines", "body_markings" = "Body Markings", "mam_body_markings" = "Species Markings" , "mam_ears" = "Ears", "ears" = "Ears", "mam_snouts" = "Snout", "legs" = "Legs", "deco_wings" = "Decorative Wings", "insect_wings" = "Insect Wings", "insect_fluff" = "Insect Fluff", "taur" = "Tauric Body", "insect_markings" = "Insect Markings", "wings" = "Wings", "arachnid_legs" = "Arachnid Legs", "arachnid_spinneret" = "Spinneret", "arachnid_mandibles" = "Mandibles", "xenohead" = "Caste Head", "xenotail" = "Tail", "xenodorsal" = "Dorsal Spines", "ipc_screen" = "Screen", "ipc_antenna" = "Antenna", "meat_type" = "Meat Type", "horns" = "Horns"))
GLOBAL_LIST_INIT(all_mutant_parts, list("tail_lizard" = "Tail", "mam_tail" = "Tail", "tail_human" = "Tail", "snout" = "Snout", "frills" = "Frills", "spines" = "Spines", "mam_body_markings" = "Species Markings" , "mam_ears" = "Ears", "ears" = "Ears", "mam_snouts" = "Snout", "legs" = "Legs", "deco_wings" = "Decorative Wings", "insect_wings" = "Insect Wings", "insect_fluff" = "Insect Fluff", "taur" = "Tauric Body", "insect_markings" = "Insect Markings", "wings" = "Wings", "arachnid_legs" = "Arachnid Legs", "arachnid_spinneret" = "Spinneret", "arachnid_mandibles" = "Mandibles", "xenohead" = "Caste Head", "xenotail" = "Tail", "xenodorsal" = "Dorsal Spines", "ipc_screen" = "Screen", "ipc_antenna" = "Antenna", "meat_type" = "Meat Type", "horns" = "Horns"))
GLOBAL_LIST_INIT(unlocked_mutant_parts, list("horns", "insect_fluff"))
//parts in either of the above two lists that require a second option that allows them to be coloured
@@ -350,3 +348,8 @@ GLOBAL_LIST_INIT(nongendered_limb_types, list("fly", "zombie" ,"synth", "shadow"
//list of eye types, corresponding to a respective left and right icon state for the set of eyes
GLOBAL_LIST_INIT(eye_types, list("normal", "insect", "moth", "double", "double2", "double3", "cyclops"))
//list linking bodypart bitflags to their actual names
GLOBAL_LIST_INIT(bodypart_names, list(num2text(HEAD) = "Head", num2text(CHEST) = "Chest", num2text(LEG_LEFT) = "Left Leg", num2text(LEG_RIGHT) = "Right Leg", num2text(ARM_LEFT) = "Left Arm", num2text(ARM_RIGHT) = "Right Arm"))
// list linking bodypart names back to the bitflags
GLOBAL_LIST_INIT(bodypart_values, list("Head" = num2text(HEAD), "Chest" = num2text(CHEST), "Left Leg" = num2text(LEG_LEFT), "Right Leg" = num2text(LEG_RIGHT), "Left Arm" = num2text(ARM_LEFT), "Right Arm" = num2text(ARM_RIGHT)))

View File

@@ -89,6 +89,7 @@
//Generic living
#define ui_living_pull "EAST-1:28,CENTER-2:15"
#define ui_living_health "EAST-1:28,CENTER:15"
#define ui_living_healthdoll "EAST-1:28,CENTER-1:15"
//Monkeys
#define ui_monkey_head "CENTER-5:13,SOUTH:5"

View File

@@ -13,7 +13,6 @@ GLOBAL_LIST_EMPTY(radial_menus)
icon_state = "radial_slice"
var/choice
var/next_page = FALSE
var/tooltips = FALSE
/obj/screen/radial/slice/MouseEntered(location, control, params)
. = ..()

View File

@@ -637,6 +637,11 @@
name = "health doll"
screen_loc = ui_healthdoll
/obj/screen/healthdoll/living
icon_state = "fullhealth0"
screen_loc = ui_living_healthdoll
var/filtered = FALSE //so we don't repeatedly create the mask of the mob every update
/obj/screen/mood
name = "mood"
icon_state = "mood5"

View File

@@ -0,0 +1,15 @@
/datum/hud/living/simple_animal
ui_style = 'icons/mob/screen_gen.dmi'
/datum/hud/living/simple_animal/New(mob/living/owner)
..()
pull_icon = new /obj/screen/pull()
pull_icon.icon = ui_style
pull_icon.update_icon()
pull_icon.screen_loc = ui_living_pull
pull_icon.hud = src
static_inventory += pull_icon
//mob health doll! assumes whatever sprite the mob is
healthdoll = new /obj/screen/healthdoll/living()
healthdoll.hud = src
infodisplay += healthdoll

View File

@@ -61,14 +61,14 @@ SUBSYSTEM_DEF(activity)
for(var/threat in threat_history)
. = max(threat_history[threat], .)
/datum/controller/subsystem/activity/proc/on_explosion(atom/epicenter, devastation_range, heavy_impact_range, light_impact_range, took, orig_dev_range, orig_heavy_range, orig_light_range)
/datum/controller/subsystem/activity/proc/on_explosion(datum/source, atom/epicenter, devastation_range, heavy_impact_range, light_impact_range, took, orig_dev_range, orig_heavy_range, orig_light_range)
if(!("explosions" in deferred_threats))
deferred_threats["explosions"] = 0
var/area/A = get_area(epicenter)
if(is_station_level(epicenter.z) && (A.area_flags & BLOBS_ALLOWED) && !istype(A, /area/asteroid))
deferred_threats["explosions"] += devastation_range**2 + heavy_impact_range**2 / 4 + light_impact_range**2 / 8 // 75 for a maxcap
/datum/controller/subsystem/activity/proc/on_death(mob/M, gibbed)
/datum/controller/subsystem/activity/proc/on_death(datum/source, mob/M, gibbed)
if(!("crew_deaths" in deferred_threats))
deferred_threats["crew_deaths"] = 0
if(M?.mind && SSjob.GetJob(M.mind.assigned_role))

View File

@@ -0,0 +1,23 @@
SUBSYSTEM_DEF(explosions)
name = "Explosions"
wait = 1
flags = SS_TICKER
priority = FIRE_PRIORITY_EXPLOSIONS
var/static/list/datum/wave_explosion/wave_explosions = list()
var/static/list/datum/wave_explosion/active_wave_explosions = list()
var/static/list/datum/wave_explosion/currentrun = list()
/datum/controller/subsystem/explosions/fire(resumed)
if(!resumed)
currentrun = active_wave_explosions.Copy()
var/datum/wave_explosion/E
var/ran = 0
while(length(currentrun) && !MC_TICK_CHECK)
ran = 0
for(var/i in currentrun)
E = i
if(E.tick())
currentrun -= E
ran++
if(!ran)
break

View File

@@ -713,7 +713,8 @@ SUBSYSTEM_DEF(ticker)
'sound/roundend/disappointed.ogg',
'sound/roundend/gondolabridge.ogg',
'sound/roundend/haveabeautifultime.ogg',
'sound/roundend/CitadelStationHasSeenBetterDays.ogg'\
'sound/roundend/CitadelStationHasSeenBetterDays.ogg',
'sound/roundend/approachingbaystation.ogg'\
)
SEND_SOUND(world, sound(round_end_sound))

View File

@@ -52,8 +52,15 @@
return
strength -= strength / hl3_release_date
if(strength <= RAD_BACKGROUND_RADIATION)
qdel(src)
addtimer(CALLBACK(src, .proc/check_dissipate), 5 SECONDS)
return PROCESS_KILL
/datum/component/radioactive/proc/check_dissipate()
if(strength <= RAD_BACKGROUND_RADIATION)
qdel(src)
return
if(!(datum_flags & DF_ISPROCESSING)) // keep going
START_PROCESSING(SSradiation, src)
/datum/component/radioactive/proc/glow_loop(atom/movable/master)
var/filter = master.get_filter("rad_glow")

View File

@@ -57,7 +57,7 @@
/obj/item/reagent_containers/hypospray/medipen, /obj/item/reagent_containers/dropper,
/obj/item/implanter, /obj/item/screwdriver, /obj/item/weldingtool/mini,
/obj/item/firing_pin, /obj/item/gun/ballistic/automatic/pistol, /obj/item/gun/ballistic/automatic/magrifle/pistol,
/obj/item/toy/plush/snakeplushie, /obj/item/gun/energy/e_gun/mini
/obj/item/toy/plush/snakeplushie, /obj/item/gun/energy/e_gun/mini, /obj/item/gun/ballistic/derringer
))
/datum/component/storage/concrete/pockets/shoes/clown/Initialize()

378
code/datums/explosion2.dm Normal file
View File

@@ -0,0 +1,378 @@
/// Creates a wave explosion at a certain place
/proc/wave_explosion(turf/target, power, factor = EXPLOSION_DEFAULT_FALLOFF_MULTIPLY, constant = EXPLOSION_DEFAULT_FALLOFF_SUBTRACT, flash = 0, fire = 0, atom/source, speed = 0,
silent = FALSE, bypass_logging = FALSE, block_resistance = 1, start_immediately = TRUE)
if(!istype(target) || (power <= EXPLOSION_POWER_DEAD))
return
if(!bypass_logging)
var/logstring = "Wave explosion at [COORD(target)]: [power]/[factor]/[constant]/[flash]/[fire]/[speed] initial/factor/constant/flash/fire/speed"
log_game(logstring)
message_admins(logstring)
return new /datum/wave_explosion(target, power, factor, constant, flash, fire, source, speed, silent, start_immediately, block_resistance)
/**
* New force-blastwave explosion system
*/
/datum/wave_explosion
/// Next unique numerical ID
var/static/next_id = 0
/// Our unique nuumerical ID
var/id
/// world.time we started at
var/start_time
/// Are we currently running?
var/running = FALSE
/// Are we currently finished?
var/finished = FALSE
/// What atom we originated from, if any
var/atom/source
/// Explosion power at which point to consider to be a dead expansion
var/power_considered_dead = EXPLOSION_POWER_DEAD
/// Explosion power we were initially at
var/power_initial
/// Base explosion power falloff multiplier (applied first)
var/power_falloff_factor = EXPLOSION_DEFAULT_FALLOFF_MULTIPLY
/// Base explosion power falloff subtract (applied second)
var/power_falloff_constant = EXPLOSION_DEFAULT_FALLOFF_SUBTRACT
/// Flash range
var/flash_range = 0
/// Fire probability per tile
var/fire_probability = 0
/// Are we silent/do we make the screenshake/sounds?
var/silent = FALSE
// Modifications
/// Object damage mod
var/object_damage_mod = 1
/// Hard obstcales get this mod INSTEAD of object damage mod
var/hard_obstacle_mod = 1
/// Window shatter mod. Overrides both [hard_obstcale_mod] and [object_damage_mod]
var/window_shatter_mod = 1
/// Wall destruction mod
var/wall_destroy_mod = 1
/// Mob damage mod
var/mob_damage_mod = 1
/// Mob gib mod
var/mob_gib_mod = 1
/// Mob deafen mod
var/mob_deafen_mod = 1
/// block = block / this, if 0 any block is absolute
var/block_resistance = 1
// Rewrite count: 2
// Each cycle is a "perfect ring".
// We run into the problem that diagonal hitboxes don't exist on 2d grid games.
// How we deal with this is this:
// The first half of each cycle explodes cardinal directions awaiting expansion first
// Diagonals get added to a potential diagonals list.
// The second half of each cycle checks the potential diagonals list. If something isn't on the exploded list,
// we know it's a valid diagonal and explode it.
// Then all exploded turfs are flushed to exploded_last and it continues.
// Direction bitflags use the WEX_DIR_X flags so we can keep track of more than one direction in a single field
// The insanity begins when I realized that doing cardinals are easy but diagonals require:
// - Tallying the explosive power that should go into it
// - Exploding it afterwards using the tallied power rather than passed power (so corners aren't far weaker unless there's one side of it blocked)
// Expanding the explosion power of the now exploded diagonal into the two dirs its cardinals are in
// If this is done using a perfect algorithm it should be relatively efficient and result in a near-perfect shockwave simulation.
/// The last ring that's been exploded. Any turfs in this will completely ignore the current cycle. Turf = TRUE
var/list/turf/exploded_last = list()
/// The "edges" + dirs that need to be processed this cycle. turf = dir flags
var/list/turf/edges = list()
/// The powers of the current turf edges. turf = power
var/list/turf/powers = list()
/// What cycle are we on?
var/cycle
/// When we started the current cycle
var/cycle_start
/// Time to wait between cycles
var/cycle_speed = 0
/// Current index for list
var/index = 1
/datum/wave_explosion/New(turf/initial, power, factor = EXPLOSION_DEFAULT_FALLOFF_MULTIPLY, constant = EXPLOSION_DEFAULT_FALLOFF_SUBTRACT, flash = 0, fire = 0, atom/source, speed = 0, silent = FALSE, autostart = TRUE, block_resistance = 1)
id = ++next_id
if(next_id > SHORT_REAL_LIMIT)
next_id = 0
SSexplosions.wave_explosions += src
src.power_initial = power
src.power_falloff_factor = factor
src.power_falloff_constant = constant
src.flash_range = flash
src.fire_probability = fire
src.source = source
src.cycle_speed = speed
src.silent = silent
src.block_resistance = block_resistance
if(!istype(initial))
stack_trace("Wave explosion created without a turf. This better be for debugging purposes.")
return
if(autostart)
start(initial)
/datum/wave_explosion/Destroy()
if(running)
stop(FALSE)
return ..()
/datum/wave_explosion/proc/start(list/turf/_starting)
if(running)
CRASH("Attempted to start() a running wave explosion")
if(!islist(_starting))
_starting = list(_starting)
var/list/mob/to_flash = list()
var/list/feedback = list()
var/list/mob/mob_potential_shake = list()
var/list/mob/closest_to = list()
for(var/i in 1 to _starting.len)
var/turf/starting = _starting[i]
edges[starting] = WEX_ALLDIRS
powers[starting] = power_initial
var/x0 = starting.x
var/y0 = starting.y
var/z0 = starting.z
var/area/areatype = get_area(starting)
feedback += list(list("power" = power_initial, factor = "factor", constant = "constant", flash = "flash", fire = "fire", speed = "speed", "x" = x0, "y" = y0, "z" = z0, "area" = areatype.type, "time" = TIME_STAMP("YYYY-MM-DD hh:mm:ss", 1)))
// Play sounds; we want sounds to be different depending on distance so we will manually do it ourselves.
// Stereo users will also hear the direction of the explosion!
// Calculate far explosion sound range. Only allow the sound effect for heavy/devastating explosions.
// 3/7/14 will calculate to 80 + 35
if(!silent)
for(var/mob/M in GLOB.player_list)
// Double check for client
var/turf/M_turf = get_turf(M)
if(M_turf && M_turf.z == z0)
var/dist = get_dist(M_turf, starting)
if(isnull(mob_potential_shake[M]))
mob_potential_shake[M] = dist
closest_to[M] = starting
else if(mob_potential_shake[M] < dist)
mob_potential_shake[M] = dist
closest_to[M] = starting
for(var/array in GLOB.doppler_arrays)
var/obj/machinery/doppler_array/A = array
A.sense_wave_explosion(starting, power_initial, cycle_speed)
// Flash mobs
if(flash_range)
for(var/mob/living/L in viewers(flash_range, starting))
to_flash |= L
if(!silent)
var/frequency = get_rand_frequency()
var/sound/explosion_sound = sound(get_sfx("explosion"))
var/sound/far_explosion_sound = sound('sound/effects/explosionfar.ogg')
var/far_dist = sqrt(power_initial) * 7.5
for(var/mob/M in mob_potential_shake)
var/dist = mob_potential_shake[M]
var/baseshakeamount
if(sqrt(power_initial) - dist > 0)
baseshakeamount = sqrt((sqrt(power_initial) - dist)*0.1)
// If inside the blast radius + world.view - 2
if(dist <= round(2 * sqrt(power_initial) + world.view - 2, 1))
M.playsound_local(closest_to[M], null, 100, 1, frequency, max_distance = 5, S = explosion_sound)
if(baseshakeamount > 0)
shake_camera(M, 25, clamp(baseshakeamount, 0, 10))
// You hear a far explosion if you're outside the blast radius. Small bombs shouldn't be heard all over the station.
else if(dist <= far_dist)
var/far_volume = clamp(far_dist, 30, 50) // Volume is based on explosion size and dist
far_volume += (dist <= far_dist * 0.5 ? 50 : 0) // add 50 volume if the mob is pretty close to the explosion
M.playsound_local(closest_to[M], null, far_volume, 1, frequency, max_distance = 5, S = far_explosion_sound)
if(baseshakeamount > 0)
shake_camera(M, 10, clamp(baseshakeamount*0.25, 0, 2.5))
for(var/i in 1 to to_flash.len)
var/mob/living/L = to_flash[i]
L.flash_act()
SSblackbox.record_feedback("associative", "wave_explosion", 1, feedback)
if(!cycle)
cycle = 1
SSexplosions.active_wave_explosions += src
running = TRUE
cycle_start = world.time - cycle_speed
tick()
/datum/wave_explosion/proc/stop(delete = TRUE)
SSexplosions.active_wave_explosions -= src
SSexplosions.currentrun -= src
edges = null
powers = null
exploded_last = null
cycle = null
running = FALSE
qdel(src)
#define SHOULD_SUSPEND ((cycle_start + cycle_speed) > world.time)
/**
* Called by SSexplosions to propagate this.
* Return TRUE if postponed
*/
/datum/wave_explosion/proc/tick()
/// Each tick goes through one full cycle.
// This can be changed to a "continuous process" system where indexes are tracked if needed.
if(!src.edges.len)
// we're done
finished = TRUE
stop(TRUE)
return TRUE
if(SHOULD_SUSPEND)
return TRUE
// Set up variables
var/turf/T
var/turf/expanding
var/power
var/returned
var/blocked
var/dir
// insanity define to explode a turf with a certain amount of power, direction, and set returned.
#define WEX_ACT(_T, _P, _D) \
returned = max(0, _T.wave_explode(_P, src, _D)); \
blocked = _P - returned; \
if(!block_resistance) { \
if(blocked > EXPLOSION_POWER_NO_RESIST_THRESHOLD) { \
returned = 0; \
} \
} \
else if(blocked) { \
returned = _P - (blocked / block_resistance); \
}; \
returned = round((returned * power_falloff_factor) - power_falloff_constant, EXPLOSION_POWER_QUANTIZATION_ACCURACY); \
if(prob(fire_probability)) { \
new /obj/effect/hotspot(_T); \
};
// Cache hot lists
var/list/turf/edges = src.edges
var/list/turf/powers = src.powers
var/list/turf/exploded_last = src.exploded_last
// prepare expansions
var/list/turf/edges_next = list()
var/list/turf/powers_next = list()
var/list/turf/powers_returned = list()
var/list/turf/diagonals = list()
var/list/turf/diagonal_powers = list()
var/list/turf/diagonal_powers_max = list()
// to_chat(world, "DEBUG: cycle start edges [english_list_assoc(edges)]")
// Process cardinals:
// Explode all cardinals and expand in directions, gathering all cardinals it should go to.
// Power for when things meet in the middle should be the greatest of the two.
for(var/i in edges)
T = i
power = powers[T]
dir = edges[T]
WEX_ACT(T, power, dir)
if(returned < power_considered_dead)
continue
powers_returned[T] = returned
// diagonal power calc when multiple things hit one diagonal
#define CALCULATE_DIAGONAL_POWER(existing, adding, maximum) min(maximum, existing + adding)
// diagonal hitting cardinal expansion
#define CALCULATE_DIAGONAL_CROSS_POWER(existing, adding) max(existing, adding)
// insanity define to mark the next set of cardinals.
#define CARDINAL_MARK(ndir, cdir, edir) \
if(edir & cdir) { \
CARDINAL_MARK_NOCHECK(ndir, cdir, edir); \
};
#define CARDINAL_MARK_NOCHECK(ndir, cdir, edir) \
expanding = get_step(T,ndir); \
if(expanding && !exploded_last[expanding] && !edges[expanding]) { \
powers_next[expanding] = max(powers_next[expanding], returned); \
edges_next[expanding] = (cdir | edges_next[expanding]); \
};
// insanity define to do diagonal marking as 2 substeps
#define DIAGONAL_SUBSTEP(ndir, cdir, edir) \
expanding = get_step(T,ndir); \
if(expanding && !exploded_last[expanding] && !edges[expanding]) { \
if(!edges_next[expanding]) { \
diagonal_powers_max[expanding] = max(diagonal_powers_max[expanding], returned, powers[T]); \
diagonal_powers[expanding] = CALCULATE_DIAGONAL_POWER(diagonal_powers[expanding], returned, diagonal_powers_max[expanding]); \
diagonals[expanding] = (cdir | diagonals[expanding]); \
}; \
else { \
powers_next[expanding] = CALCULATE_DIAGONAL_CROSS_POWER(powers_next[expanding], returned); \
}; \
};
// insanity define to mark the diagonals that would otherwise be missed
#define DIAGONAL_MARK(ndir, cdir, edir) \
if(edir & cdir) { \
DIAGONAL_MARK_NOCHECK(ndir, cdir, edir); \
};
// this only works because right now, WEX_DIR_X is the same as a byond dir
// and we know we're only passing in one dir at a time.
// if this ever stops being the case, and explosions break when you touch this, now you know why.
#define DIAGONAL_MARK_NOCHECK(ndir, cdir, edir) \
DIAGONAL_SUBSTEP(turn(ndir, 90), turn(cdir, 90), edir); \
DIAGONAL_SUBSTEP(turn(ndir, -90), turn(cdir, -90), edir);
// mark
#define MARK(ndir, cdir, edir) \
if(edir & cdir) { \
CARDINAL_MARK_NOCHECK(ndir, cdir, edir); \
DIAGONAL_MARK_NOCHECK(ndir, cdir, edir); \
};
CARDINAL_MARK(NORTH, WEX_DIR_NORTH, dir)
CARDINAL_MARK(SOUTH, WEX_DIR_SOUTH, dir)
CARDINAL_MARK(EAST, WEX_DIR_EAST, dir)
CARDINAL_MARK(WEST, WEX_DIR_WEST, dir)
// to_chat(world, "DEBUG: cycle mid edges_next [english_list_assoc(edges_next)]")
// Sweep after cardinals for diagonals
for(var/i in edges)
T = i
power = powers[T]
dir = edges[T]
returned = powers_returned[T]
DIAGONAL_MARK(NORTH, WEX_DIR_NORTH, dir)
DIAGONAL_MARK(SOUTH, WEX_DIR_SOUTH, dir)
DIAGONAL_MARK(EAST, WEX_DIR_EAST, dir)
DIAGONAL_MARK(WEST, WEX_DIR_WEST, dir)
// to_chat(world, "DEBUG: cycle mid diagonals [english_list_assoc(diagonals)]")
// Process diagonals:
for(var/i in diagonals)
T = i
power = diagonal_powers[T]
dir = diagonals[T]
WEX_ACT(T, power, dir)
if(returned < power_considered_dead)
continue
CARDINAL_MARK(NORTH, WEX_DIR_NORTH, dir)
CARDINAL_MARK(SOUTH, WEX_DIR_SOUTH, dir)
CARDINAL_MARK(EAST, WEX_DIR_EAST, dir)
CARDINAL_MARK(WEST, WEX_DIR_WEST, dir)
// to_chat(world, "DEBUG: cycle end edges_next [english_list_assoc(edges_next)]")
// flush lists
src.exploded_last = edges + diagonals
src.edges = edges_next
src.powers = powers_next
cycle++
cycle_start = world.time
#undef SHOULD_SUSPEND
#undef WEX_ACT
#undef DIAGONAL_SUBSTEP
#undef DIAGONAL_MARK
#undef CARDINAL_MARK
#undef MARK

View File

@@ -142,7 +142,8 @@
// Can most things breathe?
if(trace_gases)
continue
if(A.get_moles(/datum/gas/oxygen) >= 16)
var/oxy_moles = A.get_moles(/datum/gas/oxygen)
if(oxy_moles < 16 || oxy_moles > 50)
continue
if(A.get_moles(/datum/gas/plasma))
continue

View File

@@ -167,6 +167,7 @@
ADD_TRAIT(H, TRAIT_PIERCEIMMUNE, SLEEPING_CARP_TRAIT)
ADD_TRAIT(H, TRAIT_NODISMEMBER, SLEEPING_CARP_TRAIT)
ADD_TRAIT(H, TRAIT_TASED_RESISTANCE, SLEEPING_CARP_TRAIT)
ADD_TRAIT(H, TRAIT_NOPUGILIST, SLEEPING_CARP_TRAIT) // cqc doesn't get this as it's intended to be able to stack with northstar gloves
H.physiology.brute_mod *= 0.4 //brute is really not gonna cut it
H.physiology.burn_mod *= 0.7 //burn is distinctly more useful against them than brute but they're still resistant
H.physiology.stamina_mod *= 0.4 //You take less stamina damage overall, but you do not reduce the damage from stun batons as much
@@ -183,14 +184,15 @@
REMOVE_TRAIT(H, TRAIT_PIERCEIMMUNE, SLEEPING_CARP_TRAIT)
REMOVE_TRAIT(H, TRAIT_NODISMEMBER, SLEEPING_CARP_TRAIT)
REMOVE_TRAIT(H, TRAIT_TASED_RESISTANCE, SLEEPING_CARP_TRAIT)
H.physiology.brute_mod *= (1/0.4) //brute is really not gonna cut it
H.physiology.burn_mod *= (1/0.7) //burn is distinctly more useful against them than brute but they're still resistant
H.physiology.stamina_mod *= (1/0.4) //You take less stamina damage overall, but you do not reduce the damage from stun batons as much
H.physiology.stun_mod *= (1/0.3) //for those rare stuns
H.physiology.pressure_mod *= (1/0.3) //go hang out with carp
H.physiology.cold_mod *= (1/0.3) //cold mods are different to burn mods, they do stack however
H.physiology.heat_mod *= (1/2) //this is mostly so sleeping carp has a viable weakness. Cooking them alive. Setting them on fire and heating them will be their biggest weakness. The reason for this is....filet jokes.
H.physiology.stamina_buffer_mod *= (1/0.75) //to help with some stamina
REMOVE_TRAIT(H, TRAIT_NOPUGILIST, SLEEPING_CARP_TRAIT)
H.physiology.brute_mod = initial(H.physiology.brute_mod)
H.physiology.burn_mod = initial(H.physiology.burn_mod)
H.physiology.stamina_mod = initial(H.physiology.stamina_mod)
H.physiology.stun_mod = initial(H.physiology.stun_mod)
H.physiology.pressure_mod = initial(H.physiology.pressure_mod) //no more carpies
H.physiology.cold_mod = initial(H.physiology.cold_mod)
H.physiology.heat_mod = initial(H.physiology.heat_mod)
H.physiology.stamina_buffer_mod = initial(H.physiology.stamina_buffer_mod)
H.faction -= "carp" //:(
/mob/living/carbon/human/proc/sleeping_carp_help()

View File

@@ -11,7 +11,7 @@
/datum/mutation/human/space_adaptation/New(class_ = MUT_OTHER, timer, datum/mutation/human/copymut)
..()
if(!(type in visual_indicators))
visual_indicators[type] = list(mutable_appearance('icons/effects/genetics.dmi', "fire", -MUTATIONS_LAYER))
visual_indicators[type] = list(mutable_appearance('icons/effects/genetics.dmi', "space_adapt", -MUTATIONS_LAYER))
/datum/mutation/human/space_adaptation/get_visual_indicator()
return visual_indicators[type][1]

View File

@@ -36,6 +36,14 @@
///Value used to increment ex_act() if reactionary_explosions is on
var/explosion_block = 0
/// Flags for explosions
var/explosion_flags = NONE
/// Amount to decrease wave explosions by
var/wave_explosion_block = 0
/// Amount to multiply wave explosions by
var/wave_explosion_multiply = 1
//its inherent color, the colored paint applied on it, special color effect etc...
/**
* used to store the different colors on an atom
*
@@ -43,7 +51,6 @@
*/
var/list/atom_colours
/// a very temporary list of overlays to remove
var/list/remove_overlays
/// a very temporary list of overlays to add
@@ -556,6 +563,34 @@
contents_explosion(severity, target)
SEND_SIGNAL(src, COMSIG_ATOM_EX_ACT, severity, target)
/**
* Called when a wave explosion hits this atom. Do not override this.
*
* Returns explosion power to "allow through".
*/
/atom/proc/wave_explode(power, datum/wave_explosion/explosion, dir)
set waitfor = FALSE
// SHOULD_NOT_SLEEP(TRUE)
SHOULD_NOT_OVERRIDE(TRUE)
SEND_SIGNAL(src, COMSIG_ATOM_WAVE_EX_ACT, args)
. = wave_ex_act(power, explosion, dir) // this must happen first for stuff like destruction/damage to tick.
if(isnull(.))
stack_trace("wave_ex_act on [type] failed to return a number. defaulting to no blocking.")
return power
if((explosion_flags & EXPLOSION_FLAG_DENSITY_DEPENDENT) && !density)
return power // no block
else if((explosion_flags & EXPLOSION_FLAG_HARD_OBSTACLE) && !QDELETED(src))
return 0 // fully blocked
/**
* Called when a wave explosion hits this atom.
*
* Returns explosion power to "allow through". Standard handling and flag overrides in [wave_explode()].
*/
/atom/proc/wave_ex_act(power, datum/wave_explosion/explosion, dir)
// SHOULD_NOT_SLEEP(TRUE)
return power * wave_explosion_multiply - wave_explosion_block
/atom/proc/blob_act(obj/structure/blob/B)
SEND_SIGNAL(src, COMSIG_ATOM_BLOB_ACT, B)
return

View File

@@ -55,6 +55,9 @@
///Internal holder for emissive blocker object, do not use directly use blocks_emissive
var/atom/movable/emissive_blocker/em_block
/// Should we use tooltips, if the thing does not have the code implemented `get_tooltip_data()`, it will default to examine(src)
var/tooltips = FALSE
/atom/movable/Initialize(mapload)
. = ..()
@@ -576,7 +579,7 @@
//TODO: Better floating
/atom/movable/proc/float(on, throw_override)
if(throwing || !throw_override)
if(throwing && !throw_override)
return
if(on && !(movement_type & FLOATING))
animate(src, pixel_y = 2, time = 10, loop = -1, flags = ANIMATION_RELATIVE)

View File

@@ -96,6 +96,10 @@ Class Procs:
flags_ricochet = RICOCHET_HARD
ricochet_chance_mod = 0.3
explosion_flags = EXPLOSION_FLAG_DENSITY_DEPENDENT
wave_explosion_block = EXPLOSION_BLOCK_MACHINE
wave_explosion_multiply = EXPLOSION_DAMPEN_MACHINE
anchored = TRUE
interaction_flags_atom = INTERACT_ATOM_ATTACK_HAND | INTERACT_ATOM_UI_INTERACT

View File

@@ -79,10 +79,12 @@
if (obj_flags & EMAGGED)
return
obj_flags |= EMAGGED
SSshuttle.shuttle_purchase_requirements_met |= "emagged"
if (authenticated)
authorize_access = get_all_accesses()
to_chat(user, "<span class='danger'>You scramble the communication routing circuits!</span>")
playsound(src, 'sound/machines/terminal_alert.ogg', 50, FALSE)
SSshuttle.shuttle_purchase_requirements_met["emagged"] = TRUE
return
/obj/machinery/computer/communications/ui_act(action, list/params)

View File

@@ -54,6 +54,8 @@
assemblytype = /obj/structure/door_assembly
normalspeed = 1
explosion_block = 1
wave_explosion_block = EXPLOSION_BLOCK_WALL
wave_explosion_multiply = EXPLOSION_DAMPEN_WALL
hud_possible = list(DIAG_AIRLOCK_HUD)
interaction_flags_machine = INTERACT_MACHINE_WIRES_IF_OPEN | INTERACT_MACHINE_ALLOW_SILICON | INTERACT_MACHINE_OPEN_SILICON | INTERACT_MACHINE_REQUIRES_SILICON | INTERACT_MACHINE_OPEN
@@ -686,7 +688,7 @@
else
. += "It looks very robust."
if(hasSiliconAccessInArea(user) && (!stat & BROKEN))
if(hasSiliconAccessInArea(user) && !(stat & BROKEN))
. += "<span class='notice'>Shift-click [src] to [ density ? "open" : "close"] it.</span>"
. += "<span class='notice'>Ctrl-click [src] to [ locked ? "raise" : "drop"] its bolts.</span>"
. += "<span class='notice'>Alt-click [src] to [ secondsElectrified ? "un-electrify" : "permanently electrify"] it.</span>"

View File

@@ -16,6 +16,11 @@
interaction_flags_atom = INTERACT_ATOM_UI_INTERACT
wave_explosion_block = EXPLOSION_BLOCK_DENSE_FILLER
wave_explosion_multiply = EXPLOSION_DAMPEN_DENSE_FILLER
explosion_flags = EXPLOSION_FLAG_HARD_OBSTACLE | EXPLOSION_FLAG_DENSITY_DEPENDENT
var/secondsElectrified = 0
var/air_tight = FALSE //TRUE means density will be set as soon as the door begins to close
var/shockedby
@@ -412,3 +417,8 @@
/obj/machinery/door/GetExplosionBlock()
return density ? real_explosion_block : 0
/obj/machinery/door/wave_explosion_damage(power, datum/wave_explosion/explosion)
. = ..()
if(!density)
return . * EXPLOSION_DAMAGE_OPEN_DOOR_FACTOR

View File

@@ -71,3 +71,6 @@
/obj/machinery/door/password/ex_act(severity, target)
return
/obj/machinery/door/password/wave_ex_act(power, datum/wave_explosion/explosion, dir)
return 0 //no.

View File

@@ -8,6 +8,8 @@
closingLayer = CLOSED_BLASTDOOR_LAYER
sub_door = TRUE
explosion_block = 3
wave_explosion_block = EXPLOSION_BLOCK_BLAST_PROOF
wave_explosion_multiply = EXPLOSION_DAMPEN_BLAST_PROOF
heat_proof = TRUE
safe = FALSE
max_integrity = 600

View File

@@ -360,6 +360,8 @@
max_integrity = 300 //Stronger doors for prison (regular window door health is 200)
reinf = 1
explosion_block = 1
wave_explosion_block = EXPLOSION_BLOCK_REINFORCED_WINDOW
wave_explosion_multiply = EXPLOSION_DAMPEN_REINFORCED_WINDOW
/obj/machinery/door/window/brigdoor/security/cell
name = "cell door"

View File

@@ -114,6 +114,44 @@ GLOBAL_LIST_EMPTY(doppler_arrays)
LAZYADD(message_log, messages.Join(" "))
return TRUE
/obj/machinery/doppler_array/proc/sense_wave_explosion(turf/epicenter, power, speed)
if(stat & NOPOWER)
return FALSE
var/turf/zone = get_turf(src)
if(zone.z != epicenter.z)
return FALSE
if(next_announce > world.time)
return FALSE
next_announce = world.time + cooldown
var/distance = get_dist(epicenter, zone)
var/direct = get_dir(zone, epicenter)
if(distance > max_dist)
return FALSE
if(!(direct & dir) && !integrated)
return FALSE
var/list/messages = list("Explosive shockwave detected.", \
"Epicenter at: grid ([epicenter.x],[epicenter.y]). Shockwave expanding at a theoretical speed of [speed] m/s.", \
"Wave energy: [power]MJ.")
if(integrated)
var/obj/item/clothing/head/helmet/space/hardsuit/helm = loc
if(!helm || !istype(helm, /obj/item/clothing/head/helmet/space/hardsuit))
return FALSE
helm.display_visor_message("Waveform explosion detected! Wave energy: [power]MJ.")
else
for(var/message in messages)
say(message)
if(LAZYLEN(message_log) > list_limit)
say("Storage buffer is full! Clearing buffers...")
LAZYCLEARLIST(message_log)
LAZYADD(message_log, messages.Join(" "))
return TRUE
/obj/machinery/doppler_array/examine(mob/user)
. = ..()
. += "<span class='notice'>Its dish is facing to the [dir2text(dir)].</span>"

View File

@@ -1,9 +1,5 @@
#define LIMBGROWER_MAIN_MENU 1
#define LIMBGROWER_CATEGORY_MENU 2
#define LIMBGROWER_CHEMICAL_MENU 3
//use these for the menu system
/// The limbgrower. Makes organd and limbs with synthflesh and chems.
/// See [limbgrower_designs.dm] for everything we can make.
/obj/machinery/limbgrower
name = "limb grower"
desc = "It grows new limbs using Synthflesh."
@@ -15,161 +11,235 @@
active_power_usage = 100
circuit = /obj/item/circuitboard/machine/limbgrower
var/operating = FALSE
var/disabled = FALSE
/// The category of limbs we're browing in our UI.
var/selected_category = "human"
/// If we're currently printing something.
var/busy = FALSE
var/prod_coeff = 1
/// How efficient our machine is. Better parts = less chemicals used and less power used. Range of 1 to 0.25.
var/production_coefficient = 1
/// How long it takes for us to print a limb. Affected by production_coefficient.
var/production_speed = 3 SECONDS
/// The design we're printing currently.
var/datum/design/being_built
/// Our internal techweb for limbgrower designs.
var/datum/techweb/stored_research
var/selected_category
var/screen = 1
/// All the categories of organs we can print.
var/list/categories = list(
"human" = /datum/species/human,
"lizard" = /datum/species/lizard,
"mammal" = /datum/species/mammal,
"insect" = /datum/species/insect,
"fly" = /datum/species/fly,
"plasmaman" = /datum/species/plasmaman,
"xeno" = /datum/species/xeno,
"other" = /datum/species,
)
var/list/stored_species = list()
"human",
"lizard",
"mammal",
"insect",
"fly",
"plasmaman",
"xeno",
"other",
)
var/obj/item/disk/data/dna_disk
/obj/machinery/limbgrower/Initialize()
create_reagents(100, OPENCONTAINER)
stored_research = new /datum/techweb/specialized/autounlocking/limbgrower
for(var/i in categories)
var/species = categories[i]
stored_species[i] = new species()
. = ..()
AddComponent(/datum/component/plumbing/simple_demand)
AddComponent(/datum/component/simple_rotation, ROTATION_WRENCH | ROTATION_CLOCKWISE, null, CALLBACK(src, .proc/can_be_rotated))
/obj/machinery/limbgrower/ui_interact(mob/user)
/obj/machinery/limbgrower/ui_interact(mob/user, datum/tgui/ui)
. = ..()
if(!is_operational())
return
ui = SStgui.try_update_ui(user, src, ui)
if(!ui)
ui = new(user, src, "Limbgrower", src)
ui.open()
var/dat = main_win(user)
/obj/machinery/limbgrower/ui_data(mob/user)
var/list/data = list()
switch(screen)
if(LIMBGROWER_MAIN_MENU)
dat = main_win(user)
if(LIMBGROWER_CATEGORY_MENU)
dat = category_win(user,selected_category)
if(LIMBGROWER_CHEMICAL_MENU)
dat = chemical_win(user)
for(var/datum/reagent/reagent_id in reagents.reagent_list)
var/list/reagent_data = list(
reagent_name = reagent_id.name,
reagent_amount = reagent_id.volume,
reagent_type = reagent_id.type
)
data["reagents"] += list(reagent_data)
var/datum/browser/popup = new(user, "Limb Grower", name, 400, 500)
popup.set_content(dat)
popup.open()
data["total_reagents"] = reagents.total_volume
data["max_reagents"] = reagents.maximum_volume
data["busy"] = busy
var/list/disk_data = list()
disk_data["disk"] = dna_disk //Do i, the machine, have a disk?
disk_data["name"] = dna_disk?.fields["name"] //Name for the human saved if there is one
data["disk"] = disk_data
return data
/obj/machinery/limbgrower/ui_static_data(mob/user)
var/list/data = list()
data["categories"] = list()
var/species_categories = categories.Copy()
for(var/species in species_categories)
species_categories[species] = list()
for(var/design_id in stored_research.researched_designs)
var/datum/design/limb_design = SSresearch.techweb_design_by_id(design_id)
for(var/found_category in species_categories)
if(found_category in limb_design.category)
species_categories[found_category] += limb_design
for(var/category in species_categories)
var/list/category_data = list(
name = category,
designs = list(),
)
for(var/datum/design/found_design in species_categories[category])
var/list/all_reagents = list()
for(var/reagent_typepath in found_design.reagents_list)
var/datum/reagent/reagent_id = find_reagent_object_from_type(reagent_typepath)
var/list/reagent_data = list(
name = reagent_id.name,
amount = (found_design.reagents_list[reagent_typepath] * production_coefficient),
)
all_reagents += list(reagent_data)
category_data["designs"] += list(list(
parent_category = category,
name = found_design.name,
id = found_design.id,
needed_reagents = all_reagents,
))
data["categories"] += list(category_data)
return data
/obj/machinery/limbgrower/on_deconstruction()
for(var/obj/item/reagent_containers/glass/G in component_parts)
reagents.trans_to(G, G.reagents.maximum_volume)
for(var/obj/item/reagent_containers/glass/our_beaker in component_parts)
reagents.trans_to(our_beaker, our_beaker.reagents.maximum_volume)
..()
/obj/machinery/limbgrower/attackby(obj/item/O, mob/user, params)
if(busy)
/obj/machinery/limbgrower/attackby(obj/item/user_item, mob/living/user, params)
if (busy)
to_chat(user, "<span class=\"alert\">\The [src] is busy. Please wait for completion of previous operation.</span>")
return
if(default_deconstruction_screwdriver(user, "limbgrower_panelopen", "limbgrower_idleoff", O))
updateUsrDialog()
if(default_deconstruction_screwdriver(user, "limbgrower_panelopen", "limbgrower_idleoff", user_item))
ui_close(user)
return
if(panel_open && default_deconstruction_crowbar(O))
return
if(user.a_intent == INTENT_HARM) //so we can hit the machine
if(user_item.tool_behaviour == TOOL_WRENCH && panel_open)
return ..()
if(istype(O, /obj/item/disk))
if(panel_open && default_deconstruction_crowbar(user_item))
return
if(istype(user_item, /obj/item/disk))
if(dna_disk)
to_chat(user, "<span class='warning'>\The [src] already has a dna disk, take it out first!</span>")
return
else
O.forceMove(src)
dna_disk = O
to_chat(user, "<span class='notice'>You insert \the [O] into \the [src].</span>")
user_item.forceMove(src)
dna_disk = user_item
to_chat(user, "<span class='notice'>You insert \the [user_item] into \the [src].</span>")
playsound(src, 'sound/machines/terminal_insert_disc.ogg', 50, 0)
return
/obj/machinery/limbgrower/Topic(href, href_list)
if(..())
if(user.a_intent != INTENT_HELP)
return ..()
/obj/machinery/limbgrower/proc/can_be_rotated()
if(panel_open)
return TRUE
return FALSE
/obj/machinery/limbgrower/ui_act(action, list/params)
. = ..()
if(.)
return
if (!busy)
if(href_list["menu"])
screen = text2num(href_list["menu"])
if(href_list["category"])
selected_category = href_list["category"]
if (busy)
to_chat(usr, "<span class='danger'>\The [src] is busy. Please wait for completion of previous operation.</span>")
return
if(href_list["disposeI"]) //Get rid of a reagent incase you add the wrong one by mistake
reagents.del_reagent(text2path(href_list["disposeI"]))
switch(action)
if(href_list["make"])
if("empty_reagent")
reagents.del_reagent(text2path(params["reagent_type"]))
. = TRUE
/////////////////
//href protection
being_built = stored_research.isDesignResearchedID(href_list["make"]) //check if it's a valid design
if("eject_disk")
eject_disk(usr)
if("make_limb")
being_built = stored_research.isDesignResearchedID(params["design_id"])
if(!being_built)
return
CRASH("[src] was passed an invalid design id!")
/// All the reagents we're using to make our organ.
var/list/consumed_reagents_list = being_built.reagents_list.Copy()
/// The amount of power we're going to use, based on how much reagent we use.
var/power = 0
var/synth_cost = being_built.reagents_list[/datum/reagent/medicine/synthflesh]*prod_coeff
var/power = max(2000, synth_cost/5)
for(var/reagent_id in consumed_reagents_list)
consumed_reagents_list[reagent_id] *= production_coefficient
if(!reagents.has_reagent(reagent_id, consumed_reagents_list[reagent_id]))
audible_message("<span class='notice'>\The [src] buzzes.</span>")
playsound(src, 'sound/machines/buzz-sigh.ogg', 50, FALSE)
return
if(reagents.has_reagent(/datum/reagent/medicine/synthflesh, being_built.reagents_list[/datum/reagent/medicine/synthflesh]*prod_coeff))
busy = TRUE
use_power(power)
flick("limbgrower_fill",src)
icon_state = "limbgrower_idleon"
addtimer(CALLBACK(src, .proc/build_item),32*prod_coeff)
power = max(2000, (power + consumed_reagents_list[reagent_id]))
if(href_list["dna_disk"])
var/mob/living/carbon/user = usr
if(istype(user))
if(!dna_disk)
var/obj/item/disk/diskette = user.get_active_held_item()
if(istype(diskette))
diskette.forceMove(src)
dna_disk = diskette
to_chat(user, "<span class='notice'>You insert \the [diskette] into \the [src].</span>")
else
dna_disk.forceMove(src.loc)
user.put_in_active_hand(dna_disk)
to_chat(user, "<span class='notice'>You remove \the [dna_disk] from \the [src].</span>")
dna_disk = null
else
to_chat(user, "<span class='warning'>You are unable to grasp \the [dna_disk] disk from \the [src].</span>")
else
to_chat(usr, "<span class=\"alert\">\The [src] is busy. Please wait for completion of previous operation.</span>")
busy = TRUE
use_power(power)
flick("limbgrower_fill",src)
icon_state = "limbgrower_idleon"
selected_category = params["active_tab"]
addtimer(CALLBACK(src, .proc/build_item, consumed_reagents_list), production_speed * production_coefficient)
. = TRUE
updateUsrDialog()
return
/obj/machinery/limbgrower/proc/build_item()
if(reagents.has_reagent(/datum/reagent/medicine/synthflesh, being_built.reagents_list[/datum/reagent/medicine/synthflesh]*prod_coeff)) //sanity check, if this happens we are in big trouble
reagents.remove_reagent(/datum/reagent/medicine/synthflesh, being_built.reagents_list[/datum/reagent/medicine/synthflesh]*prod_coeff)
var/buildpath = being_built.build_path
if(ispath(buildpath, /obj/item/bodypart)) //This feels like spaghetti code, but i need to initiliaze a limb somehow
build_limb(buildpath)
else if(ispath(buildpath, /obj/item/organ/genital)) //genitals are uhh... customizable
build_genital(buildpath)
else
//Just build whatever it is
new buildpath(loc)
else
src.visible_message("<span class=\"error\"> Something went very wrong and there isnt enough synthflesh anymore!</span>")
busy = FALSE
flick("limbgrower_unfill",src)
icon_state = "limbgrower_idleoff"
updateUsrDialog()
/*
* The process of beginning to build a limb or organ.
* Goes through and sanity checks that we actually have enough reagent to build our item.
* Then, remove those reagents from our reagents datum.
*
* After the reagents are handled, we can proceede with making the limb or organ. (Limbs are handled in a separate proc)
*
* modified_consumed_reagents_list - the list of reagents we will consume on build, modified by the production coefficient.
*/
/obj/machinery/limbgrower/proc/build_item(list/modified_consumed_reagents_list)
for(var/reagent_id in modified_consumed_reagents_list)
if(!reagents.has_reagent(reagent_id, modified_consumed_reagents_list[reagent_id]))
audible_message("<span class='notice'>\The [src] buzzes.</span>")
playsound(src, 'sound/machines/buzz-sigh.ogg', 50, FALSE)
break
/obj/machinery/limbgrower/proc/build_limb(buildpath)
reagents.remove_reagent(reagent_id, modified_consumed_reagents_list[reagent_id])
var/built_typepath = being_built.build_path
// If we have a bodypart, we need to initialize the limb on its own. Otherwise we can build it here.
if(ispath(built_typepath, /obj/item/bodypart))
build_limb(built_typepath)
else if(ispath(built_typepath, /obj/item/organ/genital)) //genitals are uhh... customizable
build_genital(built_typepath)
else
new built_typepath(loc)
busy = FALSE
flick("limbgrower_unfill", src)
icon_state = "limbgrower_idleoff"
/*
* The process of putting together a limb.
* This is called from after we remove the reagents, so this proc is just initializing the limb type.
*
* This proc handles skin / mutant color, greyscaling, names and descriptions, and various other limb creation steps.
*
* built_typepath - the path of the bodypart we're building.
*/
/obj/machinery/limbgrower/proc/build_limb(built_typepath)
//i need to create a body part manually using a set icon (otherwise it doesnt appear)
var/obj/item/bodypart/limb
var/datum/species/selected = stored_species[selected_category]
limb = new buildpath(loc)
var/datum/species/selected = GLOB.species_datums[selected_category]
limb = new built_typepath(loc)
limb.base_bp_icon = selected.icon_limbs || DEFAULT_BODYPART_ICON_ORGANIC
limb.species_id = selected.limbs_id
limb.color_src = (MUTCOLORS in selected.species_traits ? MUTCOLORS : (selected.use_skintones ? SKINTONE : FALSE))
@@ -189,135 +259,103 @@
BP.name = "\improper synthetic [lowertext(selected.name)] [limb.name]"
BP.desc = "A synthetic [selected_category] limb that will morph on its first use in surgery. This one is for the [parse_zone(limb.body_zone)]."
/obj/machinery/limbgrower/proc/build_genital(buildpath)
/*
* Builds genitals, modifies to be the same
* as the person's cloning data on the data disk
*/
/obj/machinery/limbgrower/proc/build_genital(built_typepath)
//i needed to create a way to customize gene tools using dna
var/list/features = dna_disk?.fields["features"]
if(length(features))
switch(buildpath)
switch(built_typepath)
if(/obj/item/organ/genital/penis)
var/obj/item/organ/genital/penis/penis = new(loc)
if(features["has_cock"])
penis.shape = features["cock_shape"]
penis.length = features["cock_shape"]
penis.diameter_ratio = features["cock_diameter_ratio"]
penis.color = sanitize_hexcolor(features["cock_color"], 6)
penis.update_icon()
penis.color = sanitize_hexcolor(features["cock_color"], 6, TRUE)
penis.update()
if(/obj/item/organ/genital/testicles)
var/obj/item/organ/genital/testicles/balls = new(loc)
if(features["has_balls"])
balls.color = sanitize_hexcolor(features["balls_color"], 6)
balls.color = sanitize_hexcolor(features["balls_color"], 6, TRUE)
balls.shape = features["balls_shape"]
balls.size = features["balls_size"]
balls.fluid_rate = features["balls_cum_rate"]
balls.fluid_mult = features["balls_cum_mult"]
balls.fluid_efficiency = features["balls_efficiency"]
balls.update()
if(/obj/item/organ/genital/vagina)
var/obj/item/organ/genital/vagina/vegana = new(loc)
if(features["has_vagina"])
vegana.color = sanitize_hexcolor(features["vag_color"], 6)
if(features["has_vag"])
vegana.color = sanitize_hexcolor(features["vag_color"], 6, TRUE)
vegana.shape = features["vag_shape"]
vegana.update()
if(/obj/item/organ/genital/breasts)
var/obj/item/organ/genital/breasts/boobs = new(loc)
if(features["has_breasts"])
boobs.color = sanitize_hexcolor(features["breasts_color"], 6)
boobs.color = sanitize_hexcolor(features["breasts_color"], 6, TRUE)
boobs.size = features["breasts_size"]
boobs.shape = features["breasts_shape"]
if(!features["breasts_producing"])
boobs.genital_flags &= ~(GENITAL_FUID_PRODUCTION|CAN_CLIMAX_WITH|CAN_MASTURBATE_WITH)
boobs.update()
else
new buildpath(loc)
new built_typepath(loc)
else
new buildpath(loc)
new built_typepath(loc)
/obj/machinery/limbgrower/RefreshParts()
reagents.maximum_volume = 0
for(var/obj/item/reagent_containers/glass/G in component_parts)
reagents.maximum_volume += G.volume
G.reagents.trans_to(src, G.reagents.total_volume)
var/T=1.2
for(var/obj/item/stock_parts/manipulator/M in component_parts)
T -= M.rating*0.2
prod_coeff = min(1,max(0,T)) // Coeff going 1 -> 0,8 -> 0,6 -> 0,4
for(var/obj/item/reagent_containers/glass/our_beaker in component_parts)
reagents.maximum_volume += our_beaker.volume
our_beaker.reagents.trans_to(src, our_beaker.reagents.total_volume)
production_coefficient = 1.2
for(var/obj/item/stock_parts/manipulator/our_manipulator in component_parts)
production_coefficient -= our_manipulator.rating * 0.2
production_coefficient = clamp(production_coefficient, 0, 1) // coefficient goes from 1 -> 0.8 -> 0.6 -> 0.4
/obj/machinery/limbgrower/examine(mob/user)
. = ..()
if(!panel_open)
. += "<span class='notice'>It looks like as if the panel were open you could rotate it with a <b>wrench</b>.</span>"
else
. += "<span class='notice'>The panel is open.</span>"
if(in_range(user, src) || isobserver(user))
. += "<span class='notice'>The status display reads: Storing up to <b>[reagents.maximum_volume]u</b> of synthflesh.<br>Synthflesh consumption at <b>[prod_coeff*100]%</b>.<span>"
. += "<span class='notice'>The status display reads: Storing up to <b>[reagents.maximum_volume]u</b> of reagents.<br>Reagent consumption rate at <b>[production_coefficient * 100]%</b>.</span>"
/obj/machinery/limbgrower/proc/main_win(mob/user)
var/dat = "<div class='statusDisplay'><h3>[src] Menu:</h3><br>"
dat += "<A href='?src=[REF(src)];dna_disk=1'>[dna_disk ? "Remove" : "Insert"] cloning data disk</A>"
dat += "<hr>"
dat += "<A href='?src=[REF(src)];menu=[LIMBGROWER_CHEMICAL_MENU]'>Chemical Storage</A>"
dat += materials_printout()
dat += "<table style='width:100%' align='center'><tr>"
for(var/C in categories)
dat += "<td><A href='?src=[REF(src)];category=[C];menu=[LIMBGROWER_CATEGORY_MENU]'>[C]</A></td>"
dat += "</tr><tr>"
//one category per line
dat += "</tr></table></div>"
return dat
/obj/machinery/limbgrower/proc/category_win(mob/user,selected_category)
var/dat = "<A href='?src=[REF(src)];menu=[LIMBGROWER_MAIN_MENU]'>Return to main menu</A>"
dat += "<div class='statusDisplay'><h3>Browsing [selected_category]:</h3><br>"
dat += materials_printout()
for(var/v in stored_research.researched_designs)
var/datum/design/D = SSresearch.techweb_design_by_id(v)
if(!(selected_category in D.category))
continue
if(disabled || !can_build(D))
dat += "<span class='linkOff'>[D.name]</span>"
else
dat += "<a href='?src=[REF(src)];make=[D.id];multiplier=1'>[D.name]</a>"
dat += "[get_design_cost(D)]<br>"
dat += "</div>"
return dat
/obj/machinery/limbgrower/proc/chemical_win(mob/user)
var/dat = "<A href='?src=[REF(src)];menu=[LIMBGROWER_MAIN_MENU]'>Return to main menu</A>"
dat += "<div class='statusDisplay'><h3>Browsing Chemical Storage:</h3><br>"
dat += materials_printout()
for(var/datum/reagent/R in reagents.reagent_list)
dat += "[R.name]: [R.volume]"
dat += "<A href='?src=[REF(src)];disposeI=[R]'>Purge</A><BR>"
dat += "</div>"
return dat
/obj/machinery/limbgrower/proc/materials_printout()
var/dat = "<b>Total amount:></b> [reagents.total_volume] / [reagents.maximum_volume] cm<sup>3</sup><br>"
return dat
/obj/machinery/limbgrower/proc/can_build(datum/design/D)
return (reagents.has_reagent(/datum/reagent/medicine/synthflesh, D.reagents_list[/datum/reagent/medicine/synthflesh]*prod_coeff)) //Return whether the machine has enough synthflesh to produce the design
/obj/machinery/limbgrower/proc/get_design_cost(datum/design/D)
var/dat
if(D.reagents_list[/datum/reagent/medicine/synthflesh])
dat += "[D.reagents_list[/datum/reagent/medicine/synthflesh] * prod_coeff] Synthetic flesh "
return dat
/*
* Checks our reagent list to see if a design can be built.
*
* limb_design - the design we're checking for buildability.
*
* returns TRUE if we have enough reagent to build it. Returns FALSE if we do not.
*/
/obj/machinery/limbgrower/proc/can_build(datum/design/limb_design)
for(var/datum/reagent/reagent_id in limb_design.reagents_list)
if(!reagents.has_reagent(reagent_id, limb_design.reagents_list[reagent_id] * production_coefficient))
return FALSE
return TRUE
/// Emagging a limbgrower allows you to build synthetic armblades.
/obj/machinery/limbgrower/emag_act(mob/user)
. = ..()
if(obj_flags & EMAGGED)
return
for(var/id in SSresearch.techweb_designs)
var/datum/design/D = SSresearch.techweb_design_by_id(id)
if((D.build_type & LIMBGROWER) && ("emagged" in D.category))
stored_research.add_design(D)
for(var/design_id in SSresearch.techweb_designs)
var/datum/design/found_design = SSresearch.techweb_design_by_id(design_id)
if((found_design.build_type & LIMBGROWER) && ("emagged" in found_design.category))
stored_research.add_design(found_design)
to_chat(user, "<span class='warning'>A warning flashes onto the screen, stating that safety overrides have been deactivated!</span>")
obj_flags |= EMAGGED
return TRUE
update_static_data(user)
/obj/machinery/limbgrower/AltClick(mob/living/user)
. = ..()
eject_disk(user)
/obj/machinery/limbgrower/proc/eject_disk(mob/user)
if(istype(user) && user.canUseTopic(src, BE_CLOSE, FALSE, NO_TK))
if(busy)
to_chat(user, "<span class=\"alert\">\The [src] is busy. Please wait for completion of previous operation.</span>")
@@ -326,6 +364,7 @@
dna_disk.forceMove(src.loc)
user.put_in_active_hand(dna_disk)
to_chat(user, "<span class='notice'>You remove \the [dna_disk] from \the [src].</span>")
playsound(src, 'sound/machines/terminal_insert_disc.ogg', 50, 0)
dna_disk = null
else
to_chat(user, "<span class='warning'>\The [src] has doesn't have a disk on it!")

View File

@@ -50,6 +50,10 @@
/obj/effect/decal/cleanable/glass/ex_act()
qdel(src)
/obj/effect/decal/cleanable/glass/wave_ex_act(power, datum/wave_explosion/explosion, dir)
qdel(src)
return power
/obj/effect/decal/cleanable/glass/plasma
icon_state = "plasmatiny"
@@ -131,6 +135,9 @@
/obj/effect/decal/cleanable/greenglow/ex_act()
return
/obj/effect/decal/cleanable/greenglow/wave_ex_act(power, datum/wave_explosion/explosion, dir)
return power
/obj/effect/decal/cleanable/cobweb
name = "cobweb"
desc = "Somebody should remove that."
@@ -253,6 +260,11 @@
if(severity == 1) //so shreds created during an explosion aren't deleted by the explosion.
qdel(src)
/obj/effect/decal/cleanable/shreds/wave_ex_act(power, datum/wave_explosion/explosion, dir)
if(power > EXPLOSION_POWER_ERASE_SHREDS)
qdel(src)
return power // no block
/obj/effect/decal/cleanable/shreds/Initialize()
pixel_x = rand(-10, 10)
pixel_y = rand(-10, 10)

View File

@@ -309,6 +309,10 @@
/obj/structure/foamedmetal/resin/Initialize()
. = ..()
neutralize_air()
addtimer(CALLBACK(src, .proc/neutralize_air), 5) // yeah this sucks, maybe when auxmos is out
/obj/structure/foamedmetal/resin/proc/neutralize_air()
if(isopenturf(loc))
var/turf/open/O = loc
O.ClearWet()

View File

@@ -248,6 +248,14 @@ GLOBAL_VAR_INIT(embedpocalypse, FALSE) // if true, all items will be able to emb
loc = null
loc = T
/obj/item/wave_ex_act(power, datum/wave_explosion/explosion, dir)
. = ..()
if(!anchored)
var/throw_dist = round(rand(3, max(3, 2.5 * sqrt(power))), 1)
throw_speed = EXPLOSION_THROW_SPEED
var/turf/target = get_ranged_target_turf(src, dir, throw_dist)
throw_at(target, throw_dist, EXPLOSION_THROW_SPEED)
/obj/item/examine(mob/user) //This might be spammy. Remove?
. = ..()

View File

@@ -157,7 +157,7 @@
to_chat(user, "<span class='notice'>You need to get closer!</span>")
return
if(use_paint(user) && isturf(F))
F.AddElement(/datum/element/decal, 'icons/turf/decals.dmi', stored_decal_total, turn(stored_dir, -dir2angle(F.dir)), CLEAN_STRONG, color, null, null, alpha)
F.AddElement(/datum/element/decal, 'icons/turf/decals.dmi', stored_decal_total, stored_dir, CLEAN_STRONG, color, null, null, alpha)
/obj/item/airlock_painter/decal/attack_self(mob/user)
if((ink) && (ink.charges >= 1))
@@ -180,6 +180,11 @@
stored_decal_total = "[stored_decal][yellow_fix][stored_color]"
return
/obj/item/airlock_painter/decal/ui_assets(mob/user)
return list(
get_asset_datum(/datum/asset/spritesheet/decals)
)
/obj/item/airlock_painter/decal/ui_interact(mob/user, datum/tgui/ui)
ui = SStgui.try_update_ui(user, src, ui)
if(!ui)
@@ -189,6 +194,7 @@
/obj/item/airlock_painter/decal/ui_data(mob/user)
var/list/data = list()
data["decal_direction"] = stored_dir
data["decal_dir_text"] = dir2text(stored_dir)
data["decal_color"] = stored_color
data["decal_style"] = stored_decal
data["decal_list"] = list()

View File

@@ -553,6 +553,9 @@
/obj/item/card/id/syndicate/locked_banking
bank_support = ID_LOCKED_BANK_ACCOUNT
/obj/item/card/id/pirate
access = list(ACCESS_SYNDICATE)
/obj/item/card/id/captains_spare
name = "captain's spare ID"
desc = "The spare ID of the High Lord himself."

View File

@@ -75,18 +75,3 @@
desc = "A chromosome that reduces action based mutation cooldowns by by 50%."
icon_state = "energy"
energy_coeff = 0.5
/obj/item/chromosome/reinforcer
name = "reinforcement chromosome"
desc = "A chromosome that renders mutations immune to mutadone."
icon_state = "reinforcer"
weight = 3
/obj/item/chromosome/reinforcer/can_apply(datum/mutation/human/HM)
if(!HM || !(HM.can_chromosome == CHROMOSOME_NONE))
return FALSE
return !HM.mutadone_proof
/obj/item/chromosome/reinforcer/apply(datum/mutation/human/HM)
HM.mutadone_proof = TRUE
..()

View File

@@ -649,6 +649,9 @@
pre_noise = TRUE
post_noise = FALSE
var/stun_delay = 0 // how long it takes for you to be able to stun someone with the spraycan again
var/last_stun_time = 0
/obj/item/toy/crayon/spraycan/isValidSurface(surface)
return (istype(surface, /turf/open/floor) || istype(surface, /turf/closed/wall))
@@ -716,7 +719,8 @@
if(C.client)
C.blur_eyes(3)
C.blind_eyes(1)
if(C.get_eye_protection() <= 0) // no eye protection? ARGH IT BURNS.
if(C.get_eye_protection() <= 0 && (last_stun_time + stun_delay) <= world.time) // no eye protection? ARGH IT BURNS.
last_stun_time = world.time
C.confused = max(C.confused, 3)
C.DefaultCombatKnockdown(60)
if(ishuman(C) && actually_paints)
@@ -771,6 +775,7 @@
name = "cyborg spraycan"
desc = "A metallic container containing shiny synthesised paint."
charges = -1
stun_delay = 5 SECONDS
/obj/item/toy/crayon/spraycan/borg/draw_on(atom/target,mob/user,proximity, params)
var/diff = ..()

View File

@@ -100,6 +100,42 @@
"<span class='suicide'>[user] is slitting [user.p_their()] stomach open with the [src.name]! It looks like [user.p_theyre()] trying to commit seppuku.</span>"))
return (BRUTELOSS)
/obj/item/kitchen/efink
name = "E-Fink"
icon_state = "efink"
desc = "The E-Fink is a product by Mending Solutions Inc. Unfortunately it can only mend sliced meat, fruits and dough back to their original state. Unbutchering is not possible."
flags_1 = CONDUCT_1
force = 10
w_class = WEIGHT_CLASS_SMALL
throwforce = 10
hitsound = 'sound/weapons/bladesliceb.ogg'
throw_speed = 3
throw_range = 6
custom_materials = list(/datum/material/iron=12000)
attack_verb = list("slashed", "stabbed", "sliced", "torn", "ripped", "diced", "cut")
sharpness = SHARP_POINTY
armor = list("melee" = 0, "bullet" = 0, "laser" = 0, "energy" = 0, "bomb" = 0, "bio" = 0, "rad" = 0, "fire" = 50, "acid" = 50)
var/bayonet = FALSE //Can this be attached to a gun?
wound_bonus = -5
bare_wound_bonus = 10
custom_price = PRICE_NORMAL
/obj/item/kitchen/efink/Initialize()
. = ..()
AddComponent(/datum/component/butchering, 80 - force, 100, force - 10) //bonus chance increases depending on force
/obj/item/kitchen/efink/attack(mob/living/carbon/M, mob/living/carbon/user)
if(user.zone_selected == BODY_ZONE_PRECISE_EYES)
return eyestab(M,user)
else
return ..()
/obj/item/kitchen/efink/suicide_act(mob/user)
user.visible_message(pick("<span class='suicide'>[user] is slitting [user.p_their()] wrists with the [src.name]! It looks like [user.p_theyre()] trying to commit suicide.</span>", \
"<span class='suicide'>[user] is slitting [user.p_their()] throat with the [src.name]! It looks like [user.p_theyre()] trying to commit suicide.</span>", \
"<span class='suicide'>[user] is slitting [user.p_their()] stomach open with the [src.name]! It looks like [user.p_theyre()] trying to commit seppuku.</span>"))
return (BRUTELOSS)
/obj/item/kitchen/knife/ritual
name = "ritual knife"
desc = "The unearthly energies that once powered this blade are now dormant."
@@ -248,6 +284,24 @@
/obj/item/kitchen/rollingpin/suicide_act(mob/living/carbon/user)
user.visible_message("<span class='suicide'>[user] begins flattening [user.p_their()] head with \the [src]! It looks like [user.p_theyre()] trying to commit suicide!</span>")
return BRUTELOSS
/obj/item/kitchen/unrollingpin
name = "unrolling pin"
desc = "For when you accidentally flattened something."
icon_state = "unrolling_pin"
force = 8
throwforce = 5
throw_speed = 3
throw_range = 7
w_class = WEIGHT_CLASS_NORMAL
custom_materials = list(/datum/material/wood = MINERAL_MATERIAL_AMOUNT * 1.5)
attack_verb = list("bashed", "battered", "bludgeoned", "thrashed", "whacked")
custom_price = PRICE_ALMOST_CHEAP
/obj/item/kitchen/unrollingpin/suicide_act(mob/living/carbon/user)
user.visible_message("<span class='suicide'>[user] begins unflattening [user.p_their()] head with \the [src]! It looks like [user.p_theyre()] trying to commit suicide!</span>")
return BRUTELOSS
/* Trays moved to /obj/item/storage/bag */
/obj/item/kitchen/knife/scimitar

View File

@@ -135,8 +135,8 @@
/obj/item/organ/cyberimp/arm/toolset,
/obj/item/organ/cyberimp/arm/surgery,
/obj/item/organ/cyberimp/chest/thrusters,
/obj/item/organ/lungs/cybernetic,
/obj/item/organ/liver/cybernetic) //cyberimplants range from a nice bonus to fucking broken bullshit so no subtypesof
/obj/item/organ/lungs/cybernetic/tier3,
/obj/item/organ/liver/cybernetic/tier3) //cyberimplants range from a nice bonus to fucking broken bullshit so no subtypesof
for(var/V in templist)
var/atom/A = V
augment_list[initial(A.name)] = A

View File

@@ -383,7 +383,7 @@
. = ..()
/obj/item/stack/medical/mesh/on_attack_hand(mob/user, act_intent = user.a_intent, unarmed_attack_flags)
if(!is_open & user.get_inactive_held_item() == src)
if(!is_open && (user.get_inactive_held_item() == src))
to_chat(user, "<span class='warning'>You need to open [src] first.</span>")
return
. = ..()

View File

@@ -248,6 +248,7 @@ GLOBAL_LIST_INIT(wood_recipes, list ( \
null, \
new/datum/stack_recipe("rifle stock", /obj/item/weaponcrafting/stock, 10, time = 20), \
new/datum/stack_recipe("rolling pin", /obj/item/kitchen/rollingpin, 2, time = 30), \
new/datum/stack_recipe("unrolling pin", /obj/item/kitchen/unrollingpin, 2, time = 30), \
new/datum/stack_recipe("wooden bucket", /obj/item/reagent_containers/glass/bucket/wood, 2, time = 30), \
new/datum/stack_recipe("painting frame", /obj/item/wallframe/painting, 1, time = 10),\
new/datum/stack_recipe("wooden buckler", /obj/item/shield/riot/buckler, 20, time = 40), \

View File

@@ -367,7 +367,7 @@
/obj/item/storage/fancy/cigarettes/derringer/AltClick(mob/living/carbon/user)
if(!istype(user) || !user.canUseTopic(src, BE_CLOSE, ismonkey(user)))
return
var/obj/item/W = (locate(/obj/item/ammo_casing/a357) in contents) || (locate(/obj/item/clothing/mask/cigarette) in contents) || locate(/obj/item/ammo_casing/g4570) //Easy access smokes and bullets
var/obj/item/W = (locate(/obj/item/ammo_casing/a357) in contents) || (locate(/obj/item/clothing/mask/cigarette) in contents) ||(locate(/obj/item/gun/ballistic/derringer) in contents) || (locate(/obj/item/ammo_casing/c38) in contents) || locate(/obj/item/ammo_casing/g4570) in contents//Easy access smokes and bullets
if(W && contents.len > 0)
SEND_SIGNAL(src, COMSIG_TRY_STORAGE_TAKE, W, user)
user.put_in_hands(W)
@@ -382,6 +382,7 @@
new /obj/item/ammo_casing/a357(src)
new /obj/item/ammo_casing/a357(src)
new /obj/item/ammo_casing/a357(src)
new /obj/item/ammo_casing/a357(src)
new /obj/item/clothing/mask/cigarette/syndicate(src)
//For traitors with luck/class
@@ -404,6 +405,7 @@
new /obj/item/ammo_casing/g4570(src)
new /obj/item/ammo_casing/g4570(src)
new /obj/item/ammo_casing/g4570(src)
new /obj/item/ammo_casing/g4570(src)
new /obj/item/clothing/mask/cigarette/xeno(src)
//For Cargomen, looking for a good deal on arms, with no quarrels as to where they're from.
@@ -419,6 +421,7 @@
new /obj/item/ammo_casing/c38/lethal(src)
new /obj/item/ammo_casing/c38/lethal(src)
new /obj/item/ammo_casing/c38/lethal(src)
new /obj/item/ammo_casing/c38/lethal(src)
new /obj/item/clothing/mask/cigarette/shadyjims (src)
/////////////
//CIGAR BOX//

View File

@@ -71,6 +71,19 @@
if(3)
take_damage(rand(10, 90), BRUTE, "bomb", 0)
/obj/wave_ex_act(power, datum/wave_explosion/explosion, dir)
if(resistance_flags & INDESTRUCTIBLE)
return power
. = ..()
if(explosion.source == src)
obj_integrity = 0
qdel(src)
return
take_damage(wave_explosion_damage(power, explosion), BRUTE, "bomb", 0)
/obj/proc/wave_explosion_damage(power, datum/wave_explosion/explosion)
return (explosion_flags & EXPLOSION_FLAG_HARD_OBSTACLE)? EXPLOSION_POWER_STANDARD_SCALE_HARD_OBSTACLE_DAMAGE(power, explosion.hard_obstacle_mod) : EXPLOSION_POWER_STANDARD_SCALE_OBJECT_DAMAGE(power, explosion.object_damage_mod)
/obj/bullet_act(obj/item/projectile/P)
. = ..()
playsound(src, P.hitsound, 50, 1)

View File

@@ -56,6 +56,11 @@
name = "gear crate"
icon_state = "secgearcrate"
/obj/structure/closet/crate/secure/soviet
desc = "A crate, purportedly from Space Russia."
name = "soviet crate"
icon_state = "sovietcrate"
/obj/structure/closet/crate/secure/hydroponics
desc = "A crate with a lock on it, painted in the scheme of the station's botanists."
name = "secure hydroponics crate"

View File

@@ -73,3 +73,15 @@
name = "wumborian fugu den"
desc = "A den housing a nest of wumborian fugus, how do they all even fit in there?"
mob_types = list(/mob/living/simple_animal/hostile/asteroid/fugu)
/obj/structure/spawner/clown
name = "Laughing Larry"
desc = "A laughing, jovial figure. Something seems stuck in his throat."
icon_state = "clownbeacon"
icon = 'icons/obj/device.dmi'
max_integrity = 200
max_mobs = 15
spawn_time = 150
mob_types = list(/mob/living/simple_animal/hostile/retaliate/clown, /mob/living/simple_animal/hostile/retaliate/clown/fleshclown, /mob/living/simple_animal/hostile/retaliate/clown/clownhulk, /mob/living/simple_animal/hostile/retaliate/clown/longface, /mob/living/simple_animal/hostile/retaliate/clown/clownhulk/chlown, /mob/living/simple_animal/hostile/retaliate/clown/clownhulk/honcmunculus, /mob/living/simple_animal/hostile/retaliate/clown/mutant/blob)
spawn_text = "climbs out of"
faction = list("clown")

View File

@@ -127,7 +127,7 @@
to_chat(user, "<span class='danger'>Throwing [pushed_mob] onto the table might hurt them!</span>")
return
var/added_passtable = FALSE
if(!pushed_mob.pass_flags & PASSTABLE)
if(!(pushed_mob.pass_flags & PASSTABLE))
added_passtable = TRUE
pushed_mob.pass_flags |= PASSTABLE
pushed_mob.Move(src.loc)

View File

@@ -43,6 +43,10 @@ GLOBAL_LIST_EMPTY(electrochromatic_window_lookup)
attack_hand_speed = CLICK_CD_MELEE
attack_hand_is_action = TRUE
explosion_flags = EXPLOSION_FLAG_HARD_OBSTACLE
wave_explosion_block = EXPLOSION_BLOCK_WINDOW
wave_explosion_multiply = EXPLOSION_DAMPEN_WINDOW
/// Electrochromatic status
var/electrochromatic_status = NOT_ELECTROCHROMATIC
/// Electrochromatic ID. Set the first character to ! to replace with a SSmapping generated pseudorandom obfuscated ID for mapping purposes.
@@ -111,6 +115,9 @@ GLOBAL_LIST_EMPTY(electrochromatic_window_lookup)
return TRUE
return FALSE
/obj/structure/window/wave_explosion_damage(power, datum/wave_explosion/explosion)
return EXPLOSION_POWER_STANDARD_SCALE_WINDOW_DAMAGE(power, explosion.window_shatter_mod)
/obj/structure/window/narsie_act()
add_atom_colour(NARSIE_WINDOW_COLOUR, FIXED_COLOUR_PRIORITY)
@@ -520,6 +527,8 @@ GLOBAL_LIST_EMPTY(electrochromatic_window_lookup)
armor = list("melee" = 50, "bullet" = 0, "laser" = 0, "energy" = 0, "bomb" = 25, "bio" = 100, "rad" = 100, "fire" = 80, "acid" = 100)
max_integrity = 50
explosion_block = 1
wave_explosion_block = EXPLOSION_BLOCK_REINFORCED_WINDOW
wave_explosion_multiply = EXPLOSION_DAMPEN_REINFORCED_WINDOW
glass_type = /obj/item/stack/sheet/rglass
rad_insulation = RAD_HEAVY_INSULATION
ricochet_chance_mod = 0.8
@@ -545,6 +554,8 @@ GLOBAL_LIST_EMPTY(electrochromatic_window_lookup)
armor = list("melee" = 75, "bullet" = 5, "laser" = 0, "energy" = 0, "bomb" = 45, "bio" = 100, "rad" = 100, "fire" = 99, "acid" = 100)
max_integrity = 150
explosion_block = 1
wave_explosion_block = EXPLOSION_BLOCK_BOROSILICATE_WINDOW
wave_explosion_multiply = EXPLOSION_DAMPEN_BOROSILICATE_WINDOW
glass_type = /obj/item/stack/sheet/plasmaglass
cleanable_type = /obj/effect/decal/cleanable/glass/plasma
rad_insulation = RAD_NO_INSULATION
@@ -570,6 +581,8 @@ GLOBAL_LIST_EMPTY(electrochromatic_window_lookup)
armor = list("melee" = 85, "bullet" = 20, "laser" = 0, "energy" = 0, "bomb" = 60, "bio" = 100, "rad" = 100, "fire" = 99, "acid" = 100)
max_integrity = 500
explosion_block = 2
wave_explosion_block = EXPLOSION_BLOCK_EXTREME
wave_explosion_multiply = EXPLOSION_BLOCK_EXTREME
glass_type = /obj/item/stack/sheet/plasmarglass
/obj/structure/window/plasma/reinforced/spawner/east
@@ -742,6 +755,8 @@ GLOBAL_LIST_EMPTY(electrochromatic_window_lookup)
max_integrity = 80
armor = list("melee" = 60, "bullet" = 25, "laser" = 0, "energy" = 0, "bomb" = 25, "bio" = 100, "rad" = 100, "fire" = 80, "acid" = 100)
explosion_block = 2 //fancy AND hard to destroy. the most useful combination.
wave_explosion_block = EXPLOSION_BLOCK_BOROSILICATE_WINDOW
wave_explosion_multiply = EXPLOSION_DAMPEN_BOROSILICATE_WINDOW
decon_speed = 40
glass_type = /obj/item/stack/tile/brass
glass_amount = 1

View File

@@ -6,6 +6,8 @@
blocks_air = 1
rad_flags = RAD_PROTECT_CONTENTS | RAD_NO_CONTAMINATE
rad_insulation = RAD_MEDIUM_INSULATION
wave_explosion_block = 10
wave_explosion_multiply = 0.75
/// How much we block yelling
var/yelling_resistance = 40
@@ -30,6 +32,7 @@
name = "wall"
icon = 'icons/turf/walls.dmi'
explosion_block = 50
wave_explosion_block = INFINITY
/turf/closed/indestructible/rust_heretic_act()
return

View File

@@ -12,6 +12,19 @@
clawfootstep = FOOTSTEP_HARD_CLAW
heavyfootstep = FOOTSTEP_GENERIC_HEAVY
/// Minimum explosion power to break tile
var/explosion_power_break_tile = EXPLOSION_POWER_FLOOR_TILE_BREAK
/// Minimum explosion power to break turf
var/explosion_power_break_turf = EXPLOSION_POWER_FLOOR_TURF_BREAK
//// Minimum explosion power to scrape away the floor
var/explosion_power_turf_scrape = EXPLOSION_POWER_FLOOR_TURF_SCRAPE
//// Shielded turfs are completely protected from anything under this
var/explosion_power_protect_shielded = EXPLOSION_POWER_FLOOR_SHIELDED_IMMUNITY
/// Starting from here, there's a chance for this to break
var/explosion_power_minimum_chance_break = EXPLOSION_POWER_FLOOR_MINIMUM_TURF_BREAK
/// Starting from here, +20% chance to break turf.
var/explosion_power_break_turf_bonus = EXPLOSION_POWER_FLOOR_TURF_BREAK_BONUS
var/icon_regular_floor = "floor" //used to remember what icon the tile should have by default
var/icon_plating = "plating"
thermal_conductivity = 0.004
@@ -98,6 +111,48 @@
src.break_tile()
src.hotspot_expose(1000,CELL_VOLUME)
/turf/open/floor/wave_ex_act(power, datum/wave_explosion/explosion, dir)
var/shielded = is_shielded()
. = ..()
if(shielded)
if(power < explosion_power_protect_shielded)
return
else
power -= explosion_power_protect_shielded
hotspot_expose(1000, CELL_VOLUME)
if(power < explosion_power_break_tile)
return
if(power < explosion_power_minimum_chance_break)
if(prob(33 + ((explosion_power_break_turf - power) / (explosion_power_break_turf - explosion_power_break_tile))))
break_tile()
return
if((power < explosion_power_turf_scrape) && ((power >= explosion_power_break_turf) || prob((1 - ((explosion_power_break_turf - power) / (explosion_power_break_turf - explosion_power_minimum_chance_break))) * 100 + ((power > explosion_power_break_turf_bonus)? 20 : 0))))
switch(pick(1, 2;75, 3))
if(1)
if(!length(baseturfs) || !ispath(baseturfs[baseturfs.len-1], /turf/open/floor))
ScrapeAway(flags = CHANGETURF_INHERIT_AIR)
ReplaceWithLattice()
else
ScrapeAway(2, flags = CHANGETURF_INHERIT_AIR)
if(prob(33))
new /obj/item/stack/sheet/metal(src)
return
if(2)
ScrapeAway(2, flags = CHANGETURF_INHERIT_AIR)
return
if(3)
if(prob(80))
ScrapeAway(flags = CHANGETURF_INHERIT_AIR)
return
else
break_tile()
hotspot_expose(1000,CELL_VOLUME)
if(prob(33))
new /obj/item/stack/sheet/metal(src)
if(power >= explosion_power_turf_scrape)
ScrapeAway(2, flags = CHANGETURF_INHERIT_AIR)
return
/turf/open/floor/is_shielded()
for(var/obj/structure/A in contents)
if(A.level == 3)

View File

@@ -12,6 +12,11 @@
sheet_amount = 1
girder_type = /obj/structure/girder/reinforced
explosion_block = 2
wave_explosion_block = EXPLOSION_BLOCK_BLAST_PROOF
wave_explosion_multiply = EXPLOSION_DAMPEN_BLAST_PROOF
explosion_power_to_scrape = EXPLOSION_POWER_RWALL_SCRAPE
explosion_power_to_dismantle = EXPLOSION_POWER_RWALL_DISMANTLE
explosion_power_minimum_chance_dismantle = EXPLOSION_POWER_RWALL_MINIMUM_DISMANTLE
rad_insulation = RAD_HEAVY_INSULATION
/turf/closed/wall/r_wall/deconstruction_hints(mob/user)

View File

@@ -6,6 +6,8 @@
icon = 'icons/turf/walls/wall.dmi'
icon_state = "wall"
explosion_block = 1
wave_explosion_block = EXPLOSION_BLOCK_WALL
wave_explosion_multiply = EXPLOSION_DAMPEN_WALL
flags_1 = DEFAULT_RICOCHET_1
flags_ricochet = RICOCHET_HARD
thermal_conductivity = WALL_HEAT_TRANSFER_COEFFICIENT
@@ -15,6 +17,14 @@
baseturfs = /turf/open/floor/plating
explosion_flags = EXPLOSION_FLAG_HARD_OBSTACLE
/// Explosion power to disintegrate the wall
var/explosion_power_to_scrape = EXPLOSION_POWER_WALL_SCRAPE
/// Explosion power to dismantle the wall
var/explosion_power_to_dismantle = EXPLOSION_POWER_WALL_DISMANTLE
/// Explosion power to potentially dismantle the wall
var/explosion_power_minimum_chance_dismantle = EXPLOSION_POWER_WALL_MINIMUM_DISMANTLE
var/hardness = 40 //lower numbers are harder. Used to determine the probability of a hulk smashing through.
var/slicing_duration = 100 //default time taken to slice the wall
var/sheet_type = /obj/item/stack/sheet/metal
@@ -91,6 +101,13 @@
if(!density)
..()
/turf/closed/wall/wave_ex_act(power, datum/wave_explosion/explosion, dir)
. = ..()
var/resultant_power = power * explosion.wall_destroy_mod
if(resultant_power >= explosion_power_to_scrape)
ScrapeAway()
else if((resultant_power >= explosion_power_to_dismantle) || ((resultant_power >= explosion_power_minimum_chance_dismantle) && prob(((resultant_power - explosion_power_minimum_chance_dismantle) / (explosion_power_to_dismantle - explosion_power_minimum_chance_dismantle)) * 100)))
dismantle_wall(prob((resultant_power - explosion_power_to_dismantle)/(explosion_power_to_scrape - explosion_power_to_dismantle)), TRUE)
/turf/closed/wall/blob_act(obj/structure/blob/B)
if(prob(50))

View File

@@ -8,6 +8,8 @@
temperature = TCMB
thermal_conductivity = OPEN_HEAT_TRANSFER_COEFFICIENT
heat_capacity = 700000
wave_explosion_multiply = EXPLOSION_DAMPEN_SPACE
wave_explosion_block = EXPLOSION_BLOCK_SPACE
var/destination_z
var/destination_x

View File

@@ -462,6 +462,24 @@ GLOBAL_LIST_EMPTY(station_turfs)
A.ex_act(severity, target)
CHECK_TICK
/turf/wave_ex_act(power, datum/wave_explosion/explosion, dir)
. = ..()
var/affecting_level
if(is_shielded())
affecting_level = 3
else if(intact)
affecting_level = 2
else
affecting_level = 1
var/atom/A
for(var/i in contents)
if(. <= 0)
return 0
A = i
if(!QDELETED(A) && A.level >= affecting_level)
. = A.wave_explode(., explosion, dir)
maptext = "[.]"
/turf/narsie_act(force, ignore_mobs, probability = 20)
. = (prob(probability) || force)
for(var/I in src)

View File

@@ -96,6 +96,7 @@ GLOBAL_LIST_INIT(admin_verbs_fun, list(
/client/proc/cmd_select_equipment,
/client/proc/cmd_admin_gib_self,
/client/proc/drop_bomb,
/client/proc/drop_wave_explosion,
/client/proc/set_dynex_scale,
/client/proc/drop_dynex_bomb,
/client/proc/cinematic,
@@ -550,6 +551,51 @@ GLOBAL_PROTECT(admin_verbs_hideable)
log_admin("[key_name(usr)] created an admin explosion at [epicenter.loc].")
SSblackbox.record_feedback("tally", "admin_verb", 1, "Drop Bomb") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
/client/proc/drop_wave_explosion()
set category = "Special Verbs"
set name = "Drop Wave Explosion"
set desc = "Cause an explosive shockwave at your location."
var/power = input(src, "Wave initial power", "Power", 50) as num|null
if(isnull(power))
return
var/falloff = input(src, "Wave innate falloff factor", "Falloff", EXPLOSION_DEFAULT_FALLOFF_MULTIPLY) as num|null
if(isnull(falloff))
return
falloff = max(0, falloff)
if(falloff > 1)
to_chat(src, "<span class='danger'>Aborting: Falloff cannot be higher tahn 1.")
return
var/constant = input(src, "Wave innate falloff constant", "Constant", EXPLOSION_DEFAULT_FALLOFF_SUBTRACT) as num|null
if(isnull(constant))
return
if(constant < 0)
to_chat(src, "<span class='danger'>Aborting: Falloff constant cannot be less than 0.")
return
var/fire = input(src, "Probability per tile of fire?", "Fire Probability", 0) as num|null
if(isnull(fire))
return
var/speed = input(src, "Speed in ticks to wait between cycles? 0 for fast as possible", "Wait", 0) as num|null
if(isnull(speed))
return
var/block_resistance = input(src, "DANGEROUS: Block resistance? USE 1 IF YOU DO NOT KNOW WHAT YOU ARE DOING.", "Block Negation", 1) as num|null
if(isnull(block_resistance))
return
block_resistance = max(0, block_resistance)
if(power > 500)
var/sure = alert(src, "Explosion power is extremely high. Are you absolutely sure?", "Uhh...", "No", "Yes")
if(sure != "Yes")
return
// point of no return
var/turf/target = get_turf(mob)
if(!target)
to_chat(src, "<span class='danger'>Cannot proceed. Not on turf.</span>")
return
message_admins("[ADMIN_LOOKUPFLW(usr)] creating an admin explosion at [target.loc].")
log_admin("[key_name(usr)] created an admin explosion at [target.loc].")
SSblackbox.record_feedback("tally", "admin_verb", 1, "Drop Wave Explosion") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
wave_explosion(target, power, falloff, constant, null, fire, speed = speed, block_resistance = block_resistance)
/client/proc/drop_dynex_bomb()
set category = "Admin.Fun"
set name = "Drop DynEx Bomb"

View File

@@ -104,7 +104,7 @@ GLOBAL_VAR(antag_prototypes)
var/datum/component/activity/activity = current.GetComponent(/datum/component/activity)
if(activity)
out += "Activity level: [activity.activity_level]<br>"
out += "Hasn't changed areas in approximately [activity.not_moved_counter] seconds"
out += "Hasn't changed areas in approximately [activity.not_moved_counter] seconds<br>"
var/special_statuses = get_special_statuses()
if(length(special_statuses))

View File

@@ -41,7 +41,6 @@
H.dna.features["horns"] = pick(GLOB.horns_list)
H.dna.features["frills"] = pick(GLOB.frills_list)
H.dna.features["spines"] = pick(GLOB.spines_list)
H.dna.features["body_markings"] = pick(GLOB.body_markings_list)
H.dna.features["insect_wings"] = pick(GLOB.insect_wings_list)
H.dna.features["deco_wings"] = pick(GLOB.deco_wings_list)
H.dna.features["insect_fluff"] = pick(GLOB.insect_fluffs_list)

View File

@@ -238,3 +238,9 @@
/proc/__nan()
var/list/L = json_decode("{\"value\":NaN}")
return L["value"]
/**
* Wrapper to return a copy of contents, as SDQL2 can't tell an internal list from a normal list.
*/
/atom/proc/_contents()
return contents.Copy()

View File

@@ -571,6 +571,26 @@ Traitors and the like can also be revived with the previous role mostly intact.
message_admins("[key_name_admin(src)] has created a command report")
SSblackbox.record_feedback("tally", "admin_verb", 1, "Create Command Report") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
/client/proc/cmd_admin_make_priority_announcement()
set category = "Admin.Events"
set name = "Make Priority Announcement"
if(!check_rights(R_ADMIN))
return
var/input = input(usr, "Enter a priority announcement. Ensure it makes sense IC.", "What?", "") as message|null
if(!input)
return
var/title = input(src, "What should the title be?", "What?","") as text|null
var/special_name = input(src, "Who is making the announcement?", "Who?", "") as text|null
priority_announce(input, title, sender_override = special_name)
log_admin("[key_name(src)] has sent a priority announcement: [input]")
message_admins("[key_name_admin(src)] has made a priority announcement")
SSblackbox.record_feedback("tally", "admin_verb", 1, "Make Priority Announcement") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
/client/proc/cmd_change_command_name()
set category = "Admin.Events"
set name = "Change Command Name"

View File

@@ -111,7 +111,7 @@ GLOBAL_LIST_EMPTY(antagonists)
var/datum/skill_modifier/job/M = GLOB.skill_modifiers[GET_SKILL_MOD_ID(A, type)]
if(istype(M))
M.name = "[name] Training"
owner.AddComponent(/datum/component/activity)
owner.current.AddComponent(/datum/component/activity)
SEND_SIGNAL(owner.current, COMSIG_MOB_ANTAG_ON_GAIN, src)
/datum/antagonist/proc/is_banned(mob/M)
@@ -164,14 +164,12 @@ GLOBAL_LIST_EMPTY(antagonists)
/datum/antagonist/proc/remove_blacklisted_quirks()
var/mob/living/L = owner.current
if(istype(L))
var/list/my_quirks = L.client?.prefs.all_quirks.Copy()
SSquirks.filter_quirks(my_quirks,blacklisted_quirks)
for(var/q in L.roundstart_quirks)
var/datum/quirk/Q = q
if(!(SSquirks.quirk_name_by_path(Q.type) in my_quirks))
if(Q.type in blacklisted_quirks)
if(initial(Q.antag_removal_text))
to_chat(L, "<span class='boldannounce'>[initial(Q.antag_removal_text)]</span>")
L.remove_quirk(Q.type)
qdel(Q)
//Returns the team antagonist belongs to if any.
/datum/antagonist/proc/get_team()

View File

@@ -680,6 +680,11 @@
glove_type = /obj/item/clothing/gloves/fingerless/pugilist/cling // just punch his head off dude
glove_name_simple = "bone gauntlets"
/obj/effect/proc_holder/changeling/gloves/gauntlets/sting_action(mob/living/user)
if(HAS_TRAIT(user, TRAIT_NOPUGILIST))
to_chat(user, "<span class='warning'>We would gain nothing by forming our fists into brute-force weapons when we are trained in precision martial arts!</span>")
return
/obj/item/clothing/gloves/fingerless/pugilist/cling // switches between lesser GotNS and Big Punchy Rib Breaky Hands
name = "hewn bone gauntlets"
icon_state = "ling_gauntlets"

View File

@@ -115,7 +115,7 @@
skewee.visible_message("<span class='warning'>[skewee] painfully slides back down [src].</span>")
if(skewee.stat >= UNCONSCIOUS)
return //by ratvar, no more spamming my deadchat, holy fuck
skewee.say("Oof, ouch owwie!!", forced = "fail brass skewer removal")
skewee.emote("pain")
return
skewee.visible_message("<span class='danger'>[skewee] comes free of [src] with a squelching pop!</span>", \
"<span class='boldannounce'>You come free of [src]!</span>")

View File

@@ -62,13 +62,24 @@
/datum/action/innate/heretic_shatter/IsAvailable()
if(IS_HERETIC(holder) || IS_HERETIC_MONSTER(holder))
return TRUE
return ..()
else
return FALSE
/datum/action/innate/heretic_shatter/Activate()
if(do_after(holder,10, target = holder))
var/turf/safe_turf = find_safe_turf(zlevels = sword.z, extended_safety_checks = TRUE)
if(!sword || QDELETED(sword))
return
if(!IsAvailable()) //Never trust the user.
return
var/swordz = (get_turf(sword))?.z //SHOULD usually have a turf but if it doesn't better be prepared.
if(!swordz)
to_chat(holder, "<span class='warning'>[sword] flickers but remains in place, as do you...</span>")
return
var/turf/safe_turf = find_safe_turf(zlevels = swordz, extended_safety_checks = TRUE)
if(!safe_turf)
to_chat(holder, "<span class='warning'>[sword] flickers but remains in place, as do you...</span>")
return
do_teleport(holder,safe_turf,forceMove = TRUE,channel=TELEPORT_CHANNEL_MAGIC)
to_chat(holder,"<span class='warning'>You feel a gust of energy flow through your body... the Rusted Hills heard your call...</span>")
qdel(sword)
@@ -218,8 +229,8 @@
flags_inv = NONE
flags_cover = NONE
desc = "Black like tar, doesn't reflect any light. Runic symbols line the outside, with each flash you lose comprehension of what you are seeing."
item_flags = EXAMINE_SKIP
armor = list("melee" = 30, "bullet" = 30, "laser" = 30,"energy" = 30, "bomb" = 15, "bio" = 0, "rad" = 0, "fire" = 0, "acid" = 0)
obj_flags = NONE | EXAMINE_SKIP
/obj/item/clothing/suit/hooded/cultrobes/void
name = "void cloak"
@@ -242,9 +253,10 @@
//We need to account for the hood shenanigans, and that way we can make sure items always fit, even if one of the slots is used by the fucking hood.
if(suittoggled)
to_chat(carbon_user,"<span class='notice'>The light shifts around you making the cloak invisible!</span>")
else
obj_flags |= EXAMINE_SKIP
else if(obj_flags & EXAMINE_SKIP) // ensures that it won't toggle visibility if raising the hood failed
to_chat(carbon_user,"<span class='notice'>The kaleidoscope of colours collapses around you, as the cloak shifts to visibility!</span>")
item_flags = suittoggled ? EXAMINE_SKIP : ~EXAMINE_SKIP
obj_flags ^= EXAMINE_SKIP
else
to_chat(carbon_user,"<span class='danger'>You can't force the hood onto your head!</span>")

View File

@@ -50,7 +50,7 @@
/obj/item/melee/touch_attack/mansus_fist/afterattack(atom/target, mob/user, proximity_flag, click_parameters)
if(!proximity_flag | target == user)
if(!proximity_flag || (target == user))
return
playsound(user, 'sound/items/welder.ogg', 75, TRUE)
if(ishuman(target))

View File

@@ -24,7 +24,7 @@
var/check = FALSE
if(ismob(target))
var/mob/living/mobster = target
if(!mobster.mob_biotypes & MOB_ROBOTIC)
if(!(mobster.mob_biotypes & MOB_ROBOTIC))
return FALSE
else
check = TRUE

View File

@@ -633,7 +633,7 @@ This is here to make the tiles around the station mininuke change when it's arme
AddComponent(/datum/component/stationloving, !fake)
/obj/item/disk/nuclear/process()
++process_tick
process_tick++
if(fake)
STOP_PROCESSING(SSobj, src)
CRASH("A fake nuke disk tried to call process(). Who the fuck and how the fuck")
@@ -650,7 +650,7 @@ This is here to make the tiles around the station mininuke change when it's arme
disk_comfort_level++
if(disk_comfort_level >= 2) //Sleep tight, disky.
if(process_tick % 30)
if(!(process_tick % 30))
visible_message("<span class='notice'>[src] sleeps soundly. Sleep tight, disky.</span>")
if(last_disk_move < world.time - 5000 && prob((world.time - 5000 - last_disk_move)*0.0001))
var/datum/round_event_control/operative/loneop = locate(/datum/round_event_control/operative) in SSevents.control

View File

@@ -177,6 +177,9 @@
/mob/living/simple_animal/revenant/ex_act(severity, target)
return 1 //Immune to the effects of explosions.
/mob/living/simple_animal/revenant/wave_ex_act(power, datum/wave_explosion/explosion, dir)
return power
/mob/living/simple_animal/revenant/blob_act(obj/structure/blob/B)
return //blah blah blobs aren't in tune with the spirit world, or something.

View File

@@ -84,6 +84,9 @@
if(slam_cooldown + slam_cooldown_time > world.time)
to_chat(src, "<span class='warning'>Your slam ability is still on cooldown!</span>")
return
if(!isopenturf(loc))
to_chat(src, "<span class='warning'>You need to be on open flooring to do that!")
return
face_atom(A)
var/mob/living/victim = A

View File

@@ -345,6 +345,14 @@
InsertAll("", each, GLOB.alldirs)
..()
/datum/asset/spritesheet/decals
name = "decals"
/datum/asset/spritesheet/decals/register()
for(var/each in list('icons/turf/decals.dmi'))
InsertAll("", each, GLOB.alldirs)
..()
/datum/asset/spritesheet/supplypods
name = "supplypods"

View File

@@ -44,7 +44,7 @@
return FALSE
/turf/proc/ImmediateCalculateAdjacentTurfs()
var/canpass = CANATMOSPASS(src, src)
var/canpass = CANATMOSPASS(src, src)
var/canvpass = CANVERTICALATMOSPASS(src, src)
for(var/direction in GLOB.cardinals_multiz)
var/turf/T = get_step_multiz(src, direction)
@@ -79,31 +79,27 @@
if (atmos_adjacent_turfs)
adjacent_turfs = atmos_adjacent_turfs.Copy()
else
adjacent_turfs = list()
return list() // don't bother checking diagonals, diagonals are going to be cardinal checks anyways.
if (!alldir)
return adjacent_turfs
var/turf/curloc = src
for (var/direction in GLOB.diagonals_multiz)
var/matchingDirections = 0
var/turf/S = get_step_multiz(curloc, direction)
if(!S)
var/turf/other
var/turf/mid
for (var/d in GLOB.diagonals)
other = get_step(src, d)
if(!other)
continue
// NS step
mid = get_step(src, NSCOMPONENT(d))
if((mid in adjacent_turfs) && (get_step(mid, EWCOMPONENT(d)) in adjacent_turfs))
adjacent_turfs += other
continue
// EW step
mid = get_step(src, EWCOMPONENT(d))
if((mid in adjacent_turfs) && (get_step(mid, NSCOMPONENT(d)) in adjacent_turfs))
adjacent_turfs += other
continue
for (var/checkDirection in GLOB.cardinals_multiz)
var/turf/checkTurf = get_step(S, checkDirection)
if(!S.atmos_adjacent_turfs || !S.atmos_adjacent_turfs[checkTurf])
continue
if (adjacent_turfs[checkTurf])
matchingDirections++
if (matchingDirections >= 2)
adjacent_turfs += S
break
return adjacent_turfs
/atom/proc/air_update_turf(command = 0)

View File

@@ -4,10 +4,10 @@ GLOBAL_DATUM(the_gateway, /obj/machinery/gateway/centerstation)
GLOBAL_LIST_EMPTY(gateway_destinations)
/**
* Corresponds to single entry in gateway control.
*
* Will NOT be added automatically to GLOB.gateway_destinations list.
*/
* Corresponds to single entry in gateway control.
*
* Will NOT be added automatically to GLOB.gateway_destinations list.
*/
/datum/gateway_destination
var/name = "Unknown Destination"
var/wait = 0 /// How long after roundstart this destination becomes active
@@ -85,7 +85,7 @@ GLOBAL_LIST_EMPTY(gateway_destinations)
. = "Exit gateway unpowered."
/datum/gateway_destination/gateway/get_target_turf()
return get_step(target_gateway.portal,SOUTH)
return get_step(target_gateway, SOUTH)
/datum/gateway_destination/gateway/post_transfer(atom/movable/AM)
. = ..()
@@ -144,7 +144,7 @@ GLOBAL_LIST_EMPTY(gateway_destinations)
name = "gateway"
desc = "A mysterious gateway built by unknown hands, it allows for faster than light travel to far-flung locations."
icon = 'icons/obj/machines/gateway.dmi'
icon_state = "off"
icon_state = "portal_frame"
resistance_flags = INDESTRUCTIBLE | LAVA_PROOF | FIRE_PROOF | UNACIDABLE | ACID_PROOF
// 3x2 offset by one row
@@ -171,10 +171,16 @@ GLOBAL_LIST_EMPTY(gateway_destinations)
var/datum/gateway_destination/target
/// bumper object, the thing that starts actual teleport
var/obj/effect/gateway_portal_bumper/portal
/// Visual object for handling the viscontents
/// DISABLED DUE TO BYOND BUG CAUSING STACK OVERFLOWS OF ANY HUMAN INSTANTIATION NEAR AN ACTIVATED GATEWAY.
/// Probably due to it referencing each other through the gateway (there's a deep loop, maybe BYOND isn't catching something when it usually would)
// var/obj/effect/gateway_portal_effect/portal_visuals
/obj/machinery/gateway/Initialize()
generate_destination()
update_icon()
// portal_visuals = new
// vis_contents += portal_visuals
return ..()
/obj/machinery/gateway/proc/generate_destination()
@@ -191,6 +197,7 @@ GLOBAL_LIST_EMPTY(gateway_destinations)
if(use_power == ACTIVE_POWER_USE)
use_power = IDLE_POWER_USE
update_icon()
// portal_visuals.reset_visuals()
/obj/machinery/gateway/process()
if((stat & (NOPOWER)) && use_power)
@@ -198,12 +205,6 @@ GLOBAL_LIST_EMPTY(gateway_destinations)
deactivate()
return
/obj/machinery/gateway/update_icon_state()
if(target)
icon_state = "on"
else
icon_state = "off"
/obj/machinery/gateway/safe_throw_at(atom/target, range, speed, mob/thrower, spin = TRUE, diagonals_first = FALSE, datum/callback/callback, force = MOVE_FORCE_STRONG, gentle = FALSE)
return
@@ -216,6 +217,7 @@ GLOBAL_LIST_EMPTY(gateway_destinations)
return
target = D
target.activate(destination)
// portal_visuals.setup_visuals(target)
generate_bumper()
use_power = ACTIVE_POWER_USE
update_icon()
@@ -307,7 +309,7 @@ GLOBAL_LIST_EMPTY(gateway_destinations)
try_to_connect(D)
return TRUE
if("deactivate")
if(G && G.target)
if(G?.target)
G.deactivate()
return TRUE
@@ -324,3 +326,39 @@ GLOBAL_LIST_EMPTY(gateway_destinations)
/obj/item/paper/fluff/gateway
info = "Congratulations,<br><br>Your station has been selected to carry out the Gateway Project.<br><br>The equipment will be shipped to you at the start of the next quarter.<br> You are to prepare a secure location to house the equipment as outlined in the attached documents.<br><br>--Nanotrasen Bluespace Research"
name = "Confidential Correspondence, Pg 1"
/obj/effect/gateway_portal_effect
appearance_flags = KEEP_TOGETHER|TILE_BOUND|PIXEL_SCALE
mouse_opacity = MOUSE_OPACITY_TRANSPARENT
vis_flags = VIS_INHERIT_ID
layer = GATEWAY_UNDERLAY_LAYER //Slightly lower than gateway itself
var/alpha_icon = 'icons/obj/machines/gateway.dmi'
var/alpha_icon_state = "portal_mask"
var/datum/gateway_destination/our_destination
/obj/effect/gateway_portal_effect/proc/setup_visuals(datum/gateway_destination/D)
our_destination = D
update_portal_filters()
/obj/effect/gateway_portal_effect/proc/reset_visuals()
our_destination = null
update_portal_filters()
/obj/effect/gateway_portal_effect/proc/update_portal_filters()
clear_filters()
vis_contents = null
if(!our_destination)
return
add_filter("portal_alpha", 1, list("type" = "alpha", "icon" = icon(alpha_icon, alpha_icon_state), "x" = 32, "y" = 32))
add_filter("portal_blur", 1, list("type" = "blur", "size" = 0.5))
add_filter("portal_ripple", 1, list("type" = "ripple", "size" = 2, "radius" = 1, "falloff" = 1, "y" = 7))
animate(get_filter("portal_ripple"), time = 1.3 SECONDS, loop = -1, easing = LINEAR_EASING, radius = 32)
var/turf/center_turf = our_destination.get_target_turf()
vis_contents += block(locate(center_turf.x - 1, center_turf.y - 1, center_turf.z), locate(center_turf.x + 1, center_turf.y + 1, center_turf.z))

View File

@@ -75,7 +75,7 @@
cost = 250
unit_name = "heart"
export_types = list(/obj/item/organ/heart)
exclude_types = list(/obj/item/organ/heart/cursed, /obj/item/organ/heart/cybernetic)
exclude_types = list(/obj/item/organ/heart/cursed, /obj/item/organ/heart/cybernetic/tier2, /obj/item/organ/heart/cybernetic/tier3)
/datum/export/organs/tongue
cost = 75
@@ -92,29 +92,30 @@
cost = 50 //can be replaced
unit_name = "stomach"
export_types = list(/obj/item/organ/stomach)
exclude_types = list(/obj/item/organ/stomach/cybernetic/tier2, /obj/item/organ/stomach/cybernetic/tier3)
/datum/export/organs/lungs
cost = 150
unit_name = "lungs"
export_types = list(/obj/item/organ/lungs)
exclude_types = list(/obj/item/organ/lungs/cybernetic, /obj/item/organ/lungs/cybernetic/upgraded)
export_types = list(/obj/item/organ/lungs,)
exclude_types = list(/obj/item/organ/lungs/cybernetic/tier2, /obj/item/organ/lungs/cybernetic/tier3)
/datum/export/organs/liver
cost = 175
unit_name = "liver"
export_types = list(/obj/item/organ/liver)
exclude_types = list(/obj/item/organ/liver/cybernetic, /obj/item/organ/liver/cybernetic/upgraded)
exclude_types = list(/obj/item/organ/liver/cybernetic/tier2, /obj/item/organ/liver/cybernetic/tier3)
/datum/export/organs/cybernetic
cost = 225
unit_name = "cybernetic organ"
export_types = list(/obj/item/organ/liver/cybernetic, /obj/item/organ/lungs/cybernetic, /obj/item/organ/eyes/robotic, /obj/item/organ/heart/cybernetic)
exclude_types = list(/obj/item/organ/lungs/cybernetic/upgraded, /obj/item/organ/liver/cybernetic/upgraded)
export_types = list(/obj/item/organ/liver/cybernetic/tier2, /obj/item/organ/lungs/cybernetic/tier2, /obj/item/organ/eyes/robotic/shield, /obj/item/organ/eyes/robotic/glow, /obj/item/organ/stomach/cybernetic/tier2, /obj/item/organ/heart/cybernetic/tier2)
exclude_types = list(/obj/item/organ/liver/cybernetic/tier3, /obj/item/organ/lungs/cybernetic/tier3, /obj/item/organ/eyes/robotic/xray, /obj/item/organ/eyes/robotic/thermals, /obj/item/organ/stomach/cybernetic/tier3, /obj/item/organ/heart/cybernetic/tier3)
/datum/export/organs/upgraded
cost = 275
unit_name = "upgraded cybernetic organ"
export_types = list(/obj/item/organ/lungs/cybernetic/upgraded, /obj/item/organ/liver/cybernetic/upgraded)
export_types = list(/obj/item/organ/liver/cybernetic/tier3, /obj/item/organ/lungs/cybernetic/tier3, /obj/item/organ/eyes/robotic/xray, /obj/item/organ/eyes/robotic/thermals, /obj/item/organ/stomach/cybernetic/tier3, /obj/item/organ/heart/cybernetic/tier3)
/datum/export/organs/tail // yeah have fun pulling this off someone without catching a bwoink
cost = 500

View File

@@ -176,6 +176,7 @@
/obj/effect/spawner/bundle/crate/surplusrifle,
/obj/item/storage/toolbox/ammo/surplus)
crate_name = "surplus military crate"
crate_type = /obj/structure/closet/crate/secure/soviet
/datum/supply_pack/security/armory/russian/fill(obj/structure/closet/crate/C)
for(var/i in 1 to 5)
@@ -239,7 +240,6 @@
desc = "Hey kid.. c'mere. Boss says we need to offload these, to any buyer, no questions asked. You pay us, we give you three of these guns, no strings attached. Locks are to ensure they get to PAYING customers."
cost = 2000
contraband = TRUE
can_private_buy = TRUE
contains = list(/obj/item/storage/fancy/cigarettes/derringer/smuggled,
/obj/item/storage/fancy/cigarettes/derringer/smuggled,
/obj/item/storage/fancy/cigarettes/derringer/smuggled,

View File

@@ -80,15 +80,15 @@
/datum/supply_pack/security/russianclothing
name = "Russian Surplus Clothing"
desc = "An old russian crate full of surplus armor that they used to use! Has two sets of bulletproff armor, a few union suits and some warm hats!"
desc = "An old russian crate full of surplus armor that they used to use! Has two sets of bulletproof armor, a few union suits and some warm hats!"
contraband = TRUE
cost = 5750 // Its basicly sec suits, good boots/gloves
contains = list(/obj/item/clothing/suit/armor/navyblue/russian,
/obj/item/clothing/suit/armor/navyblue/russian,
contains = list(/obj/item/clothing/under/syndicate/rus_army,
/obj/item/clothing/under/syndicate/rus_army,
/obj/item/clothing/shoes/combat,
/obj/item/clothing/shoes/combat,
/obj/item/clothing/head/ushanka,
/obj/item/clothing/head/ushanka,
/obj/item/clothing/head/helmet/rus_helmet,
/obj/item/clothing/head/helmet/rus_helmet,
/obj/item/clothing/suit/armor/bulletproof,
/obj/item/clothing/suit/armor/bulletproof,
/obj/item/clothing/head/helmet/alt,
@@ -98,23 +98,23 @@
/obj/item/clothing/mask/gas,
/obj/item/clothing/mask/gas)
crate_name = "surplus russian clothing"
crate_type = /obj/structure/closet/crate/internals
crate_type = /obj/structure/closet/crate/secure/soviet
/datum/supply_pack/security/russian_partisan
name = "Russian Partisan Gear"
desc = "An old russian partisan equipment crate, comes with a full russian outfit, a loaded surplus rifle and a second magazine."
contraband = TRUE
access = FALSE
cost = 6500
contains = list(/obj/item/clothing/suit/armor/navyblue/russian,
/obj/item/clothing/shoes/combat,
/obj/item/clothing/head/ushanka,
/obj/item/clothing/head/helmet/rus_helmet,
/obj/item/clothing/suit/armor/bulletproof,
/obj/item/clothing/head/helmet/alt,
/obj/item/clothing/gloves/tackler/combat/insulated,
/obj/item/clothing/under/syndicate/rus_army,
/obj/item/clothing/mask/gas)
crate_name = "surplus russian gear"
crate_type = /obj/structure/closet/crate/internals
crate_type = /obj/structure/closet/crate/secure/soviet
/datum/supply_pack/security/russian_partisan/fill(obj/structure/closet/crate/C)
..()
@@ -241,7 +241,7 @@
access = FALSE
access_any = list(ACCESS_SECURITY, ACCESS_FORENSICS_LOCKERS)
contains = list(/obj/item/ammo_box/c38/dumdum)
crate_name = ".38 match crate"
crate_name = ".38 dumdum crate"
/datum/supply_pack/security/match
name = ".38 Match Grade Speedloader"

View File

@@ -124,7 +124,7 @@ GLOBAL_LIST_EMPTY(preferences_datums)
var/eye_type = DEFAULT_EYES_TYPE //Eye type
var/split_eye_colors = FALSE
var/datum/species/pref_species = new /datum/species/human() //Mutant race
var/list/features = list("mcolor" = "FFFFFF", "mcolor2" = "FFFFFF", "mcolor3" = "FFFFFF", "tail_lizard" = "Smooth", "tail_human" = "None", "snout" = "Round", "horns" = "None", "horns_color" = "85615a", "ears" = "None", "wings" = "None", "wings_color" = "FFF", "frills" = "None", "deco_wings" = "None", "spines" = "None", "body_markings" = "None", "legs" = "Plantigrade", "insect_wings" = "Plain", "insect_fluff" = "None", "insect_markings" = "None", "arachnid_legs" = "Plain", "arachnid_spinneret" = "Plain", "arachnid_mandibles" = "Plain", "mam_body_markings" = "Plain", "mam_ears" = "None", "mam_snouts" = "None", "mam_tail" = "None", "mam_tail_animated" = "None", "xenodorsal" = "Standard", "xenohead" = "Standard", "xenotail" = "Xenomorph Tail", "taur" = "None", "genitals_use_skintone" = FALSE, "has_cock" = FALSE, "cock_shape" = DEF_COCK_SHAPE, "cock_length" = COCK_SIZE_DEF, "cock_diameter_ratio" = COCK_DIAMETER_RATIO_DEF, "cock_color" = "ffffff", "cock_taur" = FALSE, "has_balls" = FALSE, "balls_color" = "ffffff", "balls_shape" = DEF_BALLS_SHAPE, "balls_size" = BALLS_SIZE_DEF, "balls_cum_rate" = CUM_RATE, "balls_cum_mult" = CUM_RATE_MULT, "balls_efficiency" = CUM_EFFICIENCY, "has_breasts" = FALSE, "breasts_color" = "ffffff", "breasts_size" = BREASTS_SIZE_DEF, "breasts_shape" = DEF_BREASTS_SHAPE, "breasts_producing" = FALSE, "has_vag" = FALSE, "vag_shape" = DEF_VAGINA_SHAPE, "vag_color" = "ffffff", "has_womb" = FALSE, "balls_visibility" = GEN_VISIBLE_NO_UNDIES, "breasts_visibility"= GEN_VISIBLE_NO_UNDIES, "cock_visibility" = GEN_VISIBLE_NO_UNDIES, "vag_visibility" = GEN_VISIBLE_NO_UNDIES, "ipc_screen" = "Sunburst", "ipc_antenna" = "None", "flavor_text" = "", "silicon_flavor_text" = "", "ooc_notes" = "", "meat_type" = "Mammalian", "body_model" = MALE, "body_size" = RESIZE_DEFAULT_SIZE, "color_scheme" = OLD_CHARACTER_COLORING)
var/list/features = list("mcolor" = "FFFFFF", "mcolor2" = "FFFFFF", "mcolor3" = "FFFFFF", "tail_lizard" = "Smooth", "tail_human" = "None", "snout" = "Round", "horns" = "None", "horns_color" = "85615a", "ears" = "None", "wings" = "None", "wings_color" = "FFF", "frills" = "None", "deco_wings" = "None", "spines" = "None", "legs" = "Plantigrade", "insect_wings" = "Plain", "insect_fluff" = "None", "insect_markings" = "None", "arachnid_legs" = "Plain", "arachnid_spinneret" = "Plain", "arachnid_mandibles" = "Plain", "mam_body_markings" = list(), "mam_ears" = "None", "mam_snouts" = "None", "mam_tail" = "None", "mam_tail_animated" = "None", "xenodorsal" = "Standard", "xenohead" = "Standard", "xenotail" = "Xenomorph Tail", "taur" = "None", "genitals_use_skintone" = FALSE, "has_cock" = FALSE, "cock_shape" = DEF_COCK_SHAPE, "cock_length" = COCK_SIZE_DEF, "cock_diameter_ratio" = COCK_DIAMETER_RATIO_DEF, "cock_color" = "ffffff", "cock_taur" = FALSE, "has_balls" = FALSE, "balls_color" = "ffffff", "balls_shape" = DEF_BALLS_SHAPE, "balls_size" = BALLS_SIZE_DEF, "balls_cum_rate" = CUM_RATE, "balls_cum_mult" = CUM_RATE_MULT, "balls_efficiency" = CUM_EFFICIENCY, "has_breasts" = FALSE, "breasts_color" = "ffffff", "breasts_size" = BREASTS_SIZE_DEF, "breasts_shape" = DEF_BREASTS_SHAPE, "breasts_producing" = FALSE, "has_vag" = FALSE, "vag_shape" = DEF_VAGINA_SHAPE, "vag_color" = "ffffff", "has_womb" = FALSE, "balls_visibility" = GEN_VISIBLE_NO_UNDIES, "breasts_visibility"= GEN_VISIBLE_NO_UNDIES, "cock_visibility" = GEN_VISIBLE_NO_UNDIES, "vag_visibility" = GEN_VISIBLE_NO_UNDIES, "ipc_screen" = "Sunburst", "ipc_antenna" = "None", "flavor_text" = "", "silicon_flavor_text" = "", "ooc_notes" = "", "meat_type" = "Mammalian", "body_model" = MALE, "body_size" = RESIZE_DEFAULT_SIZE, "color_scheme" = OLD_CHARACTER_COLORING)
var/custom_speech_verb = "default" //if your say_mod is to be something other than your races
var/custom_tongue = "default" //if your tongue is to be something other than your races
@@ -514,7 +514,76 @@ GLOBAL_LIST_EMPTY(preferences_datums)
dat += "</td>"
mutant_category = 0
// rp marking selection
// assume you can only have mam markings or regular markings or none, never both
var/marking_type
if(parent.can_have_part("mam_body_markings"))
marking_type = "mam_body_markings"
if(marking_type)
dat += APPEARANCE_CATEGORY_COLUMN
dat += "<h3>[GLOB.all_mutant_parts[marking_type]]</h3>" // give it the appropriate title for the type of marking
dat += "<a href='?_src_=prefs;preference=marking_add;marking_type=[marking_type];task=input'>Add marking</a>"
// list out the current markings you have
if(length(features[marking_type]))
dat += "<table>"
var/list/markings = features[marking_type]
if(!islist(markings))
// something went terribly wrong
markings = list()
var/list/reverse_markings = reverseList(markings)
for(var/list/marking_list in reverse_markings)
var/marking_index = markings.Find(marking_list) // consider changing loop to go through indexes over lists instead of using Find here
var/limb_value = marking_list[1]
var/actual_name = GLOB.bodypart_names[num2text(limb_value)] // get the actual name from the bitflag representing the part the marking is applied to
var/color_marking_dat = ""
var/number_colors = 1
var/datum/sprite_accessory/mam_body_markings/S = GLOB.mam_body_markings_list[marking_list[2]]
var/matrixed_sections = S.covered_limbs[actual_name]
if(S && matrixed_sections)
// if it has nothing initialize it to white
if(length(marking_list) == 2)
var/first = "#FFFFFF"
var/second = "#FFFFFF"
var/third = "#FFFFFF"
if(features["mcolor"])
first = "#[features["mcolor"]]"
if(features["mcolor2"])
second = "#[features["mcolor2"]]"
if(features["mcolor3"])
third = "#[features["mcolor3"]]"
marking_list += list(list(first, second, third)) // just assume its 3 colours if it isnt it doesnt matter we just wont use the other values
// index magic
var/primary_index = 1
var/secondary_index = 2
var/tertiary_index = 3
switch(matrixed_sections)
if(MATRIX_GREEN)
primary_index = 2
if(MATRIX_BLUE)
primary_index = 3
if(MATRIX_RED_BLUE)
secondary_index = 2
if(MATRIX_GREEN_BLUE)
primary_index = 2
secondary_index = 3
// we know it has one matrixed section at minimum
color_marking_dat += "<span style='border: 1px solid #161616; background-color: [marking_list[3][primary_index]];'>&nbsp;&nbsp;&nbsp;</span>"
// if it has a second section, add it
if(matrixed_sections == MATRIX_RED_BLUE || matrixed_sections == MATRIX_GREEN_BLUE || matrixed_sections == MATRIX_RED_GREEN || matrixed_sections == MATRIX_ALL)
color_marking_dat += "<span style='border: 1px solid #161616; background-color: [marking_list[3][secondary_index]];'>&nbsp;&nbsp;&nbsp;</span>"
number_colors = 2
// if it has a third section, add it
if(matrixed_sections == MATRIX_ALL)
color_marking_dat += "<span style='border: 1px solid #161616; background-color: [marking_list[3][tertiary_index]];'>&nbsp;&nbsp;&nbsp;</span>"
number_colors = 3
color_marking_dat += " <a href='?_src_=prefs;preference=marking_color;marking_index=[marking_index];marking_type=[marking_type];number_colors=[number_colors];task=input'>Change</a><BR>"
dat += "<tr><td>[marking_list[2]] - [actual_name]</td> <td><a href='?_src_=prefs;preference=marking_down;task=input;marking_index=[marking_index];marking_type=[marking_type];'>&#708;</a> <a href='?_src_=prefs;preference=marking_up;task=input;marking_index=[marking_index];marking_type=[marking_type]'>&#709;</a> <a href='?_src_=prefs;preference=marking_remove;task=input;marking_index=[marking_index];marking_type=[marking_type]'>X</a> [color_marking_dat]</td></tr>"
dat += "</table>"
for(var/mutant_part in GLOB.all_mutant_parts)
if(mutant_part == "mam_body_markings")
continue
if(parent.can_have_part(mutant_part))
if(!mutant_category)
dat += APPEARANCE_CATEGORY_COLUMN
@@ -533,8 +602,6 @@ GLOBAL_LIST_EMPTY(preferences_datums)
if(accessory)
if(accessory.color_src == MATRIXED || accessory.color_src == MUTCOLORS || accessory.color_src == MUTCOLORS2 || accessory.color_src == MUTCOLORS3) //mutcolors1-3 are deprecated now, please don't rely on these in the future
var/mutant_string = accessory.mutant_part_string
if(istype(accessory, /datum/sprite_accessory/mam_body_markings) || istype(accessory, /datum/sprite_accessory/body_markings))
continue
var/primary_feature = "[mutant_string]_primary"
var/secondary_feature = "[mutant_string]_secondary"
var/tertiary_feature = "[mutant_string]_tertiary"
@@ -1726,13 +1793,11 @@ GLOBAL_LIST_EMPTY(preferences_datums)
pref_species = new newtype()
//let's ensure that no weird shit happens on species swapping.
custom_species = null
if(!parent.can_have_part("body_markings"))
features["body_markings"] = "None"
if(!parent.can_have_part("mam_body_markings"))
features["mam_body_markings"] = "None"
features["mam_body_markings"] = list()
if(parent.can_have_part("mam_body_markings"))
if(features["mam_body_markings"] == "None")
features["mam_body_markings"] = "Plain"
features["mam_body_markings"] = list()
if(parent.can_have_part("tail_lizard"))
features["tail_lizard"] = "Smooth"
if(pref_species.id == "felinid")
@@ -1961,14 +2026,6 @@ GLOBAL_LIST_EMPTY(preferences_datums)
if(new_spines)
features["spines"] = new_spines
if("body_markings")
var/new_body_markings
new_body_markings = input(user, "Choose your character's body markings:", "Character Preference") as null|anything in GLOB.body_markings_list
if(new_body_markings)
features["body_markings"] = new_body_markings
if(new_body_markings != "None")
features["mam_body_markings"] = "None"
if("legs")
var/new_legs
new_legs = input(user, "Choose your character's legs:", "Character Preference") as null|anything in GLOB.legs_list
@@ -2088,26 +2145,6 @@ GLOBAL_LIST_EMPTY(preferences_datums)
if(new_ears)
features["mam_ears"] = new_ears
if("mam_body_markings")
var/list/snowflake_markings_list = list()
for(var/path in GLOB.mam_body_markings_list)
var/datum/sprite_accessory/mam_body_markings/instance = GLOB.mam_body_markings_list[path]
if(istype(instance, /datum/sprite_accessory))
var/datum/sprite_accessory/S = instance
if(!show_mismatched_markings && S.recommended_species && !S.recommended_species.Find(pref_species.id))
continue
if((!S.ckeys_allowed) || (S.ckeys_allowed.Find(user.client.ckey)))
snowflake_markings_list[S.name] = path
var/new_mam_body_markings
new_mam_body_markings = input(user, "Choose your character's body markings:", "Character Preference") as null|anything in snowflake_markings_list
if(new_mam_body_markings)
features["mam_body_markings"] = new_mam_body_markings
if(new_mam_body_markings != "None")
features["body_markings"] = "None"
else if(new_mam_body_markings == "None")
features["mam_body_markings"] = "Plain"
features["body_markings"] = "None"
//Xeno Bodyparts
if("xenohead")//Head or caste type
var/new_head
@@ -2133,7 +2170,7 @@ GLOBAL_LIST_EMPTY(preferences_datums)
features["xenodorsal"] = new_dors
//every single primary/secondary/tertiary colouring done at once
if("xenodorsal_primary","xenodorsal_secondary","xenodorsal_tertiary","xhead_primary","xhead_secondary","xhead_tertiary","tail_primary","tail_secondary","tail_tertiary","insect_markings_primary","insect_markings_secondary","insect_markings_tertiary","body_markings_primary","body_markings_secondary","body_markings_tertiary","insect_fluff_primary","insect_fluff_secondary","insect_fluff_tertiary","ears_primary","ears_secondary","ears_tertiary","frills_primary","frills_secondary","frills_tertiary","ipc_antenna_primary","ipc_antenna_secondary","ipc_antenna_tertiary","taur_primary","taur_secondary","taur_tertiary","snout_primary","snout_secondary","snout_tertiary","spines_primary","spines_secondary","spines_tertiary", "mam_body_markings_primary", "mam_body_markings_secondary", "mam_body_markings_tertiary")
if("xenodorsal_primary","xenodorsal_secondary","xenodorsal_tertiary","xhead_primary","xhead_secondary","xhead_tertiary","tail_primary","tail_secondary","tail_tertiary","insect_markings_primary","insect_markings_secondary","insect_markings_tertiary","insect_fluff_primary","insect_fluff_secondary","insect_fluff_tertiary","ears_primary","ears_secondary","ears_tertiary","frills_primary","frills_secondary","frills_tertiary","ipc_antenna_primary","ipc_antenna_secondary","ipc_antenna_tertiary","taur_primary","taur_secondary","taur_tertiary","snout_primary","snout_secondary","snout_tertiary","spines_primary","spines_secondary","spines_tertiary", "mam_body_markings_primary", "mam_body_markings_secondary", "mam_body_markings_tertiary")
var/the_feature = features[href_list["preference"]]
if(!the_feature)
features[href_list["preference"]] = "FFFFFF"
@@ -2390,6 +2427,111 @@ GLOBAL_LIST_EMPTY(preferences_datums)
var/selected_body_sprite = input(user, "Choose your desired body sprite", "Character Preference") as null|anything in pref_species.allowed_limb_ids
if(selected_body_sprite)
chosen_limb_id = selected_body_sprite //this gets sanitized before loading
if("marking_down")
// move the specified marking down
var/index = text2num(href_list["marking_index"])
var/marking_type = href_list["marking_type"]
if(index && marking_type && features[marking_type] && index != length(features[marking_type]))
var/index_down = index + 1
var/markings = features[marking_type]
var/first_marking = markings[index]
var/second_marking = markings[index_down]
markings[index] = second_marking
markings[index_down] = first_marking
if("marking_up")
// move the specified marking up
var/index = text2num(href_list["marking_index"])
var/marking_type = href_list["marking_type"]
if(index && marking_type && features[marking_type] && index != 1)
var/index_up = index - 1
var/markings = features[marking_type]
var/first_marking = markings[index]
var/second_marking = markings[index_up]
markings[index] = second_marking
markings[index_up] = first_marking
if("marking_remove")
// move the specified marking up
var/index = text2num(href_list["marking_index"])
var/marking_type = href_list["marking_type"]
if(index && marking_type && features[marking_type])
// because linters are just absolutely awful:
var/list/L = features[marking_type]
L.Cut(index, index + 1)
if("marking_add")
// add a marking
var/marking_type = href_list["marking_type"]
if(marking_type && features[marking_type])
var/selected_limb = input(user, "Choose the limb to apply to.", "Character Preference") as null|anything in list("Head", "Chest", "Left Arm", "Right Arm", "Left Leg", "Right Leg", "All")
if(selected_limb)
var/list/marking_list = GLOB.mam_body_markings_list
var/list/snowflake_markings_list = list()
for(var/path in marking_list)
var/datum/sprite_accessory/S = marking_list[path]
if(istype(S))
if(istype(S, /datum/sprite_accessory/mam_body_markings))
var/datum/sprite_accessory/mam_body_markings/marking = S
if(!(selected_limb in marking.covered_limbs) && selected_limb != "All")
continue
if((!S.ckeys_allowed) || (S.ckeys_allowed.Find(user.client.ckey)))
snowflake_markings_list[S.name] = path
var/selected_marking = input(user, "Select the marking to apply to the limb.") as null|anything in snowflake_markings_list
if(selected_marking)
if(selected_limb != "All")
var/limb_value = text2num(GLOB.bodypart_values[selected_limb])
features[marking_type] += list(list(limb_value, selected_marking))
else
var/datum/sprite_accessory/mam_body_markings/S = marking_list[selected_marking]
for(var/limb in S.covered_limbs)
var/limb_value = text2num(GLOB.bodypart_values[limb])
features[marking_type] += list(list(limb_value, selected_marking))
if("marking_color")
var/index = text2num(href_list["marking_index"])
var/marking_type = href_list["marking_type"]
if(index && marking_type && features[marking_type])
// work out the input options to show the user
var/list/options = list("Primary")
var/number_colors = text2num(href_list["number_colors"])
var/color_number = 1 // 1-3 which color are we editing
if(number_colors >= 2)
options += "Secondary"
if(number_colors == 3)
options += "Tertiary"
var/color_option = input(user, "Select the colour you wish to edit") as null|anything in options
if(color_option)
if(color_option == "Secondary") color_number = 2
if(color_option == "Tertiary") color_number = 3
// perform some magic on the color number
var/list/marking_list = features[marking_type][index]
var/datum/sprite_accessory/mam_body_markings/S = GLOB.mam_body_markings_list[marking_list[2]]
var/matrixed_sections = S.covered_limbs[GLOB.bodypart_names[num2text(marking_list[1])]]
if(color_number == 1)
switch(matrixed_sections)
if(MATRIX_GREEN)
color_number = 2
if(MATRIX_BLUE)
color_number = 3
else if(color_number == 2)
switch(matrixed_sections)
if(MATRIX_RED_BLUE)
color_number = 3
if(MATRIX_GREEN_BLUE)
color_number = 3
var/color_list = features[marking_type][index][3]
var/new_marking_color = input(user, "Choose your character's marking color:", "Character Preference","#"+color_list[color_number]) as color|null
if(new_marking_color)
var/temp_hsv = RGBtoHSV(new_marking_color)
if((MUTCOLORS_PARTSONLY in pref_species.species_traits) || ReadHSV(temp_hsv)[3] >= ReadHSV(MINIMUM_MUTANT_COLOR)[3]) // mutantcolors must be bright, but only if they affect the skin
color_list[color_number] = "#[sanitize_hexcolor(new_marking_color, 6)]"
else
to_chat(user, "<span class='danger'>Invalid color. Your color is not bright enough.</span>")
else
switch(href_list["preference"])
//CITADEL PREFERENCES EDIT - I can't figure out how to modularize these, so they have to go here. :c -Pooj

View File

@@ -5,7 +5,7 @@
// You do not need to raise this if you are adding new values that have sane defaults.
// Only raise this value when changing the meaning/format/name/layout of an existing value
// where you would want the updater procs below to run
#define SAVEFILE_VERSION_MAX 50
#define SAVEFILE_VERSION_MAX 52
/*
SAVEFILE UPDATING/VERSIONING - 'Simplified', or rather, more coder-friendly ~Carn
@@ -283,7 +283,7 @@ SAVEFILE UPDATING/VERSIONING - 'Simplified', or rather, more coder-friendly ~Car
qdel(temporary_gear_item)
//it's double packed into a list because += will union the two lists contents
S["loadout"] = safe_json_encode(loadout_data)
S["loadout"] = loadout_data
if(current_version < 48) //unlockable loadout items but we need to clear bad data from a mistake
S["unlockable_loadout"] = list()
@@ -295,6 +295,51 @@ SAVEFILE UPDATING/VERSIONING - 'Simplified', or rather, more coder-friendly ~Car
L -= ROLE_SYNDICATE
S["be_special"] << L
if(current_version < 51) //humans can have digi legs now, make sure they dont default to them or human players will murder me in my sleep
if(S["species"] == SPECIES_HUMAN)
features["legs"] = "Plantigrade"
if(current_version < 52) // rp markings means markings are now stored as a list, lizard markings now mam like the rest
var/marking_type
var/species_id = S["species"]
var/datum/species/actual_species = GLOB.species_datums[species_id]
// convert lizard markings to lizard markings
if(species_id == SPECIES_LIZARD && S["feature_lizard_body_markings"])
features["mam_body_markings"] = features["body_markings"]
// convert mam body marking data to the new rp marking data
if(actual_species.mutant_bodyparts["mam_body_markings"] && S["feature_mam_body_markings"]) marking_type = "feature_mam_body_markings"
if(marking_type)
var/old_marking_value = S[marking_type]
var/list/color_list = list("#FFFFFF","#FFFFFF","#FFFFFF")
if(S["feature_mcolor"]) color_list[1] = "#" + S["feature_mcolor"]
if(S["feature_mcolor2"]) color_list[2] = "#" + S["feature_mcolor2"]
if(S["feature_mcolor3"]) color_list[3] = "#" + S["feature_mcolor3"]
var/list/marking_list = list()
for(var/part in list(ARM_LEFT, ARM_RIGHT, LEG_LEFT, LEG_RIGHT, CHEST, HEAD))
var/list/copied_color_list = color_list.Copy()
var/datum/sprite_accessory/mam_body_markings/mam_marking = GLOB.mam_body_markings_list[old_marking_value]
var/part_name = GLOB.bodypart_names[num2text(part)]
if(length(mam_marking.covered_limbs) && mam_marking.covered_limbs[part_name])
var/matrixed_sections = mam_marking.covered_limbs[part_name]
// just trust me this is fine
switch(matrixed_sections)
if(MATRIX_GREEN)
copied_color_list[1] = copied_color_list[2]
if(MATRIX_BLUE)
copied_color_list[1] = copied_color_list[3]
if(MATRIX_RED_BLUE)
copied_color_list[2] = copied_color_list[3]
if(MATRIX_GREEN_BLUE)
copied_color_list[1] = copied_color_list[2]
copied_color_list[2] = copied_color_list[3]
marking_list += list(list(part, old_marking_value, copied_color_list))
features["mam_body_markings"] = marking_list
/datum/preferences/proc/load_path(ckey,filename="preferences.sav")
if(!ckey)
return
@@ -579,7 +624,7 @@ SAVEFILE UPDATING/VERSIONING - 'Simplified', or rather, more coder-friendly ~Car
var/savefile/S = new /savefile(path)
if(!S)
return FALSE
features = list("mcolor" = "FFFFFF", "mcolor2" = "FFFFFF", "mcolor3" = "FFFFFF", "tail_lizard" = "Smooth", "tail_human" = "None", "snout" = "Round", "horns" = "None", "horns_color" = "85615a", "ears" = "None", "wings" = "None", "wings_color" = "FFF", "frills" = "None", "deco_wings" = "None", "spines" = "None", "body_markings" = "None", "legs" = "Plantigrade", "insect_wings" = "Plain", "insect_fluff" = "None", "insect_markings" = "None", "arachnid_legs" = "Plain", "arachnid_spinneret" = "Plain", "arachnid_mandibles" = "Plain", "mam_body_markings" = "Plain", "mam_ears" = "None", "mam_snouts" = "None", "mam_tail" = "None", "mam_tail_animated" = "None", "xenodorsal" = "Standard", "xenohead" = "Standard", "xenotail" = "Xenomorph Tail", "taur" = "None", "genitals_use_skintone" = FALSE, "has_cock" = FALSE, "cock_shape" = DEF_COCK_SHAPE, "cock_length" = COCK_SIZE_DEF, "cock_diameter_ratio" = COCK_DIAMETER_RATIO_DEF, "cock_color" = "ffffff", "cock_taur" = FALSE, "has_balls" = FALSE, "balls_color" = "ffffff", "balls_shape" = DEF_BALLS_SHAPE, "balls_size" = BALLS_SIZE_DEF, "balls_cum_rate" = CUM_RATE, "balls_cum_mult" = CUM_RATE_MULT, "balls_efficiency" = CUM_EFFICIENCY, "has_breasts" = FALSE, "breasts_color" = "ffffff", "breasts_size" = BREASTS_SIZE_DEF, "breasts_shape" = DEF_BREASTS_SHAPE, "breasts_producing" = FALSE, "has_vag" = FALSE, "vag_shape" = DEF_VAGINA_SHAPE, "vag_color" = "ffffff", "has_womb" = FALSE, "balls_visibility" = GEN_VISIBLE_NO_UNDIES, "breasts_visibility"= GEN_VISIBLE_NO_UNDIES, "cock_visibility" = GEN_VISIBLE_NO_UNDIES, "vag_visibility" = GEN_VISIBLE_NO_UNDIES, "ipc_screen" = "Sunburst", "ipc_antenna" = "None", "flavor_text" = "", "silicon_flavor_text" = "", "ooc_notes" = "", "meat_type" = "Mammalian", "body_model" = MALE, "body_size" = RESIZE_DEFAULT_SIZE, "color_scheme" = OLD_CHARACTER_COLORING)
features = list("mcolor" = "FFFFFF", "mcolor2" = "FFFFFF", "mcolor3" = "FFFFFF", "tail_lizard" = "Smooth", "tail_human" = "None", "snout" = "Round", "horns" = "None", "horns_color" = "85615a", "ears" = "None", "wings" = "None", "wings_color" = "FFF", "frills" = "None", "deco_wings" = "None", "spines" = "None", "legs" = "Plantigrade", "insect_wings" = "Plain", "insect_fluff" = "None", "insect_markings" = "None", "arachnid_legs" = "Plain", "arachnid_spinneret" = "Plain", "arachnid_mandibles" = "Plain", "mam_body_markings" = "Plain", "mam_ears" = "None", "mam_snouts" = "None", "mam_tail" = "None", "mam_tail_animated" = "None", "xenodorsal" = "Standard", "xenohead" = "Standard", "xenotail" = "Xenomorph Tail", "taur" = "None", "genitals_use_skintone" = FALSE, "has_cock" = FALSE, "cock_shape" = DEF_COCK_SHAPE, "cock_length" = COCK_SIZE_DEF, "cock_diameter_ratio" = COCK_DIAMETER_RATIO_DEF, "cock_color" = "ffffff", "cock_taur" = FALSE, "has_balls" = FALSE, "balls_color" = "ffffff", "balls_shape" = DEF_BALLS_SHAPE, "balls_size" = BALLS_SIZE_DEF, "balls_cum_rate" = CUM_RATE, "balls_cum_mult" = CUM_RATE_MULT, "balls_efficiency" = CUM_EFFICIENCY, "has_breasts" = FALSE, "breasts_color" = "ffffff", "breasts_size" = BREASTS_SIZE_DEF, "breasts_shape" = DEF_BREASTS_SHAPE, "breasts_producing" = FALSE, "has_vag" = FALSE, "vag_shape" = DEF_VAGINA_SHAPE, "vag_color" = "ffffff", "has_womb" = FALSE, "balls_visibility" = GEN_VISIBLE_NO_UNDIES, "breasts_visibility"= GEN_VISIBLE_NO_UNDIES, "cock_visibility" = GEN_VISIBLE_NO_UNDIES, "vag_visibility" = GEN_VISIBLE_NO_UNDIES, "ipc_screen" = "Sunburst", "ipc_antenna" = "None", "flavor_text" = "", "silicon_flavor_text" = "", "ooc_notes" = "", "meat_type" = "Mammalian", "body_model" = MALE, "body_size" = RESIZE_DEFAULT_SIZE, "color_scheme" = OLD_CHARACTER_COLORING)
S.cd = "/"
if(!slot)
@@ -649,7 +694,6 @@ SAVEFILE UPDATING/VERSIONING - 'Simplified', or rather, more coder-friendly ~Car
S["feature_lizard_horns"] >> features["horns"]
S["feature_lizard_frills"] >> features["frills"]
S["feature_lizard_spines"] >> features["spines"]
S["feature_lizard_body_markings"] >> features["body_markings"]
S["feature_lizard_legs"] >> features["legs"]
S["feature_human_tail"] >> features["tail_human"]
S["feature_human_ears"] >> features["ears"]
@@ -718,7 +762,8 @@ SAVEFILE UPDATING/VERSIONING - 'Simplified', or rather, more coder-friendly ~Car
S["feature_genitals_use_skintone"] >> features["genitals_use_skintone"]
S["feature_mcolor2"] >> features["mcolor2"]
S["feature_mcolor3"] >> features["mcolor3"]
S["feature_mam_body_markings"] >> features["mam_body_markings"]
// note safe json decode will runtime the first time it migrates but this is fine and it solves itself don't worry about it if you see it error
features["mam_body_markings"] = safe_json_decode(S["feature_mam_body_markings"])
S["feature_mam_tail"] >> features["mam_tail"]
S["feature_mam_ears"] >> features["mam_ears"]
S["feature_mam_tail_animated"] >> features["mam_tail_animated"]
@@ -848,7 +893,6 @@ SAVEFILE UPDATING/VERSIONING - 'Simplified', or rather, more coder-friendly ~Car
features["ears"] = sanitize_inlist(features["ears"], GLOB.ears_list)
features["frills"] = sanitize_inlist(features["frills"], GLOB.frills_list)
features["spines"] = sanitize_inlist(features["spines"], GLOB.spines_list)
features["body_markings"] = sanitize_inlist(features["body_markings"], GLOB.body_markings_list)
features["legs"] = sanitize_inlist(features["legs"], GLOB.legs_list, "Plantigrade")
features["deco_wings"] = sanitize_inlist(features["deco_wings"], GLOB.deco_wings_list, "None")
features["insect_fluff"] = sanitize_inlist(features["insect_fluff"], GLOB.insect_fluffs_list)
@@ -1017,7 +1061,6 @@ SAVEFILE UPDATING/VERSIONING - 'Simplified', or rather, more coder-friendly ~Car
WRITE_FILE(S["feature_human_ears"] , features["ears"])
WRITE_FILE(S["feature_lizard_frills"] , features["frills"])
WRITE_FILE(S["feature_lizard_spines"] , features["spines"])
WRITE_FILE(S["feature_lizard_body_markings"] , features["body_markings"])
WRITE_FILE(S["feature_lizard_legs"] , features["legs"])
WRITE_FILE(S["feature_deco_wings"] , features["deco_wings"])
WRITE_FILE(S["feature_horns_color"] , features["horns_color"])

View File

@@ -3,7 +3,7 @@
set desc = "Authorizes your account in the panic bunker of any servers connected to this function."
set category = "OOC"
if(!(prefs.db_flags & DB_FLAG_AGE_CONFIRMATION_INCOMPLETE))
if(prefs.db_flags & DB_FLAG_AGE_CONFIRMATION_INCOMPLETE)
to_chat(src, "<span class='danger'>You are not age verified.</span>")
return

View File

@@ -358,6 +358,12 @@
..()
user.cure_blind("blindfold_[REF(src)]")
/obj/item/clothing/glasses/fakeblindfold
name = "thin blindfold"
desc = "Covers the eyes, but not thick enough to obscure vision. Mostly for aesthetic."
icon_state = "blindfoldwhite"
item_state = "blindfoldwhite"
/obj/item/clothing/glasses/sunglasses/blindfold/white
name = "blind personnel blindfold"
desc = "Indicates that the wearer suffers from blindness."

View File

@@ -37,14 +37,19 @@
/obj/item/clothing/gloves/fingerless/pugilist/equipped(mob/user, slot)
. = ..()
if(slot == SLOT_GLOVES)
use_buffs(user, TRUE)
wornonce = TRUE
if((HAS_TRAIT(user, TRAIT_NOPUGILIST)))
to_chat(user, "<span class='danger'>What purpose is there to don the weapons of pugilism if you're already well-practiced in martial arts? Mixing arts is blasphemous!</span>")
return
use_buffs(user, TRUE)
/obj/item/clothing/gloves/fingerless/pugilist/dropped(mob/user)
. = ..()
if(wornonce)
use_buffs(user, FALSE)
wornonce = FALSE
if((HAS_TRAIT(user, TRAIT_NOPUGILIST)))
return
use_buffs(user, FALSE)
/obj/item/clothing/gloves/fingerless/pugilist/proc/use_buffs(mob/user, buff)
if(buff) // tarukaja
@@ -67,6 +72,7 @@
H.dna.species.punchdamagehigh -= enhancement
H.dna.species.punchdamagelow -= enhancement
H.dna.species.punchwoundbonus -= wound_enhancement
H.dna?.species?.attack_sound_override = null
if(!silent)
to_chat(user, "<span class='warning'>With [src] off of your arms, you feel less ready to punch things.</span>")
@@ -223,6 +229,50 @@
parry_cooldown = 0
parry_failed_clickcd_duration = 0
/obj/item/clothing/gloves/fingerless/pugilist/mauler
name = "mauler gauntlets"
desc = "Plastitanium gauntlets coated in a thick nano-weave carbon material and implanted with nanite injectors that boost the wielder's strength six-fold."
icon_state = "mauler_gauntlets"
item_state = "mauler_gauntlets"
transfer_prints = FALSE
body_parts_covered = ARMS|HANDS
cold_protection = ARMS|HANDS
min_cold_protection_temperature = GLOVES_MIN_TEMP_PROTECT
max_heat_protection_temperature = GLOVES_MAX_TEMP_PROTECT
armor = list("melee" = 30, "bullet" = 30, "laser" = 10, "energy" = 10, "bomb" = 55, "bio" = 15, "rad" = 15, "fire" = 80, "acid" = 50)
siemens_coefficient = 0
permeability_coefficient = 0.05
strip_delay = 80
enhancement = 12 // same as the changeling gauntlets but without changeling utility
wound_enhancement = 12
silent = TRUE
inherited_trait = TRAIT_CHUNKYFINGERS // your fingers are fat because the gloves are
secondary_trait = TRAIT_MAULER // commit table slam
/obj/item/clothing/gloves/fingerless/pugilist/mauler/equipped(mob/user, slot)
. = ..()
if(slot == SLOT_GLOVES)
wornonce = TRUE
if((HAS_TRAIT(user, TRAIT_NOPUGILIST)))
return
use_mauls(user, TRUE)
/obj/item/clothing/gloves/fingerless/pugilist/mauler/dropped(mob/user)
. = ..()
if(wornonce)
wornonce = FALSE
if((HAS_TRAIT(user, TRAIT_NOPUGILIST)))
return
use_mauls(user, FALSE)
/obj/item/clothing/gloves/fingerless/pugilist/mauler/proc/use_mauls(mob/user, maul)
if(maul)
if(ishuman(user))
var/mob/living/carbon/human/H = user
H.dna?.species?.attack_sound_override = 'sound/weapons/mauler_punch.ogg'
if(silent)
to_chat(H, "<span class='danger'>You feel prickles around your wrists as [src] cling to them - strength courses through your veins!</span>")
/obj/item/clothing/gloves/botanic_leather
name = "botanist's leather gloves"
desc = "These leather gloves protect against thorns, barbs, prickles, spikes and other harmful objects of floral origin. They're also quite warm."
@@ -253,7 +303,6 @@
armor = list("melee" = 0, "bullet" = 0, "laser" = 0, "energy" = 0, "bomb" = 0, "bio" = 0, "rad" = 0, "fire" = 80, "acid" = 50)
strip_mod = 1.5
/obj/item/clothing/gloves/bracer
name = "bone bracers"
desc = "For when you're expecting to get slapped on the wrist. Offers modest protection to your arms."

View File

@@ -89,10 +89,8 @@
/datum/outfit/pirate/space
suit = /obj/item/clothing/suit/space/pirate
head = /obj/item/clothing/head/helmet/space/pirate/bandana
mask = /obj/item/clothing/mask/breath
suit_store = /obj/item/tank/internals/oxygen
ears = /obj/item/radio/headset/syndicate
id = /obj/item/card/id
id = /obj/item/card/id/pirate
/datum/outfit/pirate/space/captain
head = /obj/item/clothing/head/helmet/space/pirate

View File

@@ -535,3 +535,9 @@
to_chat(user, "<span class='notice'>You insert [I] into [src].</span>")
B.use(10)
icon_state = initial(icon_state)
/obj/item/clothing/shoes/swagshoes
name = "swag shoes"
desc = "They got me for my foams!"
icon_state = "SwagShoes"
item_state = "SwagShoes"

View File

@@ -145,7 +145,7 @@
/obj/item/clothing/suit/armor/riot
name = "riot suit"
desc = "A suit of semi-flexible polycarbonate body armor with heavy padding to protect against melee attacks. Helps the wearer resist shoving in close quarters."
icon_state = "riot"
icon_state = "swat"
item_state = "swat_suit"
body_parts_covered = CHEST|GROIN|LEGS|FEET|ARMS|HANDS
cold_protection = CHEST|GROIN|LEGS|FEET|ARMS|HANDS

View File

@@ -355,3 +355,10 @@
name = "Sakura Kimono'"
icon_state = "sakura_kimono"
item_state = "sakura_kimono"
/obj/item/clothing/under/costume/swagoutfit
name = "Swag outfit"
desc = "Why don't you go secure some bitches?"
icon_state = "SwagOutfit"
item_state = "SwagOutfit"
can_adjust = FALSE

View File

@@ -61,7 +61,7 @@
originMachine.visible_message("[originMachine] beeps and seems lifeless.")
kill()
return
vendingMachines = listclearnulls(vendingMachines)
listclearnulls(vendingMachines)
if(!vendingMachines.len) //if every machine is infected
for(var/obj/machinery/vending/upriser in infectedMachines)
if(prob(70) && !QDELETED(upriser))

View File

@@ -206,6 +206,7 @@
icon_screen = "syndishuttle"
icon_keyboard = "syndie_key"
light_color = LIGHT_COLOR_RED
req_access = list(ACCESS_SYNDICATE)
possible_destinations = "pirateship_away;pirateship_home;pirateship_custom"
/obj/machinery/computer/camera_advanced/shuttle_docker/syndicate/pirate
@@ -214,8 +215,8 @@
shuttleId = "pirateship"
lock_override = CAMERA_LOCK_STATION
shuttlePortId = "pirateship_custom"
x_offset = 9
y_offset = 0
x_offset = 11
y_offset = 1
see_hidden = FALSE
/obj/docking_port/mobile/pirate
@@ -224,11 +225,7 @@
rechargeTime = 3 MINUTES
/obj/machinery/suit_storage_unit/pirate
suit_type = /obj/item/clothing/suit/space
helmet_type = /obj/item/clothing/head/helmet/space
mask_type = /obj/item/clothing/mask/breath
storage_type = /obj/item/tank/jetpack/void
// storage_type = /obj/item/tank/internals/oxygen
storage_type = /obj/item/tank/jetpack/carbondioxide
/obj/machinery/loot_locator
name = "Booty Locator"

View File

@@ -17,24 +17,29 @@
announceWhen = rand(4, 60)
supernova = new
SSsun.suns += supernova
if(prob(20))
power = rand(5,100) / 100
else
power = rand(5,5000) / 100
switch(rand(1,5))
if(1)
power = rand(5,100) / 100
if(2)
power = rand(5,500) / 100
if(3)
power = rand(5,1000) / 100
if(4, 5)
power = rand(5,5000) / 100
supernova.azimuth = rand(0, 359)
supernova.power_mod = 0
/datum/round_event/supernova/announce()
var/message = "Our tachyon-doppler array has detected a supernova in your vicinity. Peak flux from the supernova estimated to be [round(power,0.1)] times current solar flux. [power > 1 ? "Short burts of radiation may be possible, so please prepare accordingly." : ""]"
var/message = "[station_name()]: Our tachyon-doppler array has detected a supernova in your vicinity. Peak flux from the supernova estimated to be [round(power,0.1)] times current solar flux; if the supernova is close to your sun in the sky, your solars may receive this as a power boost.[power > 1 ? " Short burts of radiation may be possible, so please prepare accordingly." : ""] We hope you enjoy the light."
if(prob(power * 25))
priority_announce(message)
priority_announce(message, sender_override = "Nanotrasen Meteorology Division")
else
print_command_report(message)
/datum/round_event/supernova/start()
supernova.power_mod = 0.001 * power
var/explosion_size = rand(1000000000, 999999999)
var/explosion_size = rand(1000000000, 10000000000)
var/turf/epicenter = get_turf_in_angle(supernova.azimuth, SSmapping.get_station_center(), round(world.maxx * 0.45))
for(var/array in GLOB.doppler_arrays)
var/obj/machinery/doppler_array/A = array
@@ -51,13 +56,15 @@
supernova.power_mod = min(supernova.power_mod*1.2, power)
if(activeFor > endWhen-10)
supernova.power_mod /= 4
if(prob(round(supernova.power_mod)) && prob(5) && storm_count < 5 && !SSweather.get_weather_by_type(/datum/weather/rad_storm))
if(prob(round(supernova.power_mod*2)) && prob(3) && storm_count < 5 && !SSweather.get_weather_by_type(/datum/weather/rad_storm))
SSweather.run_weather(/datum/weather/rad_storm/supernova)
storm_count++
/datum/round_event/supernova/end()
SSsun.suns -= supernova
qdel(supernova)
priority_announce("The supernova's flux is now negligible. Radiation storms have ceased. Have a pleasant shift, [station_name()], and thank you for bearing with nature.",
sender_override = "Nanotrasen Meteorology Division")
/datum/weather/rad_storm/supernova
weather_duration_lower = 50

Some files were not shown because too many files have changed in this diff Show More