Merge pull request #5 from Citadel-Station-13/master

k
This commit is contained in:
YakumoChen
2020-07-09 02:36:47 -04:00
committed by GitHub
147 changed files with 4016 additions and 2372 deletions
+121 -105
View File
@@ -2,156 +2,172 @@
"a" = (
/turf/template_noop,
/area/template_noop)
"b" = (
/turf/closed/wall/mineral/cult,
/area/ruin/unpowered)
"c" = (
/obj/structure/healingfountain,
/turf/open/floor/engine/cult,
/turf/open/floor/carpet/purple,
/area/ruin/unpowered)
"d" = (
/obj/structure/fluff/divine/conduit,
/turf/open/floor/engine/cult,
/turf/open/floor/mineral/plasma,
/area/ruin/unpowered)
"e" = (
/obj/structure/sacrificealtar,
/turf/open/floor/engine/cult,
/turf/open/floor/carpet/purple,
/area/ruin/unpowered)
"f" = (
/turf/open/floor/engine/cult,
/mob/living/simple_animal/butterfly,
/turf/open/floor/carpet/purple,
/area/ruin/unpowered)
"g" = (
/mob/living/simple_animal/butterfly,
/turf/open/floor/engine/cult,
/turf/open/floor/carpet/red,
/area/ruin/unpowered)
"h" = (
/obj/structure/fans/tiny/invisible,
/turf/open/floor/engine/cult,
/turf/open/floor/carpet/red,
/area/ruin/unpowered)
"u" = (
/turf/open/floor/carpet/purple,
/area/ruin/unpowered)
"G" = (
/turf/closed/wall/mineral/cult{
sheet_amount = 0
},
/area/ruin/unpowered)
"J" = (
/mob/living/simple_animal/butterfly,
/turf/open/floor/carpet/royalblack,
/area/ruin/unpowered)
"T" = (
/turf/open/floor/carpet/royalblack,
/area/ruin/unpowered)
"U" = (
/turf/open/floor/carpet/red,
/area/ruin/unpowered)
(1,1,1) = {"
a
b
b
b
b
b
b
b
b
b
b
b
b
b
b
b
G
G
G
G
G
G
G
G
G
G
G
G
G
G
G
"}
(2,1,1) = {"
a
b
G
d
f
f
U
T
T
T
J
T
T
T
T
T
T
d
f
f
d
f
f
d
f
f
d
b
G
"}
(3,1,1) = {"
b
b
G
G
e
g
f
f
U
d
g
f
f
f
f
g
f
g
f
b
U
d
U
U
d
U
U
u
G
"}
(4,1,1) = {"
b
G
c
f
f
f
f
f
f
f
f
f
f
f
f
f
U
T
u
T
T
u
T
T
u
T
T
T
h
"}
(5,1,1) = {"
b
b
G
G
e
f
f
f
f
g
f
f
f
f
f
f
f
b
U
d
g
U
d
U
U
d
U
U
u
G
"}
(6,1,1) = {"
a
b
G
d
g
f
U
T
T
T
J
T
T
T
T
T
T
d
f
f
d
f
f
d
f
g
d
b
G
"}
(7,1,1) = {"
a
b
b
b
b
b
b
b
b
b
b
b
b
b
b
b
G
G
G
G
G
G
G
G
G
G
G
G
G
G
G
"}
@@ -42,6 +42,10 @@
"ak" = (
/obj/structure/toilet,
/obj/effect/turf_decal/sand,
/obj/item/reagent_containers/food/drinks/beer/light{
pixel_x = 9
},
/obj/effect/decal/cleanable/vomit/old,
/turf/open/floor/plating,
/area/ruin/powered/beach)
"al" = (
@@ -191,7 +195,9 @@
/turf/open/floor/plasteel,
/area/ruin/powered/beach)
"aM" = (
/obj/structure/reagent_dispensers/beerkeg,
/obj/structure/reagent_dispensers/beerkeg{
reagent_id = /datum/reagent/consumable/ethanol/beer/light
},
/turf/open/floor/wood,
/area/ruin/powered/beach)
"aN" = (
@@ -371,7 +377,7 @@
/turf/open/floor/plating/beach/sand,
/area/ruin/powered/beach)
"bP" = (
/obj/item/reagent_containers/food/drinks/beer,
/obj/item/reagent_containers/food/drinks/beer/light,
/turf/open/floor/plating/beach/sand,
/area/ruin/powered/beach)
"bQ" = (
@@ -463,6 +469,7 @@
/obj/item/storage/box/drinkingglasses,
/obj/item/storage/box/beakers,
/obj/item/storage/box/donkpockets,
/obj/item/soap,
/turf/open/floor/plating,
/area/ruin/powered/beach)
"hY" = (
@@ -537,6 +544,14 @@
},
/turf/open/floor/pod/light,
/area/ruin/powered/beach)
"rV" = (
/obj/effect/turf_decal/sand,
/obj/item/reagent_containers/food/drinks/beer/light{
pixel_y = -3;
pixel_x = -9
},
/turf/open/floor/plating,
/area/ruin/powered/beach)
"sy" = (
/obj/effect/turf_decal/caution{
dir = 4
@@ -590,6 +605,11 @@
/obj/effect/turf_decal/sand,
/turf/open/floor/pod/light,
/area/ruin/powered/beach)
"Gu" = (
/obj/structure/table/wood,
/obj/item/reagent_containers/food/drinks/beer/light,
/turf/open/floor/wood,
/area/ruin/powered/beach)
"HC" = (
/obj/structure/rack,
/obj/item/clothing/shoes/sandal,
@@ -964,7 +984,7 @@ ar
ar
ar
ar
ar
bP
ar
bR
bT
@@ -984,7 +1004,7 @@ as
aw
aC
aC
aP
Gu
aW
aK
Ga
@@ -1108,7 +1128,7 @@ aa
aa
bW
ak
au
rV
aj
aE
aC
@@ -219,6 +219,7 @@
/obj/structure/alien/weeds,
/obj/effect/decal/cleanable/blood/gibs,
/mob/living/simple_animal/hostile/alien/drone,
/obj/structure/alien/weeds/node,
/turf/open/floor/plating/asteroid/basalt/lava_land_surface,
/area/ruin/unpowered/xenonest)
"aZ" = (
@@ -535,6 +536,11 @@
/obj/effect/mob_spawn/alien/corpse/humanoid/queen,
/turf/open/floor/plating/asteroid/basalt/lava_land_surface,
/area/ruin/unpowered/xenonest)
"wA" = (
/obj/structure/alien/weeds,
/obj/structure/alien/weeds/node,
/turf/open/floor/plating/asteroid/basalt/lava_land_surface,
/area/ruin/unpowered/xenonest)
"yf" = (
/obj/structure/alien/weeds/node,
/mob/living/simple_animal/hostile/alien/sentinel,
@@ -551,6 +557,12 @@
/obj/effect/mob_spawn/alien/corpse/humanoid/drone,
/turf/open/floor/plating/asteroid/basalt/lava_land_surface,
/area/ruin/unpowered/xenonest)
"QG" = (
/obj/structure/alien/weeds,
/obj/structure/bed/nest,
/obj/structure/alien/weeds/node,
/turf/open/floor/plating/asteroid/basalt/lava_land_surface,
/area/ruin/unpowered/xenonest)
"Uh" = (
/obj/structure/alien/weeds,
/obj/item/xenos_claw,
@@ -683,7 +695,7 @@ ac
ac
aj
ac
am
QG
ac
ac
ac
@@ -800,7 +812,7 @@ ac
ac
ac
ac
ag
wA
ag
ag
ar
@@ -884,7 +896,7 @@ aa
(7,1,1) = {"
ab
ac
ag
wA
ag
ag
ag
@@ -917,7 +929,7 @@ ac
ac
ZT
ac
ag
wA
ag
ac
ab
@@ -1349,7 +1361,7 @@ ar
lG
ag
ag
ag
wA
ad
ag
ag
@@ -1555,7 +1567,7 @@ ag
ac
aF
ag
ag
ar
ag
ag
ar
@@ -1603,7 +1615,7 @@ ao
ah
ac
ag
ag
wA
ag
ag
pE
@@ -1742,7 +1754,7 @@ ag
ag
ag
ag
ac
aw
ar
ag
bD
@@ -1791,9 +1803,9 @@ ac
ac
ac
ac
wA
ag
ag
ac
aw
ar
ag
bD
@@ -1828,7 +1840,7 @@ ac
ac
ag
Uh
ag
wA
aZ
be
bo
@@ -203,6 +203,12 @@
/area/ruin/powered/snow_biodome)
"aR" = (
/obj/structure/flora/tree/pine/xmas,
/obj/item/a_gift{
pixel_y = -5
},
/obj/item/a_gift{
pixel_x = 6
},
/turf/open/floor/plating/asteroid/snow{
initial_gas_mix = "o2=22;n2=82;TEMP=180"
},
@@ -295,6 +301,12 @@
},
/turf/open/floor/pod/dark,
/area/ruin/powered/snow_biodome)
"gy" = (
/obj/item/toy/snowball,
/turf/open/floor/plating/asteroid/snow{
initial_gas_mix = "o2=22;n2=82;TEMP=180"
},
/area/ruin/powered/snow_biodome)
"gz" = (
/obj/structure/chair/stool,
/turf/open/floor/pod/dark,
@@ -316,6 +328,13 @@
},
/turf/open/floor/pod/dark,
/area/ruin/powered/snow_biodome)
"rl" = (
/obj/structure/flora/bush,
/obj/item/toy/snowball,
/turf/open/floor/plating/asteroid/snow{
initial_gas_mix = "o2=22;n2=82;TEMP=180"
},
/area/ruin/powered/snow_biodome)
"tb" = (
/obj/effect/mapping_helpers/no_lava,
/turf/open/floor/plating/asteroid/basalt/lava_land_surface,
@@ -361,6 +380,11 @@
/obj/structure/closet/secure_closet/freezer/fridge,
/turf/open/floor/pod/dark,
/area/ruin/powered/snow_biodome)
"IQ" = (
/obj/structure/table/wood,
/obj/item/reagent_containers/food/drinks/mug,
/turf/open/floor/wood,
/area/ruin/powered/snow_biodome)
"JZ" = (
/obj/structure/table,
/obj/machinery/microwave,
@@ -380,6 +404,7 @@
/area/ruin/powered/snow_biodome)
"Oj" = (
/obj/structure/table,
/obj/item/reagent_containers/food/drinks/mug,
/turf/open/floor/pod/dark,
/area/ruin/powered/snow_biodome)
"PD" = (
@@ -407,6 +432,7 @@
"QK" = (
/obj/structure/table,
/obj/item/storage/fancy/cigarettes/cigpack_carp,
/obj/item/reagent_containers/food/drinks/mug,
/turf/open/floor/pod/dark,
/area/ruin/powered/snow_biodome)
"QN" = (
@@ -417,6 +443,13 @@
/obj/effect/decal/cleanable/oil,
/turf/open/floor/pod/dark,
/area/ruin/powered/snow_biodome)
"SL" = (
/obj/structure/flora/grass/both,
/obj/item/toy/snowball,
/turf/open/floor/plating/asteroid/snow{
initial_gas_mix = "o2=22;n2=82;TEMP=180"
},
/area/ruin/powered/snow_biodome)
"Ub" = (
/obj/structure/filingcabinet,
/turf/open/floor/pod/dark,
@@ -577,7 +610,7 @@ aB
ak
ak
ak
aI
rl
by
ak
ak
@@ -740,7 +773,7 @@ aI
az
ak
ak
ak
gy
ak
ak
aI
@@ -916,7 +949,7 @@ Wg
ag
ah
as
aw
IQ
aA
aA
at
@@ -924,7 +957,7 @@ aM
aP
ak
ak
aQ
SL
ak
ak
az
@@ -1077,7 +1110,7 @@ Wg
an
Wg
ay
ak
gy
ak
ak
ak
@@ -1114,6 +1147,7 @@ aI
ak
ap
ak
gy
ak
ak
ak
@@ -1121,8 +1155,7 @@ ak
ak
ak
ak
ak
ak
gy
ak
aI
ak
@@ -1240,7 +1273,7 @@ ak
ak
az
ak
ak
gy
ak
bB
ak
@@ -11,7 +11,7 @@
"d" = (
/turf/closed/wall/rust,
/area/ruin/unpowered)
"e" = (
"f" = (
/obj/structure/mirror{
desc = "This mirror has been shattered. It looks like the bad luck energies spilling from it are taking immediate effect on your surroundings!";
icon_state = "mirror_broke";
@@ -22,17 +22,6 @@
/obj/effect/decal/cleanable/blood,
/turf/open/floor/plating,
/area/ruin/unpowered)
"f" = (
/obj/structure/mirror{
desc = "This mirror has been shattered. It looks like the bad luck energies spilling from it are taking immediate effect on your surroundings!";
icon_state = "mirror_broke";
pixel_x = 28;
broken = 1
},
/turf/open/floor/plating{
icon_state = "panelscorched"
},
/area/ruin/unpowered)
"g" = (
/obj/effect/decal/cleanable/blood/tracks,
/obj/structure/mirror{
@@ -58,11 +47,12 @@
/obj/structure/mirror{
desc = "This mirror has been shattered. It looks like the bad luck energies spilling from it are taking immediate effect on your surroundings!";
icon_state = "mirror_broke";
pixel_y = 28;
pixel_x = 28;
broken = 1
},
/obj/item/kitchen/knife/envy,
/turf/open/floor/plating,
/turf/open/floor/plating{
icon_state = "panelscorched"
},
/area/ruin/unpowered)
"l" = (
/obj/structure/mirror{
@@ -106,6 +96,16 @@
/obj/effect/mapping_helpers/no_lava,
/turf/open/floor/plating/asteroid/basalt/lava_land_surface,
/area/lavaland/surface/outdoors)
"T" = (
/obj/structure/mirror{
desc = "This mirror has been shattered. It looks like the bad luck energies spilling from it are taking immediate effect on your surroundings!";
icon_state = "mirror_broke";
pixel_y = 28;
broken = 1
},
/obj/item/kitchen/knife/envy,
/turf/open/floor/plating,
/area/ruin/unpowered)
(1,1,1) = {"
a
@@ -125,14 +125,8 @@ a
a
a
a
a
a
a
"}
(2,1,1) = {"
a
a
c
c
c
c
@@ -167,9 +161,6 @@ d
d
d
d
d
d
d
c
a
"}
@@ -178,16 +169,13 @@ c
c
d
d
d
e
f
g
g
g
m
m
m
m
m
o
m
j
@@ -201,14 +189,11 @@ d
d
d
d
d
h
h
i
i
i
i
i
h
i
i
@@ -224,10 +209,7 @@ d
d
d
d
d
k
i
i
T
i
i
i
@@ -245,12 +227,9 @@ d
d
d
d
d
i
i
i
j
i
n
i
i
@@ -266,8 +245,7 @@ c
c
d
d
d
f
k
j
l
l
@@ -276,8 +254,6 @@ l
l
l
l
l
l
j
d
c
@@ -299,9 +275,6 @@ d
d
d
d
d
d
d
c
a
"}
@@ -322,8 +295,5 @@ c
c
c
c
c
c
c
a
"}
@@ -20,7 +20,7 @@
/turf/open/floor/plasteel/freezer,
/area/ruin/powered/gluttony)
"h" = (
/obj/item/veilrender/vealrender,
/obj/item/trash/boritos,
/turf/open/floor/plasteel/freezer,
/area/ruin/powered/gluttony)
"i" = (
@@ -65,6 +65,7 @@
/obj/machinery/light/small{
dir = 1
},
/obj/item/trash/plate/alt,
/turf/open/floor/plasteel/freezer,
/area/ruin/powered/gluttony)
"v" = (
@@ -84,6 +85,28 @@
},
/turf/open/floor/plasteel/freezer,
/area/ruin/powered/gluttony)
"B" = (
/obj/item/veilrender/vealrender,
/turf/open/floor/plasteel/freezer,
/area/ruin/powered/gluttony)
"E" = (
/obj/machinery/light/small,
/obj/item/trash/cheesie,
/turf/open/floor/plasteel/freezer,
/area/ruin/powered/gluttony)
"G" = (
/obj/item/trash/waffles,
/turf/open/floor/plasteel/freezer,
/area/ruin/powered/gluttony)
"L" = (
/obj/machinery/light/small,
/obj/item/trash/plate/alt,
/turf/open/floor/plasteel/freezer,
/area/ruin/powered/gluttony)
"N" = (
/obj/item/trash/cheesie,
/turf/open/floor/plasteel/freezer,
/area/ruin/powered/gluttony)
"R" = (
/turf/closed/indestructible/riveted/uranium,
/area/ruin/powered/gluttony)
@@ -92,6 +115,10 @@
/obj/structure/fans/tiny/invisible,
/turf/open/floor/plasteel/freezer,
/area/ruin/powered/gluttony)
"Z" = (
/obj/item/trash/plate/alt,
/turf/open/floor/plasteel/freezer,
/area/ruin/powered/gluttony)
(1,1,1) = {"
a
@@ -191,7 +218,7 @@ b
b
c
R
h
j
i
o
R
@@ -213,9 +240,9 @@ b
b
c
R
i
i
v
h
G
L
R
c
b
@@ -258,7 +285,7 @@ c
c
R
t
i
N
m
R
c
@@ -305,10 +332,10 @@ g
g
i
p
i
G
z
l
i
Z
R
c
b
@@ -324,10 +351,10 @@ g
g
g
g
B
n
i
i
i
h
i
i
i
@@ -346,12 +373,12 @@ r
g
g
g
i
N
g
i
l
A
i
Z
q
R
c
@@ -368,7 +395,7 @@ R
R
R
g
i
h
v
R
R
@@ -391,7 +418,7 @@ c
R
r
i
i
q
R
c
c
@@ -435,7 +462,7 @@ c
R
j
i
v
E
R
c
b
@@ -20,9 +20,7 @@
/area/ruin/powered/greed)
"f" = (
/obj/structure/cursed_slot_machine,
/turf/open/floor/carpet{
icon_state = "carpetsymbol"
},
/turf/open/floor/carpet/black,
/area/ruin/powered/greed)
"g" = (
/obj/structure/table/wood/poker,
@@ -41,11 +39,6 @@
icon_state = "carpetsymbol"
},
/area/ruin/powered/greed)
"i" = (
/turf/open/floor/carpet{
icon_state = "carpetsymbol"
},
/area/ruin/powered/greed)
"j" = (
/obj/structure/table/wood/poker,
/obj/item/coin/adamantine,
@@ -57,28 +50,28 @@
/obj/machinery/computer/arcade/battle{
set_obj_flags = "EMAGGED"
},
/turf/open/floor/engine/cult,
/turf/open/floor/carpet/black,
/area/ruin/powered/greed)
"l" = (
/obj/item/coin/gold,
/turf/open/floor/engine/cult,
/turf/open/floor/carpet/black,
/area/ruin/powered/greed)
"m" = (
/turf/open/floor/engine/cult,
/turf/open/floor/carpet/black,
/area/ruin/powered/greed)
"n" = (
/obj/structure/table/wood/poker,
/obj/item/stack/spacecash/c1000,
/turf/open/floor/engine/cult,
/turf/open/floor/carpet,
/area/ruin/powered/greed)
"o" = (
/obj/item/storage/bag/money,
/turf/open/floor/engine/cult,
/turf/open/floor/carpet/black,
/area/ruin/powered/greed)
"p" = (
/obj/structure/table/wood/poker,
/obj/item/stack/ore/gold,
/turf/open/floor/engine/cult,
/turf/open/floor/carpet,
/area/ruin/powered/greed)
"q" = (
/obj/structure/table/wood/poker,
@@ -88,19 +81,19 @@
brightness = 3;
dir = 8
},
/turf/open/floor/engine/cult,
/turf/open/floor/carpet,
/area/ruin/powered/greed)
"r" = (
/obj/structure/table/wood/poker,
/obj/item/stack/spacecash/c500,
/obj/item/stack/spacecash/c100,
/obj/item/stack/spacecash/c1000,
/turf/open/floor/engine/cult,
/turf/open/floor/carpet,
/area/ruin/powered/greed)
"s" = (
/obj/structure/table/wood/poker,
/obj/item/stack/spacecash/c200,
/turf/open/floor/engine/cult,
/turf/open/floor/carpet,
/area/ruin/powered/greed)
"u" = (
/obj/structure/table/wood/poker,
@@ -110,25 +103,30 @@
/obj/machinery/light/small{
dir = 4
},
/turf/open/floor/engine/cult,
/turf/open/floor/carpet,
/area/ruin/powered/greed)
"v" = (
/obj/item/coin/gold,
/obj/machinery/light/small,
/turf/open/floor/engine/cult,
/turf/open/floor/carpet/black,
/area/ruin/powered/greed)
"w" = (
/obj/item/storage/bag/money,
/obj/machinery/light/small,
/turf/open/floor/engine/cult,
/turf/open/floor/carpet/black,
/area/ruin/powered/greed)
"H" = (
/turf/open/floor/carpet/purple,
/area/ruin/powered/greed)
"J" = (
/obj/machinery/door/airlock/gold,
/obj/structure/fans/tiny/invisible,
/turf/open/floor/engine/cult,
/turf/open/floor/carpet/purple,
/area/ruin/powered/greed)
"W" = (
/turf/closed/wall/mineral/cult,
/turf/closed/wall/mineral/cult{
sheet_amount = 0
},
/area/ruin/powered/greed)
(1,1,1) = {"
@@ -337,7 +335,7 @@ a
c
W
f
i
m
m
l
m
@@ -345,7 +343,7 @@ o
m
m
m
m
H
J
a
a
@@ -21,6 +21,7 @@
"f" = (
/obj/structure/table/wood,
/obj/item/storage/box/cups,
/obj/item/reagent_containers/food/snacks/lollipop,
/turf/open/floor/wood{
initial_gas_mix = "o2=14;n2=23;TEMP=300"
},
@@ -181,11 +182,19 @@
initial_gas_mix = "o2=14;n2=23;TEMP=300"
},
/area/ruin/unpowered)
"B" = (
/obj/effect/decal/cleanable/dirt,
/obj/item/trash/candy,
/turf/open/floor/wood{
initial_gas_mix = "o2=14;n2=23;TEMP=300"
},
/area/ruin/unpowered)
"C" = (
/obj/structure/chair/wood/wings{
dir = 4
},
/obj/effect/decal/cleanable/dirt,
/obj/item/reagent_containers/food/snacks/candy,
/turf/open/floor/plating{
initial_gas_mix = "o2=14;n2=23;TEMP=300"
},
@@ -214,6 +223,7 @@
/area/ruin/unpowered)
"G" = (
/obj/structure/table/wood,
/obj/item/reagent_containers/food/snacks/lollipop,
/turf/open/floor/wood{
initial_gas_mix = "o2=14;n2=23;TEMP=300"
},
@@ -288,6 +298,35 @@
initial_gas_mix = "o2=14;n2=23;TEMP=300"
},
/area/ruin/unpowered)
"R" = (
/obj/structure/table/wood,
/obj/effect/spawner/lootdrop/pizzaparty,
/obj/effect/decal/cleanable/dirt,
/obj/item/reagent_containers/food/snacks/candy,
/turf/open/floor/wood{
initial_gas_mix = "o2=14;n2=23;TEMP=300"
},
/area/ruin/unpowered)
"V" = (
/obj/item/reagent_containers/food/snacks/gumball,
/turf/open/floor/wood{
initial_gas_mix = "o2=14;n2=23;TEMP=300"
},
/area/ruin/unpowered)
"X" = (
/obj/effect/decal/cleanable/dirt,
/obj/item/toy/snappop,
/turf/open/floor/wood{
initial_gas_mix = "o2=14;n2=23;TEMP=300"
},
/area/ruin/unpowered)
"Z" = (
/obj/effect/decal/cleanable/dirt,
/obj/item/reagent_containers/food/snacks/gumball,
/turf/open/floor/wood{
initial_gas_mix = "o2=14;n2=23;TEMP=300"
},
/area/ruin/unpowered)
(1,1,1) = {"
a
@@ -359,8 +398,8 @@ b
c
c
e
h
h
B
Z
e
Q
e
@@ -397,8 +436,8 @@ b
d
f
n
h
h
M
X
c
e
M
@@ -417,7 +456,7 @@ b
d
g
o
h
B
h
C
J
@@ -435,7 +474,7 @@ b
b
b
e
h
Z
p
q
x
@@ -461,7 +500,7 @@ r
y
E
h
h
X
c
b
b
@@ -496,7 +535,7 @@ b
b
e
e
h
X
t
A
G
@@ -515,12 +554,12 @@ b
b
b
d
k
R
h
s
s
H
h
B
O
d
b
@@ -536,9 +575,9 @@ b
b
d
k
h
M
u
s
V
s
o
n
@@ -3,8 +3,8 @@
/turf/open/floor/plating/asteroid/basalt/lava_land_surface,
/area/lavaland/surface/outdoors)
"b" = (
/turf/closed/mineral/volcanic/lava_land_surface,
/area/lavaland/surface/outdoors)
/turf/closed/wall/mineral/diamond,
/area/ruin/powered/pride)
"c" = (
/turf/open/lava/smooth/lava_land_surface,
/area/lavaland/surface/outdoors)
@@ -23,6 +23,10 @@
"g" = (
/turf/open/floor/mineral/silver,
/area/ruin/powered/pride)
"i" = (
/obj/item/clothing/gloves/ring,
/turf/open/floor/mineral/silver,
/area/ruin/powered/pride)
"j" = (
/obj/structure/mirror{
pixel_x = -32
@@ -33,13 +37,8 @@
/turf/open/floor/mineral/silver,
/area/ruin/powered/pride)
"k" = (
/obj/structure/mirror{
pixel_x = 32
},
/obj/machinery/light/small{
dir = 1
},
/turf/open/floor/mineral/silver,
/obj/structure/mirror/magic/pride,
/turf/closed/wall/mineral/diamond,
/area/ruin/powered/pride)
"l" = (
/obj/structure/mirror{
@@ -60,19 +59,65 @@
},
/turf/open/floor/mineral/silver,
/area/ruin/powered/pride)
"o" = (
/obj/structure/mirror{
pixel_x = -32
},
/obj/item/lipstick/random,
/turf/open/floor/mineral/silver,
/area/ruin/powered/pride)
"q" = (
/obj/structure/mirror{
pixel_x = -32
},
/obj/item/clothing/gloves/ring/silver,
/turf/open/floor/mineral/silver,
/area/ruin/powered/pride)
"r" = (
/obj/machinery/light/small,
/turf/open/floor/mineral/silver,
/area/ruin/powered/pride)
"u" = (
/obj/structure/mirror{
pixel_x = 32
},
/obj/item/lipstick/random,
/turf/open/floor/mineral/silver,
/area/ruin/powered/pride)
"D" = (
/obj/item/clothing/head/wig/random,
/turf/open/floor/mineral/silver,
/area/ruin/powered/pride)
"G" = (
/turf/closed/wall/mineral/diamond,
/turf/closed/mineral/volcanic/lava_land_surface,
/area/lavaland/surface/outdoors)
"I" = (
/obj/item/clothing/gloves/ring/silver,
/turf/open/floor/mineral/silver,
/area/ruin/powered/pride)
"J" = (
/obj/structure/mirror{
pixel_x = 32
},
/obj/machinery/light/small{
dir = 1
},
/turf/open/floor/mineral/silver,
/area/ruin/powered/pride)
"L" = (
/obj/item/lipstick/random,
/turf/open/floor/mineral/silver,
/area/ruin/powered/pride)
"O" = (
/obj/structure/mirror/magic/pride,
/turf/closed/wall/mineral/diamond,
/obj/item/clothing/gloves/ring/diamond,
/turf/open/floor/mineral/silver,
/area/ruin/powered/pride)
"V" = (
/obj/item/clothing/head/wig,
/turf/open/floor/mineral/silver,
/area/ruin/powered/pride)
"Y" = (
/obj/machinery/door/airlock/diamond,
/obj/machinery/door/airlock/silver/glass,
/turf/open/floor/mineral/silver{
blocks_air = 1
},
@@ -95,10 +140,6 @@ a
a
a
a
a
a
a
a
"}
(2,1,1) = {"
a
@@ -116,91 +157,71 @@ c
c
c
c
c
c
c
c
a
"}
(3,1,1) = {"
G
c
c
b
b
b
b
b
b
b
b
b
b
b
c
c
G
G
G
G
G
G
G
G
G
G
G
G
G
G
G
c
a
"}
(4,1,1) = {"
c
c
G
G
G
b
b
j
e
q
e
l
e
e
l
e
e
l
e
e
G
o
b
c
a
"}
(5,1,1) = {"
c
G
G
G
G
G
g
g
g
g
g
b
b
g
g
g
L
g
V
g
L
i
r
G
b
a
a
"}
(6,1,1) = {"
c
G
G
G
G
G
b
O
g
k
g
g
g
g
I
g
g
g
@@ -212,77 +233,61 @@ a
"}
(7,1,1) = {"
c
G
G
G
G
G
g
g
g
g
g
g
b
b
g
g
L
D
g
L
i
g
D
r
G
c
b
a
a
"}
(8,1,1) = {"
c
c
G
G
G
k
b
b
J
f
f
m
f
f
m
u
f
f
m
f
f
G
b
c
a
"}
(9,1,1) = {"
G
c
c
b
b
b
b
b
b
b
b
b
b
b
c
c
G
G
G
G
G
G
G
G
G
G
G
G
G
G
G
c
a
"}
(10,1,1) = {"
b
b
c
c
c
c
G
G
c
c
c
@@ -641,4 +641,4 @@ a
a
a
a
"}
"}
@@ -69,7 +69,7 @@
/turf/open/floor/plasteel/white,
/area/ruin/space/has_grav/powered/ancient_shuttle)
"j" = (
/obj/machinery/computer/prototype_cloning,
/obj/machinery/computer/cloning/prototype,
/obj/machinery/light{
dir = 1
},
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
+8 -1
View File
@@ -269,11 +269,12 @@ GLOBAL_LIST_INIT(shove_disarming_types, typecacheof(list(
//stamina cost defines.
#define STAM_COST_ATTACK_OBJ_MULT 1.2
#define STAM_COST_ATTACK_MOB_MULT 0.8
#define STAM_COST_ATTACK_MOB_MULT 1
#define STAM_COST_BATON_MOB_MULT 1
#define STAM_COST_NO_COMBAT_MULT 1.25
#define STAM_COST_W_CLASS_MULT 1.25
#define STAM_COST_THROW_MULT 2
#define STAM_COST_THROW_MOB 2.5 //multiplied by (mob size + 1)^2.
///Multiplier of the (STAMINA_NEAR_CRIT - user current stamina loss) : (STAMINA_NEAR_CRIT - STAMINA_SOFTCRIT) ratio used in damage penalties when stam soft-critted.
#define STAM_CRIT_ITEM_ATTACK_PENALTY 0.66
@@ -284,6 +285,12 @@ GLOBAL_LIST_INIT(shove_disarming_types, typecacheof(list(
/// Added delay when firing guns stam-softcritted. Summed with a hardset CLICK_CD_RANGE delay, similar to STAM_CRIT_DAMAGE_DELAY otherwise.
#define STAM_CRIT_GUN_DELAY 2.75
//stamina recovery defines. Blocked if combat mode is on.
#define STAM_RECOVERY_STAM_CRIT -7.5
#define STAM_RECOVERY_RESTING -6
#define STAM_RECOVERY_NORMAL -3
#define STAM_RECOVERY_LIMB 4 //limbs recover stamina separately from handle_status_effects(), and aren't blocked by combat mode.
/**
* should the current-attack-damage be lower than the item force multiplied by this value,
* a "inefficiently" prefix will be added to the message.
+71
View File
@@ -0,0 +1,71 @@
//// COOLDOWN SYSTEMS
/*
* We have 2 cooldown systems: timer cooldowns (divided between stoppable and regular) and world.time cooldowns.
*
* When to use each?
*
* * Adding a commonly-checked cooldown, like on a subsystem to check for processing
* * * Use the world.time ones, as they are cheaper.
*
* * Adding a rarely-used one for special situations, such as giving an uncommon item a cooldown on a target.
* * * Timer cooldown, as adding a new variable on each mob to track the cooldown of said uncommon item is going too far.
*
* * Triggering events at the end of a cooldown.
* * * Timer cooldown, registering to its signal.
*
* * Being able to check how long left for the cooldown to end.
* * * Either world.time or stoppable timer cooldowns, depending on the other factors. Regular timer cooldowns do not support this.
*
* * Being able to stop the timer before it ends.
* * * Either world.time or stoppable timer cooldowns, depending on the other factors. Regular timer cooldowns do not support this.
*/
/*
* Cooldown system based on an datum-level associative lazylist using timers.
*/
//INDEXES
#define COOLDOWN_EMPLOYMENT_CABINET "employment cabinet"
//TIMER COOLDOWN MACROS
#define COMSIG_CD_STOP(cd_index) "cooldown_[cd_index]"
#define COMSIG_CD_RESET(cd_index) "cd_reset_[cd_index]"
#define TIMER_COOLDOWN_START(cd_source, cd_index, cd_time) LAZYSET(cd_source.cooldowns, cd_index, addtimer(CALLBACK(GLOBAL_PROC, /proc/end_cooldown, cd_source, cd_index), cd_time))
#define TIMER_COOLDOWN_CHECK(cd_source, cd_index) LAZYACCESS(cd_source.cooldowns, cd_index)
#define TIMER_COOLDOWN_END(cd_source, cd_index) LAZYREMOVE(cd_source.cooldowns, cd_index)
/*
* Stoppable timer cooldowns.
* Use indexes the same as the regular tiemr cooldowns.
* They make use of the TIMER_COOLDOWN_CHECK() and TIMER_COOLDOWN_END() macros the same, just not the TIMER_COOLDOWN_START() one.
* A bit more expensive than the regular timers, but can be reset before they end and the time left can be checked.
*/
#define S_TIMER_COOLDOWN_START(cd_source, cd_index, cd_time) LAZYSET(cd_source.cooldowns, cd_index, addtimer(CALLBACK(GLOBAL_PROC, /proc/end_cooldown, cd_source, cd_index), cd_time, TIMER_STOPPABLE))
#define S_TIMER_COOLDOWN_RESET(cd_source, cd_index) reset_cooldown(cd_source, cd_index)
#define S_TIMER_COOLDOWN_TIMELEFT(cd_source, cd_index) (timeleft(TIMER_COOLDOWN_CHECK(cd_source, cd_index)))
/*
* Cooldown system based on storing world.time on a variable, plus the cooldown time.
* Better performance over timer cooldowns, lower control. Same functionality.
*/
#define COOLDOWN_DECLARE(cd_index) var/##cd_index = 0
#define COOLDOWN_START(cd_source, cd_index, cd_time) (cd_source.cd_index = world.time + cd_time)
//Returns true if the cooldown has run its course, false otherwise
#define COOLDOWN_FINISHED(cd_source, cd_index) (cd_source.cd_index < world.time)
#define COOLDOWN_RESET(cd_source, cd_index) cd_source.cd_index = 0
#define COOLDOWN_TIMELEFT(cd_source, cd_index) (max(0, cd_source.cd_index - world.time))
+5
View File
@@ -224,6 +224,11 @@
#define COMSIG_LIVING_RUN_BLOCK "living_do_run_block" //from base of mob/living/do_run_block(): (real_attack, atom/object, damage, attack_text, attack_type, armour_penetration, mob/attacker, def_zone)
#define COMSIG_LIVING_GET_BLOCKING_ITEMS "get_blocking_items" //from base of mob/living/get_blocking_items(): (list/items)
#define COMSIG_LIVING_ACTIVE_BLOCK_START "active_block_start" //from base of mob/living/keybind_start_active_blocking(): (obj/item/blocking_item, list/backup_items)
#define COMPONENT_PREVENT_BLOCK_START 1
#define COMSIG_LIVING_ACTIVE_PARRY_START "active_parry_start" //from base of mob/living/initiate_parry_sequence(): (parrying_method, datum/parrying_item_mob_or_art, list/backup_items)
#define COMPONENT_PREVENT_PARRY_START 1
//ALL OF THESE DO NOT TAKE INTO ACCOUNT WHETHER AMOUNT IS 0 OR LOWER AND ARE SENT REGARDLESS!
#define COMSIG_LIVING_STATUS_STUN "living_stun" //from base of mob/living/Stun() (amount, update, ignore)
#define COMSIG_LIVING_STATUS_KNOCKDOWN "living_knockdown" //from base of mob/living/Knockdown() (amount, update, ignore)
+4
View File
@@ -115,3 +115,7 @@
//these flags are used to tell the DNA modifier if a plant gene cannot be extracted or modified.
#define PLANT_GENE_REMOVABLE (1<<0)
#define PLANT_GENE_EXTRACTABLE (1<<1)
#define CLONEPOD_GET_MIND 1
#define CLONEPOD_POLL_MIND 2
#define CLONEPOD_NO_MIND 3
+7 -6
View File
@@ -8,12 +8,6 @@
/// Levels
#define SKILL_PROGRESSION_LEVEL 4
/// Max value of skill for numerical skills
#define SKILL_NUMERICAL_MAX 100
/// Min value of skill for numerical skills
#define SKILL_NUMERICAL_MIN 0
// Standard values for job starting skills
#define STARTING_SKILL_SURGERY_MEDICAL 35 //out of SKILL_NUMERICAL_MAX
@@ -26,6 +20,13 @@
#define DEF_SKILL_GAIN 1
#define SKILL_GAIN_SURGERY_PER_STEP 0.25
#define STD_USE_TOOL_MULT 1
#define EASY_USE_TOOL_MULT 0.75
#define TRIVIAL_USE_TOOL_MULT 0.5
#define BARE_USE_TOOL_MULT 0.25
//multiplier of the difference of max_value and min_value. Mostly for balance purposes between numerical and level-based skills.
#define STD_NUM_SKILL_ITEM_GAIN_MULTI 0.002
//An extra point for each few seconds of delay when using a tool. Before the multiplier.
#define SKILL_GAIN_DELAY_DIVISOR 3 SECONDS
+6 -4
View File
@@ -1136,9 +1136,10 @@ GLOBAL_LIST_INIT(freon_color_matrix, list("#2E5E69", "#60A2A8", "#A1AFB1", rgb(0
if (!isicon(I))
if (isfile(thing)) //special snowflake
var/name = sanitize_filename("[generate_asset_name(thing)].png")
register_asset(name, thing)
if(!SSassets.cache[name])
register_asset(name, thing)
for (var/thing2 in targets)
send_asset(thing2, key, FALSE)
send_asset(thing2, key)
return "<img class='icon icon-misc' src=\"[url_encode(name)]\">"
var/atom/A = thing
if (isnull(dir))
@@ -1160,9 +1161,10 @@ GLOBAL_LIST_INIT(freon_color_matrix, list("#2E5E69", "#60A2A8", "#A1AFB1", rgb(0
I = icon(I, icon_state, dir, frame, moving)
key = "[generate_asset_name(I)].png"
register_asset(key, I)
if(!SSassets.cache[key])
register_asset(key, I)
for (var/thing2 in targets)
send_asset(thing2, key, FALSE)
send_asset(thing2, key)
return "<img class='icon icon-[icon_state]' src=\"[url_encode(key)]\">"
+1 -1
View File
@@ -153,7 +153,7 @@
var/image/item_overlay = image(holding)
item_overlay.alpha = 92
if(!user.can_equip(holding, slot_id, TRUE))
if(!user.can_equip(holding, slot_id, TRUE, TRUE, TRUE))
item_overlay.color = "#FF0000"
else
item_overlay.color = "#00ff00"
+4 -3
View File
@@ -123,7 +123,7 @@
if(totitemdamage)
totitemdamage = user.mind.item_action_skills_mod(I, totitemdamage, I.skill_difficulty, SKILL_ATTACK_OBJ, bad_trait)
for(var/skill in I.used_skills)
if(!(I.used_skills[skill] & SKILL_TRAIN_ATTACK_OBJ))
if(!(SKILL_TRAIN_ATTACK_OBJ in I.used_skills[skill]))
continue
user.mind.auto_gain_experience(skill, I.skill_gain)
@@ -192,9 +192,10 @@
if(.)
. = user.mind.item_action_skills_mod(I, ., I.skill_difficulty, SKILL_ATTACK_MOB, bad_trait)
for(var/skill in I.used_skills)
if(!(I.used_skills[skill] & SKILL_TRAIN_ATTACK_MOB))
if(!(SKILL_TRAIN_ATTACK_MOB in I.used_skills[skill]))
continue
user.mind.auto_gain_experience(skill, I.skill_gain)
var/datum/skill/S = GLOB.skill_datums[skill]
user.mind.auto_gain_experience(skill, I.skill_gain*S.item_skill_gain_multi)
// Proximity_flag is 1 if this afterattack was called on something adjacent, in your square, or on your person.
// Click parameters is the params string from byond Click() code, see that documentation.
+1 -2
View File
@@ -102,9 +102,8 @@
//stops TK grabs being equipped anywhere but into hands
/obj/item/tk_grab/equipped(mob/user, slot)
if(slot == SLOT_HANDS)
return
return ..()
qdel(src)
return
/obj/item/tk_grab/examine(user)
if (focus)
@@ -25,4 +25,23 @@
/datum/config_entry/string/medal_hub_address
/datum/config_entry/string/medal_hub_password
protection = CONFIG_ENTRY_HIDDEN
protection = CONFIG_ENTRY_HIDDEN
/datum/config_entry/keyed_list/cross_server_bunker_override
key_mode = KEY_MODE_TEXT
value_mode = VALUE_MODE_TEXT
protection = CONFIG_ENTRY_LOCKED
/datum/config_entry/keyed_list/cross_server_bunker_override/ValidateAndSet(str_val)
. = ..()
if(.)
var/list/newv = list()
for(var/I in config_entry_value)
newv[replacetext(I, "+", " ")] = config_entry_value[I]
config_entry_value = newv
/datum/config_entry/keyed_list/cross_server_bunker_override/ValidateListEntry(key_name, key_value)
return key_value != "byond:\\address:port" && ..()
/datum/config_entry/flag/allow_cross_server_bunker_override
protection = CONFIG_ENTRY_LOCKED
@@ -8,9 +8,9 @@
custom_materials = list(/datum/material/wood = MINERAL_MATERIAL_AMOUNT * 6)
icon_state = "riflestock"
/obj/item/weaponcrafting/durathread_string
name = "durathread string"
desc = "A long piece of durathread with some resemblance to cable coil."
/obj/item/weaponcrafting/string
name = "wound thread"
desc = "A long piece of thread with some resemblance to cable coil."
icon_state = "durastring"
////////////////////////////////
@@ -103,7 +103,7 @@
/datum/crafting_recipe/bone_bow
name = "Bone Bow"
result = /obj/item/gun/ballistic/bow/ashen
time = 200
time = 120 // 80+120 = 200
always_availible = FALSE
reqs = list(/obj/item/stack/sheet/bone = 8,
/obj/item/stack/sheet/sinew = 4)
@@ -112,7 +112,7 @@
/datum/crafting_recipe/bow_tablet
name = "Sandstone Bow Making Manual"
result = /obj/item/book/granter/crafting_recipe/bone_bow
time = 600 //Scribing
time = 200 //Scribing // don't care
always_availible = FALSE
reqs = list(/obj/item/stack/rods = 1,
/obj/item/stack/sheet/mineral/sandstone = 4)
@@ -192,8 +192,8 @@
result = /obj/item/gun/ballistic/bow/pipe
reqs = list(/obj/item/pipe = 5,
/obj/item/stack/sheet/plastic = 15,
/obj/item/weaponcrafting/durathread_string = 5)
time = 450
/obj/item/weaponcrafting/string = 5)
time = 150
category = CAT_WEAPONRY
subcategory = CAT_WEAPON
@@ -283,9 +283,9 @@
/datum/crafting_recipe/arrow
name = "Arrow"
result = /obj/item/ammo_casing/caseless/arrow/wood
time = 30
time = 5 // these only do 15 damage
reqs = list(/obj/item/stack/sheet/mineral/wood = 1,
/obj/item/stack/sheet/durathread = 1,
/obj/item/stack/sheet/cloth = 1,
/obj/item/stack/rods = 1) // 1 metal sheet = 2 rods = 2 arrows
category = CAT_WEAPONRY
subcategory = CAT_AMMO
@@ -293,7 +293,7 @@
/datum/crafting_recipe/bone_arrow
name = "Bone Arrow"
result = /obj/item/ammo_casing/caseless/arrow/bone
time = 30
time = 5
always_availible = FALSE
reqs = list(/obj/item/stack/sheet/bone = 1,
/obj/item/stack/sheet/sinew = 1,
@@ -305,7 +305,7 @@
name = "Ashen Arrow"
result = /obj/item/ammo_casing/caseless/arrow/ash
tools = list(TOOL_WELDER)
time = 30
time = 10 // 1.5 seconds minimum per actually worthwhile arrow excluding interface lag
always_availible = FALSE
reqs = list(/obj/item/ammo_casing/caseless/arrow/wood = 1)
category = CAT_WEAPONRY
@@ -34,3 +34,8 @@
qdel(A)
return
. = ..()
/datum/component/storage/concrete/bluespace/bag_of_holding/can_be_inserted(obj/item/I, stop_messages = FALSE, mob/M)
if(I.GetComponent(/datum/component/storage/concrete/bluespace/bag_of_holding))
return TRUE
return ..()
+1 -1
View File
@@ -89,7 +89,7 @@
/// Triggered on equip of the item containing the component
/datum/component/two_handed/proc/on_equip(datum/source, mob/user, slot)
if(require_twohands && slot == ITEM_SLOT_HANDS) // force equip the item
if(require_twohands && slot == SLOT_HANDS) // force equip the item
wield(user)
if(!user.is_holding(parent) && wielded && !require_twohands)
unwield(user)
+34
View File
@@ -39,6 +39,9 @@
/// A weak reference to another datum
var/datum/weakref/weak_reference
///Lazy associative list of currently active cooldowns.
var/list/cooldowns
#ifdef TESTING
var/running_find_references
var/last_find_references = 0
@@ -201,3 +204,34 @@
qdel(D)
else
return returned
/**
* Callback called by a timer to end an associative-list-indexed cooldown.
*
* Arguments:
* * source - datum storing the cooldown
* * index - string index storing the cooldown on the cooldowns associative list
*
* This sends a signal reporting the cooldown end.
*/
/proc/end_cooldown(datum/source, index)
if(QDELETED(source))
return
SEND_SIGNAL(source, COMSIG_CD_STOP(index))
TIMER_COOLDOWN_END(source, index)
/**
* Proc used by stoppable timers to end a cooldown before the time has ran out.
*
* Arguments:
* * source - datum storing the cooldown
* * index - string index storing the cooldown on the cooldowns associative list
*
* This sends a signal reporting the cooldown end, passing the time left as an argument.
*/
/proc/reset_cooldown(datum/source, index)
if(QDELETED(source))
return
SEND_SIGNAL(source, COMSIG_CD_RESET(index), S_TIMER_COOLDOWN_TIMELEFT(source, index))
TIMER_COOLDOWN_END(source, index)
+1 -1
View File
@@ -678,7 +678,7 @@
holder.update_transform()
var/danger = CONFIG_GET(number/threshold_body_size_slowdown)
if(features["body_size"] < danger)
var/slowdown = 1 + round(danger/features["body_size"], 0.1) * CONFIG_GET(number/body_size_slowdown_multiplier)
var/slowdown = (1 - round(features["body_size"] / danger, 0.1)) * CONFIG_GET(number/body_size_slowdown_multiplier)
holder.add_or_update_variable_movespeed_modifier(/datum/movespeed_modifier/small_stride, TRUE, slowdown)
else if(old_size < danger)
holder.remove_movespeed_modifier(/datum/movespeed_modifier/small_stride)
+2 -4
View File
@@ -58,12 +58,10 @@
var/datum/martial_art/boxing/style = new
/obj/item/clothing/gloves/boxing/equipped(mob/user, slot)
if(!ishuman(user))
return
if(slot == SLOT_GLOVES)
. = ..()
if(ishuman(user) && slot == SLOT_GLOVES)
var/mob/living/carbon/human/H = user
style.teach(H,TRUE)
return
/obj/item/clothing/gloves/boxing/dropped(mob/user)
. = ..()
+2 -3
View File
@@ -196,9 +196,8 @@
var/datum/martial_art/krav_maga/style = new
/obj/item/clothing/gloves/krav_maga/equipped(mob/user, slot)
if(!ishuman(user))
return
if(slot == SLOT_GLOVES)
. = ..()
if(ishuman(user) && slot == SLOT_GLOVES)
var/mob/living/carbon/human/H = user
style.teach(H,1)
+3 -5
View File
@@ -377,7 +377,7 @@
var/turf/ST = null
var/falling = 0
var/damage = damage_roll(A,D)
for (var/obj/O in oview(1, A))
if (O.density == 1)
if (O == A)
@@ -472,12 +472,10 @@
var/datum/martial_art/wrestling/style = new
/obj/item/storage/belt/champion/wrestling/equipped(mob/user, slot)
if(!ishuman(user))
return
if(slot == SLOT_BELT)
. = ..()
if(ishuman(user) && slot == SLOT_BELT)
var/mob/living/carbon/human/H = user
style.teach(H,1)
return
/obj/item/storage/belt/champion/wrestling/dropped(mob/user)
. = ..()
+1 -1
View File
@@ -40,7 +40,7 @@
. = list()
.["playername"] = owner.name
.["see_skill_mods"] = see_skill_mods
.["admin"] = check_rights(R_DEBUG)
.["admin"] = check_rights(R_DEBUG, FALSE)
/datum/skill_holder/ui_act(action, params)
. = ..()
+8
View File
@@ -33,6 +33,10 @@ GLOBAL_LIST_INIT_TYPED(skill_datums, /datum/skill, init_skill_datums())
var/base_multiplier = 1
/// Value added to the base multiplier depending on overall competency compared to maximum value/level.
var/competency_multiplier = 1
/// Experience gain multiplier gained from using items.
var/item_skill_gain_multi = 1
/// Skill gain quantisation
var/skill_gain_quantisation = 0.1
/// A list of ways this skill can affect or be affected through actions and skill modifiers.
var/list/skill_traits = list(SKILL_SANITY, SKILL_INTELLIGENCE)
/// Index of this skill in the UI
@@ -108,6 +112,10 @@ GLOBAL_LIST_INIT_TYPED(skill_datums, /datum/skill, init_skill_datums())
/// Min value of this skill
var/min_value = 0
/datum/skill/numerical/New()
..()
skill_gain_quantisation = item_skill_gain_multi = item_skill_gain_multi * (max_value - min_value) * STD_NUM_SKILL_ITEM_GAIN_MULTI
/datum/skill/numerical/sanitize_value(new_value)
return clamp(new_value, min_value, max_value)
+4 -6
View File
@@ -91,10 +91,10 @@
CRASH("Invalid set_skill_value call. Use skill typepaths.") //until a time when we somehow need text ids for dynamic skills, I'm enforcing this.
var/datum/skill/S = GLOB.skill_datums[skill]
value = S.sanitize_value(value)
skill_holder.need_static_data_update = TRUE
if(!isnull(value))
LAZYINITLIST(skill_holder.skills)
S.set_skill_value(skill_holder, value, src, silent)
skill_holder.need_static_data_update = TRUE
return TRUE
return FALSE
@@ -120,11 +120,9 @@
CRASH("You cannot auto increment a non numerical(experience skill!")
var/current = get_skill_value(skill, FALSE)
var/affinity = get_skill_affinity(skill)
var/target_value = current + (value * affinity)
if(maximum)
target_value = min(target_value, maximum)
if(target_value == maximum) //no more experience to gain, early return.
return
var/target_value = round(current + (value * affinity), S.skill_gain_quantisation)
if(maximum && target_value >= maximum) //no more experience to gain, early return.
return
boost_skill_value_to(skill, target_value, silent, current)
/**
+19
View File
@@ -74,6 +74,25 @@
for(var/client/C in GLOB.clients)
C.AnnouncePR(final_composed)
/datum/world_topic/auto_bunker_passthrough
keyword = "auto_bunker_override"
require_comms_key = TRUE
/datum/world_topic/auto_bunker_passthrough/Run(list/input)
if(!CONFIG_GET(flag/allow_cross_server_bunker_override))
return "Function Disabled"
var/ckeytobypass = input["ckey"]
var/is_new_ckey = !(ckey(ckeytobypass) in GLOB.bunker_passthrough)
var/sender = input["source"] || "UNKNOWN"
GLOB.bunker_passthrough |= ckey(ckeytobypass)
GLOB.bunker_passthrough[ckey(ckeytobypass)] = world.realtime
SSpersistence.SavePanicBunker() //we can do this every time, it's okay
if(!is_new_ckey)
log_admin("AUTO BUNKER: [ckeytobypass] given access (incoming comms from [sender]).")
message_admins("AUTO BUNKER: [ckeytobypass] given access (incoming comms from [sender]).")
send2irc("Panic Bunker", "AUTO BUNKER: [ckeytobypass] given access (incoming comms from [sender]).")
return "Success"
/datum/world_topic/ahelp_relay
keyword = "Ahelp"
require_comms_key = TRUE
+21 -31
View File
@@ -436,7 +436,7 @@
var/blood_id = get_blood_id()
if(!(blood_id in GLOB.blood_reagent_types))
return
return list("color" = list(BLOOD_COLOR_HUMAN), "ANIMAL DNA" = "Y-")
return list("color" = BLOOD_COLOR_HUMAN, "ANIMAL DNA" = "Y-")
/mob/living/carbon/get_blood_dna_list()
var/blood_id = get_blood_id()
@@ -444,15 +444,15 @@
return
var/list/blood_dna = list()
if(dna)
blood_dna["color"] = list(dna.species.exotic_blood_color) //so when combined, the list grows with the number of colors
blood_dna["color"] = dna.species.exotic_blood_color //so when combined, the list grows with the number of colors
blood_dna[dna.unique_enzymes] = dna.blood_type
else
blood_dna["color"] = list(BLOOD_COLOR_HUMAN)
blood_dna["color"] = BLOOD_COLOR_HUMAN
blood_dna["UNKNOWN DNA"] = "X*"
return blood_dna
/mob/living/carbon/alien/get_blood_dna_list()
return list("color" = list(BLOOD_COLOR_XENO), "UNKNOWN DNA" = "X*")
return list("color" = BLOOD_COLOR_XENO, "UNKNOWN DNA" = "X*")
//to add a mob's dna info into an object's blood_DNA list.
/atom/proc/transfer_mob_blood_dna(mob/living/L)
@@ -461,25 +461,35 @@
if(!new_blood_dna)
return FALSE
LAZYINITLIST(blood_DNA) //if our list of DNA doesn't exist yet, initialise it.
LAZYINITLIST(blood_DNA["color"])
var/old_length = blood_DNA.len
blood_DNA |= new_blood_dna
blood_DNA["color"] += new_blood_dna["color"]
var/changed = FALSE
if(!blood_DNA["color"])
blood_DNA["color"] = new_blood_dna["color"]
changed = TRUE
else
var/old = blood_DNA["color"]
blood_DNA["color"] = BlendRGB(blood_DNA["color"], new_blood_dna["color"])
changed = old != blood_DNA["color"]
if(blood_DNA.len == old_length)
return FALSE
return TRUE
return changed
//to add blood dna info to the object's blood_DNA list
/atom/proc/transfer_blood_dna(list/blood_dna, list/datum/disease/diseases)
LAZYINITLIST(blood_DNA)
LAZYINITLIST(blood_dna["color"])
var/old_length = blood_DNA.len
blood_DNA |= blood_dna
if(blood_DNA.len > old_length)
blood_DNA["color"] += blood_dna["color"]
return TRUE
. = TRUE
//some new blood DNA was added
if(!blood_dna["color"])
return
if(!blood_DNA["color"])
blood_DNA["color"] = blood_dna["color"]
else
blood_DNA["color"] = BlendRGB(blood_DNA["color"], blood_dna["color"])
//to add blood from a mob onto something, and transfer their dna info
/atom/proc/add_mob_blood(mob/living/M)
@@ -548,27 +558,7 @@
return TRUE
/atom/proc/blood_DNA_to_color()
var/list/colors = list()//first we make a list of all bloodtypes present
for(var/blood_color in blood_DNA["color"])
if(colors[blood_color])
colors[blood_color]++
else
colors[blood_color] = 1
var/final_rgb = BLOOD_COLOR_HUMAN //a default so we don't have white blood graphics if something messed up
if(colors.len)
var/sum = 0 //this is all shitcode, but it works; trust me
final_rgb = colors[1]
sum = colors[colors[1]]
if(colors.len > 1)
var/i = 2
while(i <= colors.len)
var/tmp = colors[colors[i]]
final_rgb = BlendRGB(final_rgb, colors[i], tmp/(tmp+sum))
sum += tmp
i++
return final_rgb
return (blood_DNA && blood_DNA["color"]) || BLOOD_COLOR_HUMAN
/atom/proc/clean_blood()
. = blood_DNA? TRUE : FALSE
+4 -1
View File
@@ -201,10 +201,13 @@ GLOBAL_LIST_EMPTY(objectives)
return won || ..()
/datum/objective/assassinate/once/process()
won = check_completion()
won = check_midround_completion()
if(won)
STOP_PROCESSING(SSprocessing,src)
/datum/objective/assassinate/once/proc/check_midround_completion()
return won || !considered_alive(target) //The target afking / logging off for a bit during the round doesn't complete it, but them being afk at roundend does.
/datum/objective/assassinate/internal
var/stolen = 0 //Have we already eliminated this target?
+9 -1
View File
@@ -44,7 +44,7 @@
/datum/game_mode/wizard/are_special_antags_dead()
for(var/datum/mind/wizard in wizards)
for(var/datum/mind/wizard in wizards | apprentices)
if(isliving(wizard.current) && wizard.current.stat!=DEAD)
return FALSE
@@ -58,6 +58,14 @@
return TRUE
/datum/game_mode/wizard/check_finished()
. = ..()
if(.)
finished = TRUE
else if(gamemode_ready && are_special_antags_dead() && !CONFIG_GET(keyed_list/continuous)[config_tag])
finished = TRUE
. = TRUE
/datum/game_mode/wizard/set_round_result()
..()
if(finished)
+46 -26
View File
@@ -26,6 +26,7 @@
var/efficiency
var/datum/mind/clonemind
var/get_clone_mind = CLONEPOD_GET_MIND
var/grab_ghost_when = CLONER_MATURE_CLONE
var/internal_radio = TRUE
@@ -134,43 +135,44 @@
return examine(user)
//Start growing a human clone in the pod!
/obj/machinery/clonepod/proc/growclone(ckey, clonename, ui, mutation_index, mindref, datum/species/mrace, list/features, factions, list/quirks, datum/bank_account/insurance, list/traumas)
/obj/machinery/clonepod/proc/growclone(ckey, clonename, ui, mutation_index, mindref, blood_type, datum/species/mrace, list/features, factions, list/quirks, datum/bank_account/insurance, list/traumas)
if(panel_open)
return FALSE
if(mess || attempting)
return FALSE
clonemind = locate(mindref) in SSticker.minds
if(!istype(clonemind)) //not a mind
return FALSE
if(!QDELETED(clonemind.current))
if(clonemind.current.stat != DEAD) //mind is associated with a non-dead body
if(get_clone_mind == CLONEPOD_GET_MIND)
clonemind = locate(mindref) in SSticker.minds
if(!istype(clonemind)) //not a mind
return FALSE
if(clonemind.current.suiciding) // Mind is associated with a body that is suiciding.
if(!QDELETED(clonemind.current))
if(clonemind.current.stat != DEAD) //mind is associated with a non-dead body
return FALSE
if(clonemind.current.suiciding) // Mind is associated with a body that is suiciding.
return FALSE
if(AmBloodsucker(clonemind.current)) //If the mind is a bloodsucker
return FALSE
if(clonemind.active) //somebody is using that mind
if( ckey(clonemind.key)!=ckey )
return FALSE
else
// get_ghost() will fail if they're unable to reenter their body
var/mob/dead/observer/G = clonemind.get_ghost()
if(!G)
return FALSE
if(G.suiciding) // The ghost came from a body that is suiciding.
return FALSE
if(clonemind.damnation_type) //Can't clone the damned.
INVOKE_ASYNC(src, .proc/horrifyingsound)
mess = TRUE
update_icon()
return FALSE
if(AmBloodsucker(clonemind.current)) //If the mind is a bloodsucker
return FALSE
if(clonemind.active) //somebody is using that mind
if( ckey(clonemind.key)!=ckey )
return FALSE
else
// get_ghost() will fail if they're unable to reenter their body
var/mob/dead/observer/G = clonemind.get_ghost()
if(!G)
return FALSE
if(G.suiciding) // The ghost came from a body that is suiciding.
return FALSE
if(clonemind.damnation_type) //Can't clone the damned.
INVOKE_ASYNC(src, .proc/horrifyingsound)
mess = TRUE
update_icon()
return FALSE
current_insurance = insurance
attempting = TRUE //One at a time!!
countdown.start()
var/mob/living/carbon/human/H = new /mob/living/carbon/human(src)
H.hardset_dna(ui, mutation_index, H.real_name, null, mrace, features)
H.hardset_dna(ui, mutation_index, H.real_name, blood_type, mrace, features)
H.easy_randmut(NEGATIVE+MINOR_NEGATIVE) //100% bad mutation. Can be cured with mutadone.
@@ -192,7 +194,14 @@
ADD_TRAIT(H, TRAIT_NOCRITDAMAGE, CLONING_POD_TRAIT)
H.Unconscious(80)
clonemind.transfer_to(H)
if(clonemind)
clonemind.transfer_to(H)
else if(get_clone_mind == CLONEPOD_POLL_MIND)
var/list/candidates = pollCandidatesForMob("Do you want to play as [clonename]'s defective clone? (Don't ERP without permission from the original)", null, null, null, 100, H, POLL_IGNORE_CLONE)
if(LAZYLEN(candidates))
var/mob/C = pick(candidates)
H.key = C.key
if(grab_ghost_when == CLONER_FRESH_CLONE)
H.grab_ghost()
@@ -549,6 +558,17 @@
. += "cover-on"
. += "panel"
//Experimental cloner; clones a body regardless of the owner's status, letting a ghost control it instead
/obj/machinery/clonepod/experimental
name = "experimental cloning pod"
desc = "An ancient cloning pod. It seems to be an early prototype of the experimental cloners used in Nanotrasen Stations."
icon = 'icons/obj/machines/cloning.dmi'
icon_state = "pod_0"
req_access = null
circuit = /obj/item/circuitboard/machine/clonepod/experimental
internal_radio = FALSE
get_clone_mind = CLONEPOD_POLL_MIND
/*
* Manual -- A big ol' manual.
*/
+167 -89
View File
@@ -8,6 +8,7 @@
circuit = /obj/item/circuitboard/computer/cloning
req_access = list(ACCESS_HEADS) //ONLY USED FOR RECORD DELETION RIGHT NOW.
var/obj/machinery/dna_scannernew/scanner = null //Linked scanner. For scanning.
var/clonepod_type = /obj/machinery/clonepod
var/list/pods //Linked cloning pods
var/temp = "Inactive"
var/scantemp_ckey
@@ -17,6 +18,7 @@
var/obj/item/disk/data/diskette = null //Mostly so the geneticist can steal everything.
var/loading = 0 // Nice loading text
var/autoprocess = 0
var/use_records = TRUE // Old experimental cloner.
var/list/records = list()
light_color = LIGHT_COLOR_BLUE
@@ -36,29 +38,32 @@
return ..()
/obj/machinery/computer/cloning/proc/GetAvailablePod(mind = null)
if(pods)
for(var/P in pods)
var/obj/machinery/clonepod/pod = P
if(pod.occupant && pod.clonemind == mind)
return null
if(pod.is_operational() && !(pod.occupant || pod.mess))
return pod
if(!pods)
return
for(var/P in pods)
var/obj/machinery/clonepod/pod = P
if(pod.occupant && pod.get_clone_mind == CLONEPOD_GET_MIND && pod.clonemind == mind)
return null
if(pod.is_operational() && !(pod.occupant || pod.mess))
return pod
/obj/machinery/computer/cloning/proc/HasEfficientPod()
if(pods)
for(var/P in pods)
var/obj/machinery/clonepod/pod = P
if(pod.is_operational() && pod.efficiency > 5)
return TRUE
if(!pods)
return
for(var/P in pods)
var/obj/machinery/clonepod/pod = P
if(pod.is_operational() && pod.efficiency > 5)
return TRUE
/obj/machinery/computer/cloning/proc/GetAvailableEfficientPod(mind = null)
if(pods)
for(var/P in pods)
var/obj/machinery/clonepod/pod = P
if(pod.occupant && pod.clonemind == mind)
return pod
else if(!. && pod.is_operational() && !(pod.occupant || pod.mess) && pod.efficiency > 5)
. = pod
if(!pods)
return
for(var/P in pods)
var/obj/machinery/clonepod/pod = P
if(pod.occupant && pod.clonemind == mind)
return pod
else if(!. && pod.is_operational() && !(pod.occupant || pod.mess) && pod.efficiency > 5)
. = pod
/obj/machinery/computer/cloning/process()
if(!(scanner && LAZYLEN(pods) && autoprocess))
@@ -73,7 +78,7 @@
if(pod.occupant)
continue //how though?
if(pod.growclone(R.fields["ckey"], R.fields["name"], R.fields["UI"], R.fields["SE"], R.fields["mind"], R.fields["mrace"], R.fields["features"], R.fields["factions"], R.fields["quirks"], R.fields["bank_account"], R.fields["traumas"]))
if(pod.growclone(R.fields["ckey"], R.fields["name"], R.fields["UI"], R.fields["SE"], R.fields["mind"], R.fields["blood_type"], R.fields["mrace"], R.fields["features"], R.fields["factions"], R.fields["quirks"], R.fields["bank_account"], R.fields["traumas"]))
temp = "[R.fields["name"]] => <font class='good'>Cloning cycle in progress...</font>"
records -= R
@@ -103,12 +108,10 @@
return null
/obj/machinery/computer/cloning/proc/findcloner()
var/obj/machinery/clonepod/podf = null
var/obj/machinery/clonepod/podf
for(var/direction in GLOB.cardinals)
podf = locate(/obj/machinery/clonepod, get_step(src, direction))
if (!isnull(podf) && podf.is_operational())
podf = locate(clonepod_type, get_step(src, direction))
if(podf?.is_operational())
AttachCloner(podf)
/obj/machinery/computer/cloning/proc/AttachCloner(obj/machinery/clonepod/pod)
@@ -132,7 +135,7 @@
else if(istype(W, /obj/item/multitool))
var/obj/item/multitool/P = W
if(istype(P.buffer, /obj/machinery/clonepod))
if(istype(P.buffer, clonepod_type))
if(get_area(P.buffer) != get_area(src))
to_chat(user, "<font color = #666633>-% Cannot link machines across power zones. Buffer cleared %-</font color>")
P.buffer = null
@@ -157,13 +160,14 @@
var/dat = ""
dat += "<a href='byond://?src=[REF(src)];refresh=1'>Refresh</a>"
if(scanner && HasEfficientPod() && scanner.scan_level >= AUTOCLONING_MINIMAL_LEVEL)
if(!autoprocess)
dat += "<a href='byond://?src=[REF(src)];task=autoprocess'>Autoclone</a>"
if(use_records)
if(scanner && HasEfficientPod() && scanner.scan_level >= AUTOCLONING_MINIMAL_LEVEL)
if(!autoprocess)
dat += "<a href='byond://?src=[REF(src)];task=autoprocess'>Autoclone</a>"
else
dat += "<a href='byond://?src=[REF(src)];task=stopautoprocess'>Stop autoclone</a>"
else
dat += "<a href='byond://?src=[REF(src)];task=stopautoprocess'>Stop autoclone</a>"
else
dat += "<span class='linkOff'>Autoclone</span>"
dat += "<span class='linkOff'>Autoclone</span>"
dat += "<h3>Cloning Pod Status</h3>"
dat += "<div class='statusDisplay'>[temp]&nbsp;</div>"
@@ -190,26 +194,29 @@
else if(loading)
dat += "[scanner_occupant] => Scanning..."
else
if(scanner_occupant.ckey != scantemp_ckey)
scantemp = "Ready to Scan"
scantemp_ckey = scanner_occupant.ckey
if(use_records)
if(scanner_occupant.ckey != scantemp_ckey)
scantemp = "Ready to Scan"
scantemp_ckey = scanner_occupant.ckey
else
scantemp = "Ready to Clone"
dat += "[scanner_occupant] => [scantemp]"
dat += "</div>"
if(scanner_occupant)
dat += "<a href='byond://?src=[REF(src)];scan=1'>Start Scan</a>"
dat += "<br><a href='byond://?src=[REF(src)];lock=1'>[src.scanner.locked ? "Unlock Scanner" : "Lock Scanner"]</a>"
dat += "<a href='byond://?src=[REF(src)];scan=1'>[use_records ? "Start Scan" : "Clone"]</a>"
dat += "<br><a href='byond://?src=[REF(src)];lock=1'>[scanner.locked ? "Unlock Scanner" : "Lock Scanner"]</a>"
else
dat += "<span class='linkOff'>Start Scan</span>"
// Database
dat += "<h3>Database Functions</h3>"
if (src.records.len && src.records.len > 0)
dat += "<a href='byond://?src=[REF(src)];menu=2'>View Records ([src.records.len])</a><br>"
else
dat += "<span class='linkOff'>View Records (0)</span><br>"
if (src.diskette)
dat += "<a href='byond://?src=[REF(src)];disk=eject'>Eject Disk</a><br>"
dat += "<span class='linkOff'>[use_records ? "Start Scan" : "Clone"]</span>"
if(use_records)
// Database
dat += "<h3>Database Functions</h3>"
if (src.records.len && src.records.len > 0)
dat += "<a href='byond://?src=[REF(src)];menu=2'>View Records ([src.records.len])</a><br>"
else
dat += "<span class='linkOff'>View Records (0)</span><br>"
if (src.diskette)
dat += "<a href='byond://?src=[REF(src)];disk=eject'>Eject Disk</a><br>"
@@ -290,24 +297,19 @@
autoprocess = FALSE
STOP_PROCESSING(SSmachines, src)
playsound(src, 'sound/machines/terminal_prompt_deny.ogg', 50, 0)
. = TRUE
else if ((href_list["scan"]) && !isnull(scanner) && scanner.is_operational())
scantemp = ""
loading = 1
loading = TRUE
src.updateUsrDialog()
playsound(src, 'sound/machines/terminal_prompt.ogg', 50, 0)
say("Initiating scan...")
var/prev_locked = scanner.locked
scanner.locked = TRUE
spawn(20)
src.scan_occupant(scanner.occupant)
loading = 0
src.updateUsrDialog()
playsound(src, 'sound/machines/terminal_prompt_confirm.ogg', 50, 0)
scanner.locked = prev_locked
addtimer(CALLBACK(src, .proc/finish_scan, scanner.occupant, prev_locked), 2 SECONDS)
. = TRUE
//No locking an open scanner.
else if ((href_list["lock"]) && !isnull(scanner) && scanner.is_operational())
@@ -317,8 +319,17 @@
else
scanner.locked = FALSE
playsound(src, 'sound/machines/terminal_prompt_confirm.ogg', 50, 0)
. = TRUE
else if(href_list["view_rec"])
else if (href_list["refresh"])
src.updateUsrDialog()
playsound(src, "terminal_type", 25, 0)
. = TRUE
if(. || !use_records)
return
if(href_list["view_rec"])
playsound(src, "terminal_type", 25, 0)
src.active_record = find_record("id", href_list["view_rec"], records)
if(active_record)
@@ -330,6 +341,7 @@
src.menu = 3
else
src.temp = "Record missing."
. = TRUE
else if (href_list["del_rec"])
if ((!src.active_record) || (src.menu < 3))
@@ -353,8 +365,9 @@
else
src.temp = "<font class='bad'>Access Denied.</font>"
playsound(src, 'sound/machines/terminal_prompt_deny.ogg', 50, 0)
. = TRUE
else if (href_list["disk"]) //Load or eject.
else if (href_list["disk"] && use_records) //Load or eject.
switch(href_list["disk"])
if("load")
if (!diskette || !istype(diskette.fields) || !diskette.fields["name"] || !diskette.fields)
@@ -392,10 +405,7 @@
diskette.name = "data disk - '[src.diskette.fields["name"]]'"
src.temp = "Save successful."
playsound(src, 'sound/machines/terminal_prompt_confirm.ogg', 50, 0)
else if (href_list["refresh"])
src.updateUsrDialog()
playsound(src, "terminal_type", 25, 0)
. = TRUE
else if (href_list["clone"])
var/datum/data/record/C = find_record("id", href_list["clone"], records)
@@ -415,7 +425,7 @@
else if(pod.occupant)
temp = "<font class='bad'>Cloning cycle already in progress.</font>"
playsound(src, 'sound/machines/terminal_prompt_deny.ogg', 50, 0)
else if(pod.growclone(C.fields["ckey"], C.fields["name"], C.fields["UI"], C.fields["SE"], C.fields["mind"], C.fields["mrace"], C.fields["features"], C.fields["factions"], C.fields["quirks"], C.fields["bank_account"]))
else if(pod.growclone(C.fields["ckey"], C.fields["name"], C.fields["UI"], C.fields["SE"], C.fields["mind"], C.fields["blood_type"], C.fields["mrace"], C.fields["features"], C.fields["factions"], C.fields["quirks"], C.fields["bank_account"], C.fields["traumas"]))
temp = "[C.fields["name"]] => <font class='good'>Cloning cycle in progress...</font>"
playsound(src, 'sound/machines/terminal_prompt_confirm.ogg', 50, 0)
records.Remove(C)
@@ -429,14 +439,28 @@
else
temp = "<font class='bad'>Data corruption.</font>"
playsound(src, 'sound/machines/terminal_prompt_deny.ogg', 50, 0)
. = TRUE
else if (href_list["menu"])
src.menu = text2num(href_list["menu"])
else if (href_list["menu"] && use_records)
menu = text2num(href_list["menu"])
playsound(src, "terminal_type", 25, 0)
. = TRUE
/obj/machinery/computer/cloning/proc/finish_scan(mob/living/L, prev_locked)
if(!scanner || !L)
return
src.add_fingerprint(usr)
src.updateUsrDialog()
return
if(use_records)
scan_occupant(L)
else
clone_occupant(L)
loading = FALSE
src.updateUsrDialog()
playsound(src, 'sound/machines/terminal_prompt_confirm.ogg', 50, 0)
scanner.locked = prev_locked
/obj/machinery/computer/cloning/proc/scan_occupant(occupant)
var/mob/living/mob_occupant = get_mob_or_brainmob(occupant)
@@ -455,30 +479,9 @@
if(isbrain(mob_occupant))
dna = B.stored_dna
if(!istype(dna))
scantemp = "<font class='bad'>Unable to locate valid genetic data.</font>"
playsound(src, 'sound/machines/terminal_prompt_deny.ogg', 50, 0)
return
if(mob_occupant.suiciding || mob_occupant.hellbound)
scantemp = "<font class='bad'>Subject's brain is not responding to scanning stimuli.</font>"
playsound(src, 'sound/machines/terminal_prompt_deny.ogg', 50, 0)
return
if((HAS_TRAIT(mob_occupant, TRAIT_NOCLONE)) && (src.scanner.scan_level < 2))
scantemp = "<font class='bad'>Subject no longer contains the fundamental materials required to create a living clone.</font>"
playsound(src, 'sound/machines/terminal_alert.ogg', 50, 0)
return
if ((!mob_occupant.ckey) || (!mob_occupant.client))
scantemp = "<font class='bad'>Mental interface failure.</font>"
playsound(src, 'sound/machines/terminal_prompt_deny.ogg', 50, 0)
return
if (find_record("ckey", mob_occupant.ckey, records))
scantemp = "<font class='average'>Subject already in database.</font>"
playsound(src, 'sound/machines/terminal_prompt_deny.ogg', 50, 0)
return
if(SSeconomy.full_ancap && !has_bank_account)
scantemp = "<font class='average'>Subject is either missing an ID card with a bank account on it, or does not have an account to begin with. Please ensure the ID card is on the body before attempting to scan.</font>"
playsound(src, 'sound/machines/terminal_prompt_deny.ogg', 50, 0)
if(!can_scan(dna, mob_occupant, FALSE, has_bank_account))
return
var/datum/data/record/R = new()
if(dna.species)
// We store the instance rather than the path, because some
@@ -529,3 +532,78 @@
board.records = records
scantemp = "Subject successfully scanned."
playsound(src, 'sound/machines/terminal_prompt_confirm.ogg', 50, 0)
//Used by the experimental cloning computer.
/obj/machinery/computer/cloning/proc/clone_occupant(occupant)
var/mob/living/mob_occupant = get_mob_or_brainmob(occupant)
var/datum/dna/dna
if(ishuman(mob_occupant))
var/mob/living/carbon/C = mob_occupant
dna = C.has_dna()
if(isbrain(mob_occupant))
var/mob/living/brain/B = mob_occupant
dna = B.stored_dna
if(!can_scan(dna, mob_occupant, TRUE))
return
var/clone_species
if(dna.species)
clone_species = dna.species
else
var/datum/species/rando_race = pick(GLOB.roundstart_races)
clone_species = rando_race.type
var/obj/machinery/clonepod/pod = GetAvailablePod()
//Can't clone without someone to clone. Or a pod. Or if the pod is busy. Or full of gibs.
if(!LAZYLEN(pods))
temp = "<font class='bad'>No Clonepods detected.</font>"
playsound(src, 'sound/machines/terminal_prompt_deny.ogg', 50, 0)
else if(!pod)
temp = "<font class='bad'>No Clonepods available.</font>"
playsound(src, 'sound/machines/terminal_prompt_deny.ogg', 50, 0)
else if(pod.occupant)
temp = "<font class='bad'>Cloning cycle already in progress.</font>"
playsound(src, 'sound/machines/terminal_prompt_deny.ogg', 50, 0)
else
pod.growclone(null, mob_occupant.real_name, dna.uni_identity, dna.mutation_index, null, dna.blood_type, clone_species, dna.features, mob_occupant.faction)
temp = "[mob_occupant.real_name] => <font class='good'>Cloning data sent to pod.</font>"
playsound(src, 'sound/machines/terminal_prompt_confirm.ogg', 50, 0)
/obj/machinery/computer/cloning/proc/can_scan(datum/dna/dna, mob/living/mob_occupant, experimental = FALSE, datum/bank_account/account)
if(!istype(dna))
scantemp = "<font class='bad'>Unable to locate valid genetic data.</font>"
playsound(src, 'sound/machines/terminal_prompt_deny.ogg', 50, 0)
return
if(!experimental)
if(mob_occupant.suiciding || mob_occupant.hellbound)
scantemp = "<font class='bad'>Subject's brain is not responding to scanning stimuli.</font>"
playsound(src, 'sound/machines/terminal_prompt_deny.ogg', 50, 0)
return
if((HAS_TRAIT(mob_occupant, TRAIT_NOCLONE)) && (src.scanner.scan_level < 2))
scantemp = "<font class='bad'>Subject no longer contains the fundamental materials required to create a living clone.</font>"
playsound(src, 'sound/machines/terminal_alert.ogg', 50, 0)
return
if (!experimental)
if(!mob_occupant.ckey || !mob_occupant.client)
scantemp = "<font class='bad'>Mental interface failure.</font>"
playsound(src, 'sound/machines/terminal_prompt_deny.ogg', 50, 0)
return
if (find_record("ckey", mob_occupant.ckey, records))
scantemp = "<font class='average'>Subject already in database.</font>"
playsound(src, 'sound/machines/terminal_prompt_deny.ogg', 50, 0)
return
if(SSeconomy.full_ancap && !account)
scantemp = "<font class='average'>Subject is either missing an ID card with a bank account on it, or does not have an account to begin with. Please ensure the ID card is on the body before attempting to scan.</font>"
playsound(src, 'sound/machines/terminal_prompt_deny.ogg', 50, 0)
return
return TRUE
//Prototype cloning console, much more rudimental and lacks modern functions such as saving records, autocloning, or safety checks.
/obj/machinery/computer/cloning/prototype
name = "prototype cloning console"
desc = "Used to operate an experimental cloner."
icon_screen = "dna"
icon_keyboard = "med_key"
circuit = /obj/item/circuitboard/computer/cloning/prototype
clonepod_type = /obj/machinery/clonepod/experimental
-298
View File
@@ -1,298 +0,0 @@
//Experimental cloner; clones a body regardless of the owner's status, letting a ghost control it instead
/obj/machinery/clonepod/experimental
name = "experimental cloning pod"
desc = "An ancient cloning pod. It seems to be an early prototype of the experimental cloners used in Nanotrasen Stations."
icon = 'icons/obj/machines/cloning.dmi'
icon_state = "pod_0"
req_access = null
circuit = /obj/item/circuitboard/machine/clonepod/experimental
internal_radio = FALSE
//Start growing a human clone in the pod!
/obj/machinery/clonepod/experimental/growclone(clonename, ui, mutation_index, mindref, last_death, blood_type, datum/species/mrace, list/features, factions, list/quirks)
if(panel_open)
return FALSE
if(mess || attempting)
return FALSE
attempting = TRUE //One at a time!!
countdown.start()
var/mob/living/carbon/human/H = new /mob/living/carbon/human(src)
H.hardset_dna(ui, mutation_index, H.real_name, blood_type, mrace, features)
if(efficiency > 2)
var/list/unclean_mutations = (GLOB.not_good_mutations|GLOB.bad_mutations)
H.dna.remove_mutation_group(unclean_mutations)
if(efficiency > 5 && prob(20))
H.easy_randmut(POSITIVE)
if(efficiency < 3 && prob(50))
var/mob/M = H.easy_randmut(NEGATIVE+MINOR_NEGATIVE)
if(ismob(M))
H = M
H.silent = 20 //Prevents an extreme edge case where clones could speak if they said something at exactly the right moment.
occupant = H
if(!clonename) //to prevent null names
clonename = "clone ([rand(1,999)])"
H.real_name = clonename
icon_state = "pod_1"
//Get the clone body ready
maim_clone(H)
ADD_TRAIT(H, TRAIT_STABLEHEART, "cloning")
ADD_TRAIT(H, TRAIT_EMOTEMUTE, "cloning")
ADD_TRAIT(H, TRAIT_MUTE, "cloning")
ADD_TRAIT(H, TRAIT_NOBREATH, "cloning")
ADD_TRAIT(H, TRAIT_NOCRITDAMAGE, "cloning")
H.Unconscious(80)
var/list/candidates = pollCandidatesForMob("Do you want to play as [clonename]'s defective clone?", null, null, null, 100, H)
if(LAZYLEN(candidates))
var/mob/C = pick(candidates)
H.key = C.key
if(grab_ghost_when == CLONER_FRESH_CLONE)
H.grab_ghost()
to_chat(H, "<span class='notice'><b>Consciousness slowly creeps over you as your body regenerates.</b><br><i>So this is what cloning feels like?</i></span>")
if(grab_ghost_when == CLONER_MATURE_CLONE)
H.ghostize(TRUE) //Only does anything if they were still in their old body and not already a ghost
to_chat(H.get_ghost(TRUE), "<span class='notice'>Your body is beginning to regenerate in a cloning pod. You will become conscious when it is complete.</span>")
if(H)
H.faction |= factions
H.set_cloned_appearance()
H.suiciding = FALSE
attempting = FALSE
return TRUE
//Prototype cloning console, much more rudimental and lacks modern functions such as saving records, autocloning, or safety checks.
/obj/machinery/computer/prototype_cloning
name = "prototype cloning console"
desc = "Used to operate an experimental cloner."
icon_screen = "dna"
icon_keyboard = "med_key"
circuit = /obj/item/circuitboard/computer/prototype_cloning
var/obj/machinery/dna_scannernew/scanner = null //Linked scanner. For scanning.
var/list/pods //Linked experimental cloning pods
var/temp = "Inactive"
var/scantemp = "Ready to Scan"
var/loading = FALSE // Nice loading text
light_color = LIGHT_COLOR_BLUE
/obj/machinery/computer/prototype_cloning/Initialize()
. = ..()
updatemodules(TRUE)
/obj/machinery/computer/prototype_cloning/Destroy()
if(pods)
for(var/P in pods)
DetachCloner(P)
pods = null
return ..()
/obj/machinery/computer/prototype_cloning/proc/GetAvailablePod(mind = null)
if(pods)
for(var/P in pods)
var/obj/machinery/clonepod/experimental/pod = P
if(pod.is_operational() && !(pod.occupant || pod.mess))
return pod
/obj/machinery/computer/prototype_cloning/proc/updatemodules(findfirstcloner)
scanner = findscanner()
if(findfirstcloner && !LAZYLEN(pods))
findcloner()
/obj/machinery/computer/prototype_cloning/proc/findscanner()
var/obj/machinery/dna_scannernew/scannerf = null
// Loop through every direction
for(var/direction in GLOB.cardinals)
// Try to find a scanner in that direction
scannerf = locate(/obj/machinery/dna_scannernew, get_step(src, direction))
// If found and operational, return the scanner
if (!isnull(scannerf) && scannerf.is_operational())
return scannerf
// If no scanner was found, it will return null
return null
/obj/machinery/computer/prototype_cloning/proc/findcloner()
var/obj/machinery/clonepod/experimental/podf = null
for(var/direction in GLOB.cardinals)
podf = locate(/obj/machinery/clonepod/experimental, get_step(src, direction))
if (!isnull(podf) && podf.is_operational())
AttachCloner(podf)
/obj/machinery/computer/prototype_cloning/proc/AttachCloner(obj/machinery/clonepod/experimental/pod)
if(!pod.connected)
pod.connected = src
LAZYADD(pods, pod)
/obj/machinery/computer/prototype_cloning/proc/DetachCloner(obj/machinery/clonepod/experimental/pod)
pod.connected = null
LAZYREMOVE(pods, pod)
/obj/machinery/computer/prototype_cloning/attackby(obj/item/W, mob/user, params)
if(istype(W, /obj/item/multitool))
var/obj/item/multitool/P = W
if(istype(P.buffer, /obj/machinery/clonepod/experimental))
if(get_area(P.buffer) != get_area(src))
to_chat(user, "<font color = #666633>-% Cannot link machines across power zones. Buffer cleared %-</font color>")
P.buffer = null
return
to_chat(user, "<font color = #666633>-% Successfully linked [P.buffer] with [src] %-</font color>")
var/obj/machinery/clonepod/experimental/pod = P.buffer
if(pod.connected)
pod.connected.DetachCloner(pod)
AttachCloner(pod)
else
P.buffer = src
to_chat(user, "<font color = #666633>-% Successfully stored [REF(P.buffer)] [P.buffer.name] in buffer %-</font color>")
return
else
return ..()
/obj/machinery/computer/prototype_cloning/attack_hand(mob/user)
if(..())
return
interact(user)
/obj/machinery/computer/prototype_cloning/interact(mob/user)
user.set_machine(src)
add_fingerprint(user)
if(..())
return
updatemodules(TRUE)
var/dat = ""
dat += "<a href='byond://?src=[REF(src)];refresh=1'>Refresh</a>"
dat += "<h3>Cloning Pod Status</h3>"
dat += "<div class='statusDisplay'>[temp]&nbsp;</div>"
if (isnull(src.scanner) || !LAZYLEN(pods))
dat += "<h3>Modules</h3>"
//dat += "<a href='byond://?src=[REF(src)];relmodules=1'>Reload Modules</a>"
if (isnull(src.scanner))
dat += "<font class='bad'>ERROR: No Scanner detected!</font><br>"
if (!LAZYLEN(pods))
dat += "<font class='bad'>ERROR: No Pod detected</font><br>"
// Scan-n-Clone
if (!isnull(src.scanner))
var/mob/living/scanner_occupant = get_mob_or_brainmob(scanner.occupant)
dat += "<h3>Cloning</h3>"
dat += "<div class='statusDisplay'>"
if(!scanner_occupant)
dat += "Scanner Unoccupied"
else if(loading)
dat += "[scanner_occupant] => Scanning..."
else
scantemp = "Ready to Clone"
dat += "[scanner_occupant] => [scantemp]"
dat += "</div>"
if(scanner_occupant)
dat += "<a href='byond://?src=[REF(src)];clone=1'>Clone</a>"
dat += "<br><a href='byond://?src=[REF(src)];lock=1'>[src.scanner.locked ? "Unlock Scanner" : "Lock Scanner"]</a>"
else
dat += "<span class='linkOff'>Clone</span>"
var/datum/browser/popup = new(user, "cloning", "Prototype Cloning System Control")
popup.set_content(dat)
popup.set_title_image(user.browse_rsc_icon(src.icon, src.icon_state))
popup.open()
/obj/machinery/computer/prototype_cloning/Topic(href, href_list)
if(..())
return
if(loading)
return
else if ((href_list["clone"]) && !isnull(scanner) && scanner.is_operational())
scantemp = ""
loading = TRUE
updateUsrDialog()
playsound(src, 'sound/machines/terminal_prompt.ogg', 50, 0)
say("Initiating scan...")
spawn(20)
clone_occupant(scanner.occupant)
loading = FALSE
updateUsrDialog()
playsound(src, 'sound/machines/terminal_prompt_confirm.ogg', 50, 0)
//No locking an open scanner.
else if ((href_list["lock"]) && !isnull(scanner) && scanner.is_operational())
if ((!scanner.locked) && (scanner.occupant))
scanner.locked = TRUE
playsound(src, 'sound/machines/terminal_prompt_deny.ogg', 50, 0)
else
scanner.locked = FALSE
playsound(src, 'sound/machines/terminal_prompt_confirm.ogg', 50, 0)
else if (href_list["refresh"])
updateUsrDialog()
playsound(src, "terminal_type", 25, 0)
add_fingerprint(usr)
updateUsrDialog()
return
/obj/machinery/computer/prototype_cloning/proc/clone_occupant(occupant)
var/mob/living/mob_occupant = get_mob_or_brainmob(occupant)
var/datum/dna/dna
if(ishuman(mob_occupant))
var/mob/living/carbon/C = mob_occupant
dna = C.has_dna()
if(isbrain(mob_occupant))
var/mob/living/brain/B = mob_occupant
dna = B.stored_dna
if(!istype(dna))
scantemp = "<font class='bad'>Unable to locate valid genetic data.</font>"
playsound(src, 'sound/machines/terminal_prompt_deny.ogg', 50, 0)
return
if((HAS_TRAIT(mob_occupant, TRAIT_NOCLONE)) && (src.scanner.scan_level < 2))
scantemp = "<font class='bad'>Subject no longer contains the fundamental materials required to create a living clone.</font>"
playsound(src, 'sound/machines/terminal_alert.ogg', 50, 0)
return
var/clone_species
if(dna.species)
clone_species = dna.species
else
var/datum/species/rando_race = pick(GLOB.roundstart_races)
clone_species = rando_race.type
var/obj/machinery/clonepod/pod = GetAvailablePod()
//Can't clone without someone to clone. Or a pod. Or if the pod is busy. Or full of gibs.
if(!LAZYLEN(pods))
temp = "<font class='bad'>No Clonepods detected.</font>"
playsound(src, 'sound/machines/terminal_prompt_deny.ogg', 50, 0)
else if(!pod)
temp = "<font class='bad'>No Clonepods available.</font>"
playsound(src, 'sound/machines/terminal_prompt_deny.ogg', 50, 0)
else if(pod.occupant)
temp = "<font class='bad'>Cloning cycle already in progress.</font>"
playsound(src, 'sound/machines/terminal_prompt_deny.ogg', 50, 0)
else
pod.growclone(mob_occupant.real_name, dna.uni_identity, dna.mutation_index, null, null, dna.blood_type, clone_species, dna.features, mob_occupant.faction)
temp = "[mob_occupant.real_name] => <font class='good'>Cloning data sent to pod.</font>"
playsound(src, 'sound/machines/terminal_prompt_confirm.ogg', 50, 0)
+5
View File
@@ -212,6 +212,11 @@
desc = "A heretical poster depicting the titular star of an equally heretical book."
icon_state = "poster4"
/obj/structure/sign/poster/contraband/post_ratvar
name = "Post This Ratvar"
desc = "Oh what in the hell? Those cultists have animated paper technology and they use it for a meme?"
icon_state = "postvar"
/obj/structure/sign/poster/contraband/syndicate_recruitment
name = "Syndicate Recruitment"
desc = "See the galaxy! Shatter corrupt megacorporations! Join today!"
+24 -5
View File
@@ -68,6 +68,7 @@ GLOBAL_VAR_INIT(embedpocalypse, FALSE) // if true, all items will be able to emb
var/click_delay = CLICK_CD_MELEE
var/slot_flags = 0 //This is used to determine on which slots an item can fit.
var/current_equipped_slot
pass_flags = PASSTABLE
pressure_resistance = 4
var/obj/item/master = null
@@ -179,6 +180,11 @@ GLOBAL_VAR_INIT(embedpocalypse, FALSE) // if true, all items will be able to emb
if(damtype == "brute")
hitsound = "swing_hit"
if(used_skills)
for(var/path in used_skills)
var/datum/skill/S = GLOB.skill_datums[path]
LAZYADD(used_skills[path], S.skill_traits)
/obj/item/Destroy()
item_flags &= ~DROPDEL //prevent reqdels
if(ismob(loc))
@@ -315,6 +321,10 @@ GLOBAL_VAR_INIT(embedpocalypse, FALSE) // if true, all items will be able to emb
return
if(anchored)
return
if(loc == user && current_equipped_slot && current_equipped_slot != SLOT_HANDS)
if(current_equipped_slot in user.check_obscured_slots())
to_chat(src, "<span class='warning'>You are unable to unequip that while wearing other garments over it!</span>")
return FALSE
if(resistance_flags & ON_FIRE)
var/mob/living/carbon/C = user
@@ -336,7 +346,7 @@ GLOBAL_VAR_INIT(embedpocalypse, FALSE) // if true, all items will be able to emb
C.update_damage_overlays()
return
if(acid_level > 20 && !ismob(loc))// so we can still remove the clothes on us that have acid.
if(acid_level > 20 && ismob(loc))// so we can still remove the clothes on us that have acid.
var/mob/living/carbon/C = user
if(istype(C))
if(!C.gloves || (!(C.gloves.resistance_flags & (UNACIDABLE|ACID_PROOF))))
@@ -379,6 +389,11 @@ GLOBAL_VAR_INIT(embedpocalypse, FALSE) // if true, all items will be able to emb
return
if(anchored)
return
if(loc == user && current_equipped_slot && current_equipped_slot != SLOT_HANDS)
if(current_equipped_slot in user.check_obscured_slots())
to_chat(src, "<span class='warning'>You are unable to unequip that while wearing other garments over it!</span>")
return FALSE
SEND_SIGNAL(loc, COMSIG_TRY_STORAGE_TAKE, src, user.loc, TRUE)
@@ -423,6 +438,7 @@ GLOBAL_VAR_INIT(embedpocalypse, FALSE) // if true, all items will be able to emb
/obj/item/proc/dropped(mob/user)
SHOULD_CALL_PARENT(TRUE)
current_equipped_slot = null
for(var/X in actions)
var/datum/action/A = X
A.Remove(user)
@@ -470,7 +486,9 @@ GLOBAL_VAR_INIT(embedpocalypse, FALSE) // if true, all items will be able to emb
// for items that can be placed in multiple slots
// note this isn't called during the initial dressing of a player
/obj/item/proc/equipped(mob/user, slot)
SHOULD_CALL_PARENT(TRUE)
. = SEND_SIGNAL(src, COMSIG_ITEM_EQUIPPED, user, slot)
current_equipped_slot = slot
if(!(. & COMPONENT_NO_GRANT_ACTIONS))
for(var/X in actions)
var/datum/action/A = X
@@ -496,11 +514,11 @@ GLOBAL_VAR_INIT(embedpocalypse, FALSE) // if true, all items will be able to emb
//if this is being done by a mob other than M, it will include the mob equipper, who is trying to equip the item to mob M. equipper will be null otherwise.
//If you are making custom procs but would like to retain partial or complete functionality of this one, include a 'return ..()' to where you want this to happen.
//Set disable_warning to TRUE if you wish it to not give you outputs.
/obj/item/proc/mob_can_equip(mob/living/M, mob/living/equipper, slot, disable_warning = FALSE, bypass_equip_delay_self = FALSE)
/obj/item/proc/mob_can_equip(mob/living/M, mob/living/equipper, slot, disable_warning = FALSE, bypass_equip_delay_self = FALSE, clothing_check = FALSE, list/return_warning)
if(!M)
return FALSE
return M.can_equip(src, slot, disable_warning, bypass_equip_delay_self)
return M.can_equip(src, slot, disable_warning, bypass_equip_delay_self, clothing_check, return_warning)
/obj/item/verb/verb_pickup()
set src in oview(1)
@@ -835,7 +853,7 @@ GLOBAL_VAR_INIT(embedpocalypse, FALSE) // if true, all items will be able to emb
// Called when a mob tries to use the item as a tool.
// Handles most checks.
/obj/item/proc/use_tool(atom/target, mob/living/user, delay, amount=0, volume=0, datum/callback/extra_checks, skill_gain_mult = 1, max_level = INFINITY)
/obj/item/proc/use_tool(atom/target, mob/living/user, delay, amount=0, volume=0, datum/callback/extra_checks, skill_gain_mult = STD_USE_TOOL_MULT)
// No delay means there is no start message, and no reason to call tool_start_check before use_tool.
// Run the start check here so we wouldn't have to call it manually.
if(!delay && !tool_start_check(user, amount))
@@ -880,7 +898,8 @@ GLOBAL_VAR_INIT(embedpocalypse, FALSE) // if true, all items will be able to emb
for(var/skill in used_skills)
if(!(SKILL_TRAINING_TOOL in used_skills[skill]))
continue
user.mind.auto_gain_experience(skill, gain*skill_gain_mult, GET_STANDARD_LVL(max_level))
var/datum/skill/S = GLOB.skill_datums[skill]
user.mind.auto_gain_experience(skill, gain*skill_gain_mult*S.item_skill_gain_multi)
return TRUE
+5 -4
View File
@@ -29,6 +29,11 @@
RegisterSignal(src, COMSIG_TWOHANDED_UNWIELD, .proc/on_unwield)
update_icon()
/obj/item/rcl/ComponentInitialize()
. = ..()
AddElement(/datum/element/update_icon_updates_onmob)
AddComponent(/datum/component/two_handed)
/// triggered on wield of two handed item
/obj/item/rcl/proc/on_wield(obj/item/source, mob/user)
active = TRUE
@@ -37,10 +42,6 @@
/obj/item/rcl/proc/on_unwield(obj/item/source, mob/user)
active = FALSE
/obj/item/rcl/ComponentInitialize()
. = ..()
AddElement(/datum/element/update_icon_updates_onmob)
/obj/item/rcl/attackby(obj/item/W, mob/user)
if(istype(W, /obj/item/stack/cable_coil))
var/obj/item/stack/cable_coil/C = W
+1
View File
@@ -794,6 +794,7 @@ CIGARETTE PACKETS ARE IN FANCY.DM
reagents.clear_reagents()
/obj/item/clothing/mask/vape/equipped(mob/user, slot)
. = ..()
if(slot == SLOT_WEAR_MASK)
if(!screw)
to_chat(user, "<span class='notice'>You start puffing on the vape.</span>")
@@ -116,9 +116,9 @@
build_path = /obj/machinery/computer/cloning
var/list/records = list()
/obj/item/circuitboard/computer/prototype_cloning
/obj/item/circuitboard/computer/cloning/prototype
name = "Prototype Cloning (Computer Board)"
build_path = /obj/machinery/computer/prototype_cloning
build_path = /obj/machinery/computer/cloning/prototype
/obj/item/circuitboard/computer/arcade/battle
name = "Arcade Battle (Computer Board)"
+5
View File
@@ -72,6 +72,11 @@
TEXT_ATTACK_TYPE_PROJECTILE = 4
)
/obj/item/dualsaber/Initialize()
. = ..()
RegisterSignal(src, COMSIG_TWOHANDED_WIELD, .proc/on_wield)
RegisterSignal(src, COMSIG_TWOHANDED_UNWIELD, .proc/on_unwield)
/obj/item/dualsaber/ComponentInitialize()
. = ..()
AddComponent(/datum/component/two_handed, force_unwielded=3, force_wielded=34, \
@@ -97,7 +97,7 @@
to_chat(user, "<span class='notice'>You add [A] to the [initial(name)] assembly.</span>")
else if(stage == EMPTY && istype(I, /obj/item/stack/cable_coil))
if (I.use_tool(src, user, 0, 1, max_level = JOB_SKILL_BASIC))
if (I.use_tool(src, user, 0, 1, skill_gain_mult = TRIVIAL_USE_TOOL_MULT))
det_time = 50 // In case the cable_coil was removed and readded.
stage_change(WIRED)
to_chat(user, "<span class='notice'>You rig the [initial(name)] assembly.</span>")
+1
View File
@@ -168,6 +168,7 @@
icon_state = "witchhunterhat"
item_state = "witchhunterhat"
flags_cover = HEADCOVERSEYES
flags_inv = HIDEHAIR
/obj/item/storage/box/holy/follower
name = "Followers of the Chaplain Kit"
+96 -17
View File
@@ -22,6 +22,11 @@
var/occupant_weight = 0
var/max_occupants = 3 //Hard-cap so you can't have infinite mice or something in one carrier
var/max_occupant_weight = MOB_SIZE_SMALL //This is calculated from the mob sizes of occupants
var/entrance_name = "door" //name of the entrance to the item
var/escape_time = 200 //how long it takes for mobs above small sizes to escape (for small sizes, its randomly 1.5 to 2x this)
var/load_time = 30 //how long it takes for mobs to be loaded into the pet carrier
var/has_lock_sprites = TRUE //whether to load the lock overlays or not
var/allows_hostiles = FALSE //does the pet carrier allow hostile entities to be held within it?
/obj/item/pet_carrier/Destroy()
if(occupants.len)
@@ -51,20 +56,20 @@
else
. += "<span class='notice'>It has nothing inside.</span>"
if(user.canUseTopic(src))
. += "<span class='notice'>Activate it in your hand to [open ? "close" : "open"] its door.</span>"
. += "<span class='notice'>Activate it in your hand to [open ? "close" : "open"] its [entrance_name].</span>"
if(!open)
. += "<span class='notice'>Alt-click to [locked ? "unlock" : "lock"] its door.</span>"
. += "<span class='notice'>Alt-click to [locked ? "unlock" : "lock"] its [entrance_name].</span>"
/obj/item/pet_carrier/attack_self(mob/living/user)
if(open)
to_chat(user, "<span class='notice'>You close [src]'s door.</span>")
to_chat(user, "<span class='notice'>You close [src]'s [entrance_name].</span>")
playsound(user, 'sound/effects/bin_close.ogg', 50, TRUE)
open = FALSE
else
if(locked)
to_chat(user, "<span class='warning'>[src] is locked!</span>")
return
to_chat(user, "<span class='notice'>You open [src]'s door.</span>")
to_chat(user, "<span class='notice'>You open [src]'s [entrance_name].</span>")
playsound(user, 'sound/effects/bin_open.ogg', 50, TRUE)
open = TRUE
update_icon()
@@ -86,7 +91,7 @@
if(user.a_intent == INTENT_HARM)
return ..()
if(!open)
to_chat(user, "<span class='warning'>You need to open [src]'s door!</span>")
to_chat(user, "<span class='warning'>You need to open [src]'s [entrance_name]!</span>")
return
if(target.mob_size > max_occupant_weight)
if(ishuman(target))
@@ -94,13 +99,15 @@
if(iscatperson(H))
to_chat(user, "<span class='warning'>You'd need a lot of catnip and treats, plus maybe a laser pointer, for that to work.</span>")
else
to_chat(user, "<span class='warning'>Humans, generally, do not fit into pet carriers.</span>")
to_chat(user, "<span class='warning'>Humans, generally, do not fit into [name]s.</span>")
else
to_chat(user, "<span class='warning'>You get the feeling [target] isn't meant for a [name].</span>")
return
if(user == target)
to_chat(user, "<span class='warning'>Why would you ever do that?</span>")
return
if(ishostile(target) && !allows_hostiles && target.move_resist < MOVE_FORCE_VERY_STRONG) //don't allow goliaths into pet carriers
to_chat(user, "<span class='warning'>You have a feeling you shouldn't keep this as a pet.</span>")
load_occupant(user, target)
/obj/item/pet_carrier/relaymove(mob/living/user, direction)
@@ -110,8 +117,8 @@
remove_occupant(user)
return
else if(!locked)
loc.visible_message("<span class='notice'>[user] pushes open the door to [src]!</span>", \
"<span class='warning'>[user] pushes open the door of [src]!</span>")
loc.visible_message("<span class='notice'>[user] pushes open the [entrance_name] to [src]!</span>", \
"<span class='warning'>[user] pushes open the [entrance_name] of [src]!</span>")
open = TRUE
update_icon()
return
@@ -119,12 +126,19 @@
container_resist(user)
/obj/item/pet_carrier/container_resist(mob/living/user)
//don't do the whole resist timer thing if it's open!
if(open)
loc.visible_message("<span class='notice'>[user] climbs out of [src]!</span>", \
"<span class='warning'>[user] jumps out of [src]!</span>")
remove_occupant(user)
return
user.changeNext_move(CLICK_CD_BREAKOUT)
user.last_special = world.time + CLICK_CD_BREAKOUT
if(user.mob_size <= MOB_SIZE_SMALL)
to_chat(user, "<span class='notice'>You poke a limb through [src]'s bars and start fumbling for the lock switch... (This will take some time.)</span>")
to_chat(loc, "<span class='warning'>You see [user] reach through the bars and fumble for the lock switch!</span>")
if(!do_after(user, rand(300, 400), target = user) || open || !locked || !(user in occupants))
to_chat(user, "<span class='notice'>You begin to try escaping the [src] and start fumbling for the lock switch... (This will take some time.)</span>")
to_chat(loc, "<span class='warning'>You see [user] attempting to unlock the [src]!</span>")
if(!do_after(user, rand(escape_time * 1.5, escape_time * 2), target = user) || open || !locked || !(user in occupants))
return
loc.visible_message("<span class='warning'>[user] flips the lock switch on [src] by reaching through!</span>", null, null, null, user)
to_chat(user, "<span class='boldannounce'>Bingo! The lock pops open!</span>")
@@ -132,12 +146,12 @@
playsound(src, 'sound/machines/boltsup.ogg', 30, TRUE)
update_icon()
else
loc.visible_message("<span class='warning'>[src] starts rattling as something pushes against the door!</span>", null, null, null, user)
loc.visible_message("<span class='warning'>[src] starts rattling as something pushes against the [entrance_name]!</span>", null, null, null, user)
to_chat(user, "<span class='notice'>You start pushing out of [src]... (This will take about 20 seconds.)</span>")
if(!do_after(user, 200, target = user) || open || !locked || !(user in occupants))
if(!do_after(user, escape_time, target = user) || open || !locked || !(user in occupants))
return
loc.visible_message("<span class='warning'>[user] shoves out of [src]!</span>", null, null, null, user)
to_chat(user, "<span class='notice'>You shove open [src]'s door against the lock's resistance and fall out!</span>")
to_chat(user, "<span class='notice'>You shove open [src]'s [entrance_name] against the lock's resistance and fall out!</span>")
locked = FALSE
open = TRUE
update_icon()
@@ -151,7 +165,7 @@
/obj/item/pet_carrier/update_overlays()
. = ..()
if(!open)
if(!open && has_lock_sprites)
. += "[locked ? "" : "un"]locked"
/obj/item/pet_carrier/MouseDrop(atom/over_atom)
@@ -170,7 +184,7 @@
user.visible_message("<span class='notice'>[user] starts loading [target] into [src].</span>", \
"<span class='notice'>You start loading [target] into [src]...</span>", null, null, target)
to_chat(target, "<span class='userdanger'>[user] starts loading you into [user.p_their()] [name]!</span>")
if(!do_mob(user, target, 30))
if(!do_mob(user, target, load_time))
return
if(target in occupants)
return
@@ -192,9 +206,74 @@
/obj/item/pet_carrier/proc/remove_occupant(mob/living/occupant, turf/new_turf)
if(!(occupant in occupants) || !istype(occupant))
return
occupant.forceMove(new_turf ? new_turf : drop_location())
occupant.forceMove(new_turf ? new_turf : get_turf(src))
occupants -= occupant
occupant_weight -= occupant.mob_size
occupant.setDir(SOUTH)
//bluespace jar, a reskin of the pet carrier that can fit people and smashes when thrown
/obj/item/pet_carrier/bluespace
name = "bluespace jar"
desc = "A jar, that seems to be bigger on the inside, somehow allowing lifeforms to fit through its narrow entrance."
open = FALSE //starts closed so it looks better on menus
icon_state = "bluespace_jar"
item_state = "bluespace_jar"
lefthand_file = ""
righthand_file = ""
max_occupant_weight = MOB_SIZE_HUMAN //can fit people, like a bluespace bodybag!
load_time = 40 //loading things into a jar takes longer than a regular pet carrier
entrance_name = "lid"
w_class = WEIGHT_CLASS_SMALL //it's a jar
throw_speed = 3
throw_range = 7
max_occupants = 1 //far less than a regular carrier or bluespace bodybag, because it can be thrown to release the contents
allows_hostiles = TRUE //can fit hostile creatures, with the move resist restrictions in place, this means they still cannot take things like legions/goliaths/etc regardless
has_lock_sprites = FALSE //jar doesn't show the regular lock overlay
custom_materials = list(/datum/material/glass = 1000, /datum/material/bluespace = 600)
escape_time = 10 //half the time of a bluespace bodybag
var/datum/gas_mixture/occupant_gas_supply
/obj/item/pet_carrier/bluespace/update_icon_state()
if(open)
icon_state = "bluespace_jar_open"
else
icon_state = "bluespace_jar"
/obj/item/pet_carrier/bluespace/throw_impact()
. = ..()
//delete the item upon impact, releasing the creature inside (this is handled by its deletion)
if(occupants.len)
loc.visible_message("<span class='warning'>The bluespace jar smashes, releasing [occupants[1]]!</span>")
playsound(src, "shatter", 70, 1)
qdel(src)
/obj/item/pet_carrier/bluespace/add_occupant(mob/living/occupant) //update the gas supply as required, this acts like magical internals
. = ..()
if(!occupant_gas_supply)
occupant_gas_supply = new
if(isanimal(occupant))
var/mob/living/simple_animal/animal = occupant
occupant_gas_supply.temperature = animal.minbodytemp //simple animals only care about temperature when their turf isnt a location
else
if(ishuman(occupant)) //humans require resistance to cold/heat and living in no air while inside, and lose this when outside
ADD_TRAIT(occupant, TRAIT_RESISTCOLD, "bluespace_container_cold_resist")
ADD_TRAIT(occupant, TRAIT_RESISTHEAT, "bluespace_container_heat_resist")
ADD_TRAIT(occupant, TRAIT_NOBREATH, "bluespace_container_no_breath")
ADD_TRAIT(occupant, TRAIT_RESISTHIGHPRESSURE, "bluespace_container_resist_high_pressure")
ADD_TRAIT(occupant, TRAIT_RESISTLOWPRESSURE, "bluespace_container_resist_low_pressure")
/obj/item/pet_carrier/bluespace/remove_occupant(mob/living/occupant)
. = ..()
if(ishuman(occupant))
REMOVE_TRAIT(occupant, TRAIT_RESISTCOLD, "bluespace_container_cold_resist")
REMOVE_TRAIT(occupant, TRAIT_RESISTHEAT, "bluespace_container_heat_resist")
REMOVE_TRAIT(occupant, TRAIT_NOBREATH, "bluespace_container_no_breath")
REMOVE_TRAIT(occupant, TRAIT_RESISTHIGHPRESSURE, "bluespace_container_resist_high_pressure")
REMOVE_TRAIT(occupant, TRAIT_RESISTLOWPRESSURE, "bluespace_container_resist_low_pressure")
/obj/item/pet_carrier/bluespace/return_air()
if(!occupant_gas_supply)
occupant_gas_supply = new
return occupant_gas_supply
#undef pet_carrier_full
@@ -355,6 +355,7 @@
emaggedhitdamage = 0
/obj/item/borg/lollipop/equipped()
. = ..()
check_amount()
/obj/item/borg/lollipop/dropped(mob/user)
+2 -2
View File
@@ -26,7 +26,7 @@
/datum/block_parry_data/shield
block_damage_multiplier = 0.25
block_stamina_efficiency = 2.5
block_stamina_cost_per_second = 3.5
block_stamina_cost_per_second = 2.5
block_slowdown = 0
block_lock_attacking = FALSE
block_lock_sprinting = TRUE
@@ -386,7 +386,7 @@ obj/item/shield/riot/bullet_proof
max_integrity = 100
obj_integrity = 100
can_shatter = FALSE
item_flags = SLOWS_WHILE_IN_HAND
item_flags = SLOWS_WHILE_IN_HAND | ITEM_CAN_BLOCK
var/recharge_timerid
var/recharge_delay = 15 SECONDS
@@ -69,7 +69,7 @@ GLOBAL_LIST_INIT(glass_recipes, list ( \
if (get_amount() < 1 || CC.get_amount() < 5)
to_chat(user, "<span class='warning>You need five lengths of coil and one sheet of glass to make wired glass!</span>")
return
CC.use_tool(src, user, 0, 5, max_level = JOB_SKILL_BASIC)
CC.use_tool(src, user, 0, 5, skill_gain_mult = TRIVIAL_USE_TOOL_MULT)
use(1)
to_chat(user, "<span class='notice'>You attach wire to the [name].</span>")
var/obj/item/stack/light_w/new_tile = new(user.loc)
@@ -430,6 +430,7 @@ GLOBAL_LIST_INIT(snow_recipes, list ( \
singular_name = "alien alloy sheet"
sheettype = "abductor"
merge_type = /obj/item/stack/sheet/mineral/abductor
walltype = /turf/closed/wall/mineral/abductor
GLOBAL_LIST_INIT(abductor_recipes, list ( \
new/datum/stack_recipe("alien bed", /obj/structure/bed/abductor, 2, one_per_turf = 1, on_floor = 1), \
@@ -381,6 +381,7 @@ GLOBAL_LIST_INIT(cloth_recipes, list ( \
new/datum/stack_recipe("chemistry bag", /obj/item/storage/bag/chemistry, 4), \
new/datum/stack_recipe("bio bag", /obj/item/storage/bag/bio, 4), \
null, \
new/datum/stack_recipe("string", /obj/item/weaponcrafting/string, 1, time = 10), \
new/datum/stack_recipe("improvised gauze", /obj/item/stack/medical/gauze/improvised, 1, 2, 6), \
new/datum/stack_recipe("rag", /obj/item/reagent_containers/rag, 1), \
new/datum/stack_recipe("towel", /obj/item/reagent_containers/rag/towel, 3), \
@@ -428,7 +429,6 @@ GLOBAL_LIST_INIT(durathread_recipes, list ( \
new/datum/stack_recipe("durathread beret", /obj/item/clothing/head/beret/durathread, 2, time = 40), \
new/datum/stack_recipe("durathread beanie", /obj/item/clothing/head/beanie/durathread, 2, time = 40), \
new/datum/stack_recipe("durathread bandana", /obj/item/clothing/mask/bandana/durathread, 1, time = 25), \
new/datum/stack_recipe("durathread string", /obj/item/weaponcrafting/durathread_string, 1, time = 40), \
))
/obj/item/stack/sheet/durathread
+11 -1
View File
@@ -326,6 +326,7 @@
w_class = WEIGHT_CLASS_BULKY
flags_1 = CONDUCT_1
custom_materials = list(/datum/material/iron=3000)
var/max_items = 7
/obj/item/storage/bag/tray/ComponentInitialize()
. = ..()
@@ -333,6 +334,7 @@
STR.max_w_class = WEIGHT_CLASS_NORMAL
STR.can_hold = typecacheof(list(/obj/item/reagent_containers/food, /obj/item/reagent_containers/glass, /datum/reagent/consumable, /obj/item/kitchen/knife, /obj/item/kitchen/rollingpin, /obj/item/kitchen/fork, /obj/item/storage/box)) //Should cover: Bottles, Beakers, Bowls, Booze, Glasses, Food, Kitchen Tools, and ingredient boxes.
STR.insert_preposition = "on"
STR.max_items = max_items
/obj/item/storage/bag/tray/attack(mob/living/M, mob/living/user)
. = ..()
@@ -373,6 +375,14 @@
. = ..()
update_icon()
//bluespace tray, holds more items
/obj/item/storage/bag/tray/bluespace
name = "bluespace tray"
icon_state = "bluespace_tray"
desc = "A tray created using bluespace technology to fit more food on it."
max_items = 30 // far more items
custom_materials = list(/datum/material/iron = 2000, /datum/material/bluespace = 500)
/*
* Chemistry bag
*/
@@ -462,4 +472,4 @@
STR.max_combined_w_class = INFINITY
STR.max_items = 2
STR.display_numerical_stacking = TRUE
STR.can_hold = typecacheof(list(/obj/item/rcd_ammo, /obj/item/stack/sheet))
STR.can_hold = typecacheof(list(/obj/item/rcd_ammo, /obj/item/stack/sheet))
+4 -4
View File
@@ -207,18 +207,18 @@
cig_position++
/obj/item/storage/fancy/cigarettes/attack(mob/living/carbon/M as mob, mob/living/carbon/user as mob)
if(!ismob(M))
return
if(M != user || !istype(M))
return ..()
var/obj/item/clothing/mask/cigarette/cig = locate(/obj/item/clothing/mask/cigarette) in contents
if(cig)
if(M == user && contents.len > 0 && !user.wear_mask)
if(!user.wear_mask && !(SLOT_WEAR_MASK in M.check_obscured_slots()))
var/obj/item/clothing/mask/cigarette/W = cig
SEND_SIGNAL(src, COMSIG_TRY_STORAGE_TAKE, W, M)
M.equip_to_slot_if_possible(W, SLOT_WEAR_MASK)
contents -= W
to_chat(user, "<span class='notice'>You take \a [W] out of the pack.</span>")
else
..()
return ..()
else
to_chat(user, "<span class='notice'>There are no [icon_type]s left in the pack.</span>")
+4 -7
View File
@@ -450,8 +450,7 @@
sharpness = IS_BLUNT
/obj/item/dualsaber/toy/ComponentInitialize()
. = ..()
AddComponent(/datum/component/two_handed, wieldsound='sound/weapons/saberon.ogg', unwieldsound='sound/weapons/saberoff.ogg')
AddComponent(/datum/component/two_handed, force_unwielded=0, force_wielded=0, wieldsound='sound/weapons/saberon.ogg', unwieldsound='sound/weapons/saberoff.ogg')
/obj/item/dualsaber/toy/run_block(mob/living/owner, atom/object, damage, attack_text, attack_type, armour_penetration, mob/attacker, def_zone, final_block_chance, list/block_return)
return BLOCK_NONE
@@ -469,9 +468,8 @@
slowdown_wielded = 0
sharpness = IS_BLUNT
/obj/item/dualsaber/toy/ComponentInitialize()
. = ..()
AddComponent(/datum/component/two_handed, wieldsound='sound/weapons/saberon.ogg', unwieldsound='sound/weapons/saberoff.ogg')
/obj/item/dualsaber/hypereutactic/toy/ComponentInitialize()
AddComponent(/datum/component/two_handed, force_unwielded=0, force_wielded=0, wieldsound='sound/weapons/saberon.ogg', unwieldsound='sound/weapons/saberoff.ogg')
/obj/item/dualsaber/hypereutactic/toy/run_block(mob/living/owner, atom/object, damage, attack_text, attack_type, armour_penetration, mob/attacker, def_zone, final_block_chance, list/block_return)
return BLOCK_NONE
@@ -828,12 +826,11 @@
var/obj/item/toy/cards/singlecard/H = new/obj/item/toy/cards/singlecard(user.loc)
if(holo)
holo.spawned += H // track them leaving the holodeck
choice = cards[1]
choice = popleft(cards)
H.cardname = choice
H.parentdeck = src
var/O = src
H.apply_card_vars(H,O)
src.cards -= choice
H.pickup(user)
user.put_in_hands(H)
user.visible_message("[user] draws a card from the deck.", "<span class='notice'>You draw a card from the deck.</span>")
@@ -108,8 +108,7 @@
//Life, Stat, Hud Updates, and Say
/mob/living/simple_animal/revenant/BiologicalLife(seconds, times_fired)
if(!(. = ..()))
return
. = ..()
if(stasis)
return
if(revealed && essence <= 0)
@@ -1,11 +1,4 @@
/client
var/list/sent_assets = list() // List of all asset filenames sent to this client by the asset cache, along with their assoicated md5s
var/list/completed_asset_jobs = list() /// List of all completed blocking send jobs awaiting acknowledgement by send_asset
var/last_asset_job = 0 /// Last asset send job id.
var/last_completed_asset_job = 0
/// Process asset cache client topic calls for "asset_cache_confirm_arrival=[INT]"
/client/proc/asset_cache_confirm_arrival(job_id)
var/asset_cache_job = round(text2num(job_id))
@@ -50,7 +43,7 @@
var/t = 0
var/timeout_time = timeout
src << browse({"<script>window.location.href="?asset_cache_confirm_arrival=[job]"</script>"}, "window=asset_cache_browser&file=asset_cache_send_verify.htm")
while(!completed_asset_jobs["[job]"] && t < timeout_time) // Reception is handled in Topic()
stoplag(1) // Lock up the caller until this is received.
t++
+1 -1
View File
@@ -415,7 +415,7 @@
"dna_discovered.gif" = 'html/dna_discovered.gif',
"dna_undiscovered.gif" = 'html/dna_undiscovered.gif',
"dna_extra.gif" = 'html/dna_extra.gif'
)
)
/datum/asset/simple/vv
assets = list(
@@ -189,6 +189,8 @@
if(!ishuman(user) || !user.mind || (user.mind in SSticker.mode.wizards))
to_chat(user, "<span class='warning'>You feel the magic of the dice is restricted to ordinary humans! You should leave it alone.</span>")
user.dropItemToGround(src)
return
return ..()
/obj/item/dice/d20/fate/proc/effect(var/mob/living/carbon/human/user,roll)
+10
View File
@@ -19,6 +19,8 @@
///Next tick to reset the total message counter
var/total_count_reset = 0
var/ircreplyamount = 0
/// last time they tried to do an autobunker auth
var/autobunker_last_try = 0
/////////
//OTHER//
@@ -134,5 +136,13 @@
var/parallax_layers_max = 3
var/parallax_animate_timer
// List of all asset filenames sent to this client by the asset cache, along with their assoicated md5s
var/list/sent_assets = list()
/// List of all completed blocking send jobs awaiting acknowledgement by send_asset
var/list/completed_asset_jobs = list()
/// Last asset send job id.
var/last_asset_job = 0
var/last_completed_asset_job = 0
//world.time of when the crew manifest can be accessed
var/crew_manifest_delay
+14 -11
View File
@@ -2322,14 +2322,16 @@ GLOBAL_LIST_EMPTY(preferences_datums)
var/min = CONFIG_GET(number/body_size_min)
var/max = CONFIG_GET(number/body_size_max)
var/danger = CONFIG_GET(number/threshold_body_size_slowdown)
var/new_body_size = input(user, "Choose your desired sprite size:\n([min*100]%-[max*100]%), Warning: May make your character look distorted[danger > min ? ", and an exponential slowdown will occur for those smaller than [danger*100]%!" : "!"]", "Character Preference", features["body_size"]*100) as num|null
var/new_body_size = input(user, "Choose your desired sprite size: ([min*100]%-[max*100]%)\nWarning: This may make your character look distorted[danger > min ? "! Additionally, a proportional movement speed penalty will be applied to characters smaller than [danger*100]%." : "!"]", "Character Preference", features["body_size"]*100) as num|null
if (new_body_size)
new_body_size = clamp(new_body_size * 0.01, min, max)
var/dorfy
if(danger > new_body_size)
dorfy = alert(user, "The chosen size appears to be smaller than the threshold of [danger*100]%, which will lead to an added exponential slowdown. Are you sure about that?", "Dwarfism Alert", "Yes", "Move it to the threshold", "No")
if(!dorfy || dorfy == "Move it above the threshold")
if((new_body_size + 0.01) < danger) // Adding 0.01 as a dumb fix to prevent the warning message from appearing when exactly at threshold... Not sure why that happens in the first place.
dorfy = alert(user, "You have chosen a size below the slowdown threshold of [danger*100]%. For balancing purposes, the further you go below this percentage, the slower your character will be. Do you wish to keep this size?", "Speed Penalty Alert", "Yes", "Move it to the threshold", "No")
if(dorfy == "Move it to the threshold")
new_body_size = danger
if(!dorfy) //Aborts if this var is somehow empty
return
if(dorfy != "No")
features["body_size"] = new_body_size
if("tongue")
@@ -2737,13 +2739,14 @@ GLOBAL_LIST_EMPTY(preferences_datums)
character.dna.update_body_size(old_size)
//speech stuff
var/new_tongue = GLOB.roundstart_tongues[custom_tongue]
if(new_tongue)
var/obj/item/organ/tongue/T = character.getorganslot(ORGAN_SLOT_TONGUE)
if(T)
qdel(T)
var/obj/item/organ/tongue/new_custom_tongue = new new_tongue
new_custom_tongue.Insert(character)
if(custom_tongue != "default")
var/new_tongue = GLOB.roundstart_tongues[custom_tongue]
if(new_tongue)
var/obj/item/organ/tongue/T = character.getorganslot(ORGAN_SLOT_TONGUE)
if(T)
qdel(T)
var/obj/item/organ/tongue/new_custom_tongue = new new_tongue
new_custom_tongue.Insert(character)
if(custom_speech_verb != "default")
character.dna.species.say_mod = custom_speech_verb
@@ -695,6 +695,8 @@ SAVEFILE UPDATING/VERSIONING - 'Simplified', or rather, more coder-friendly ~Car
features["balls_visibility"] = sanitize_inlist(features["balls_visibility"], safe_visibilities, GEN_VISIBLE_NO_UNDIES)
features["vag_visibility"] = sanitize_inlist(features["vag_visibility"], safe_visibilities, GEN_VISIBLE_NO_UNDIES)
custom_speech_verb = sanitize_inlist(custom_speech_verb, GLOB.speech_verbs, "default")
custom_tongue = sanitize_inlist(custom_tongue, GLOB.roundstart_tongues, "default")
features["flavor_text"] = copytext(features["flavor_text"], 1, MAX_FLAVOR_LEN)
features["silicon_flavor_text"] = copytext(features["silicon_flavor_text"], 1, MAX_FLAVOR_LEN)
+37
View File
@@ -0,0 +1,37 @@
/client/verb/bunker_auto_authorize()
set name = "Auto Authorize Panic Bunker"
set desc = "Authorizes your account in the panic bunker of any servers connected to this function."
set category = "OOC"
if(autobunker_last_try + 5 SECONDS > world.time)
to_chat(src, "<span class='danger'>Function on cooldown, try again in 5 seconds.</span>")
return
autobunker_last_try = world.time
world.send_cross_server_bunker_overrides(key, src)
/world/proc/send_cross_server_bunker_overrides(key, client/C)
var/comms_key = CONFIG_GET(string/comms_key)
if(!comms_key)
return
var/list/message = list()
message["ckey"] = key
message["source"] = "[CONFIG_GET(string/cross_comms_name)]"
message["key"] = comms_key
message["auto_bunker_override"] = TRUE
var/list/servers = CONFIG_GET(keyed_list/cross_server_bunker_override)
if(!length(servers))
to_chat(C, "<span class='boldwarning'>AUTOBUNKER: No servers are configured to receive from this one.</span>")
return
log_admin("[key] ([key_name(C)]) has initiated an autobunker authentication with linked servers.")
for(var/name in servers)
var/returned = world.Export("[servers[name]]?[list2params(message)]")
switch(returned)
if("Bad Key")
to_chat(C, "<span class='boldwarning'>AUTOBuNKER: [name] failed to authenticate with this server.</span>")
if("Function Disabled")
to_chat(C, "<span class='boldwarning'>AUTOBUNKER: [name] has autobunker receive disabled.</span>")
if("Success")
to_chat(C, "<span class='boldwarning'>AUTOBUNKER: Successfully authenticated with [name]. Panic bunker bypass granted to [key].</span>.")
else
to_chat(C, "<span class='boldwarning'>AUTOBUNKER: Unknown error ([name]).</span>")
+3 -2
View File
@@ -23,14 +23,15 @@
if(iscarbon(target) && proximity)
var/mob/living/carbon/C = target
var/mob/living/carbon/U = user
var/success = C.equip_to_slot_if_possible(new /obj/item/clothing/gloves/color/yellow/sprayon, ITEM_SLOT_GLOVES, TRUE, TRUE)
var/success = C.equip_to_slot_if_possible(new /obj/item/clothing/gloves/color/yellow/sprayon, ITEM_SLOT_GLOVES, TRUE, TRUE, clothing_check = TRUE)
if(success)
if(C == user)
C.visible_message("<span class='notice'>[U] sprays their hands with glittery rubber!</span>")
else
C.visible_message("<span class='warning'>[U] sprays glittery rubber on the hands of [C]!</span>")
else
C.visible_message("<span class='warning'>The rubber fails to stick to [C]'s hands!</span>")
user.visible_message("<span class='warning'>The rubber fails to stick to [C]'s hands!</span>",
"<span class='warning'>The rubber fails to stick to [C]'s [(SLOT_GLOVES in C.check_obscured_slots()) ? "unexposed" : ""] hands!</span>")
qdel(src)
+14 -7
View File
@@ -76,6 +76,7 @@
/obj/item/clothing/head/hooded
var/obj/item/clothing/suit/hooded/suit
dynamic_hair_suffix = ""
/obj/item/clothing/head/hooded/Destroy()
suit = null
@@ -164,7 +165,7 @@
RemoveHelmet()
..()
/obj/item/clothing/suit/space/hardsuit/proc/RemoveHelmet()
/obj/item/clothing/suit/space/hardsuit/proc/RemoveHelmet(message = TRUE)
if(!helmet)
return
suittoggled = FALSE
@@ -174,16 +175,18 @@
helmet.attack_self(H)
H.transferItemToLoc(helmet, src, TRUE)
H.update_inv_wear_suit()
to_chat(H, "<span class='notice'>The helmet on the hardsuit disengages.</span>")
if(message)
to_chat(H, "<span class='notice'>The helmet on the hardsuit disengages.</span>")
playsound(src.loc, 'sound/mecha/mechmove03.ogg', 50, 1)
else
helmet.forceMove(src)
return TRUE
/obj/item/clothing/suit/space/hardsuit/dropped(mob/user)
..()
RemoveHelmet()
/obj/item/clothing/suit/space/hardsuit/proc/ToggleHelmet()
/obj/item/clothing/suit/space/hardsuit/proc/ToggleHelmet(message = TRUE)
var/mob/living/carbon/human/H = loc
if(!helmettype)
return
@@ -192,15 +195,19 @@
if(!suittoggled)
if(ishuman(src.loc))
if(H.wear_suit != src)
to_chat(H, "<span class='warning'>You must be wearing [src] to engage the helmet!</span>")
if(message)
to_chat(H, "<span class='warning'>You must be wearing [src] to engage the helmet!</span>")
return
if(H.head)
to_chat(H, "<span class='warning'>You're already wearing something on your head!</span>")
if(message)
to_chat(H, "<span class='warning'>You're already wearing something on your head!</span>")
return
else if(H.equip_to_slot_if_possible(helmet,SLOT_HEAD,0,0,1))
to_chat(H, "<span class='notice'>You engage the helmet on the hardsuit.</span>")
if(message)
to_chat(H, "<span class='notice'>You engage the helmet on the hardsuit.</span>")
suittoggled = TRUE
H.update_inv_wear_suit()
playsound(src.loc, 'sound/mecha/mechmove03.ogg', 50, 1)
return TRUE
else
RemoveHelmet()
return RemoveHelmet(message)
+1 -1
View File
@@ -46,4 +46,4 @@
icon_state = "lewdcap"
item_state = "lewdcap"
can_adjust = FALSE
mutantrace_variation = USE_TAUR_CLIP_MASK
mutantrace_variation = STYLE_DIGITIGRADE|USE_TAUR_CLIP_MASK
+1 -1
View File
@@ -22,7 +22,7 @@
icon_state = "cmoturtle"
item_state = "w_suit"
alt_covers_chest = TRUE
mutantrace_variation = USE_TAUR_CLIP_MASK
mutantrace_variation = STYLE_DIGITIGRADE|USE_TAUR_CLIP_MASK
/obj/item/clothing/under/rank/medical/geneticist
desc = "It's made of a special fiber that gives special protection against biohazards. It has a genetics rank stripe on it."
@@ -83,6 +83,7 @@
/obj/item/reagent_containers/food/snacks/meat/slab/chicken
name = "chicken meat"
desc = "A slab of raw chicken. Remember to wash your hands!"
icon_state = "chickenbreast"
cooked_type = /obj/item/reagent_containers/food/snacks/meat/steak/chicken
slice_path = /obj/item/reagent_containers/food/snacks/meat/rawcutlet/chicken
tastes = list("chicken" = 1)
@@ -341,8 +342,14 @@
/obj/item/reagent_containers/food/snacks/meat/steak/chicken
name = "chicken steak" //Can you have chicken steaks? Maybe this should be renamed once it gets new sprites.
icon_state = "chickenbreast_cooked"
tastes = list("chicken" = 1)
/obj/item/reagent_containers/food/snacks/meat/steak/fish
name = "fish fillet"
icon_state = "grilled_carp_slice"
tastes = list("charred sushi" = 1)
/obj/item/reagent_containers/food/snacks/meat/steak/plain
foodtype = MEAT
@@ -361,6 +368,7 @@
/obj/item/reagent_containers/food/snacks/meat/steak/bear
name = "bear steak"
icon_state = "bearcook"
tastes = list("meat" = 1, "salmon" = 1)
/obj/item/reagent_containers/food/snacks/meat/steak/xeno
@@ -22,6 +22,7 @@
list_reagents = list(/datum/reagent/consumable/nutriment = 3, /datum/reagent/toxin/carpotoxin = 2, /datum/reagent/consumable/nutriment/vitamin = 2)
bitesize = 6
filling_color = "#FA8072"
cooked_type = /obj/item/reagent_containers/food/snacks/meat/steak/fish
tastes = list("fish" = 1)
foodtype = MEAT
@@ -136,6 +136,17 @@
tastes = list("fries" = 3, "cheese" = 1)
foodtype = VEGETABLES | GRAIN
/obj/item/reagent_containers/food/snacks/chilicheesefries
name = "chili cheese fries"
desc = "Fries smothered in cheese -and- chilli."
icon_state = "chilicheesefries"
trash = /obj/item/trash/plate
bonus_reagents = list(/datum/reagent/consumable/nutriment = 1, /datum/reagent/consumable/nutriment/vitamin = 2)
list_reagents = list(/datum/reagent/consumable/nutriment = 7, /datum/reagent/consumable/nutriment/vitamin = 1)
filling_color = "#FFD700"
tastes = list("fries" = 3, "cheese" = 1)
foodtype = VEGETABLES | GRAIN
/obj/item/reagent_containers/food/snacks/badrecipe
name = "burned mess"
desc = "Someone should be demoted from cook for this."
@@ -537,6 +548,15 @@
tastes = list("butter" = 1)
foodtype = DAIRY
/obj/item/reagent_containers/food/snacks/butter/margarine
name = "stick of margarine"
desc = "A stick of lightly salted vegetable oil."
icon_state = "marge"
list_reagents = list(/datum/reagent/consumable/nutriment = 4, /datum/reagent/consumable/cornoil = 2, /datum/reagent/consumable/sodiumchloride = 1)
filling_color = "#FFD700"
tastes = list("butter" = 1)
foodtype = JUNKFOOD
/obj/item/reagent_containers/food/snacks/onionrings
name = "onion rings"
desc = "Onion slices coated in batter."
@@ -21,6 +21,17 @@
tastes = list("toast" = 1)
foodtype = GRAIN
/obj/item/reagent_containers/food/snacks/baconlettucetomato
name = "blt sandwich"
desc = "The classic bacon, lettuce tomato sandwich."
icon = 'icons/obj/food/burgerbread.dmi'
icon_state = "blt"
trash = /obj/item/trash/plate
bonus_reagents = list(/datum/reagent/consumable/nutriment = 1, /datum/reagent/consumable/nutriment/vitamin = 1)
list_reagents = list(/datum/reagent/consumable/nutriment = 8, /datum/reagent/consumable/nutriment/vitamin = 2)
tastes = list("bacon" = 1, "lettuce" = 1, "tomato" = 1, "mayo" = 1)
foodtype = GRAIN | MEAT | VEGETABLES
/obj/item/reagent_containers/food/snacks/grilledcheese
name = "grilled cheese sandwich"
desc = "Goes great with Tomato soup!"
@@ -136,8 +147,9 @@
/obj/item/reagent_containers/food/snacks/tuna_sandwich
name = "tuna sandwich"
desc = "Both a salad and a sandwich in one."
icon = 'icons/obj/food/burgerbread.dmi'
icon_state = "tunasandwich"
trash = /obj/item/trash/plate
list_reagents = list(/datum/reagent/consumable/nutriment = 12, /datum/reagent/consumable/nutriment/vitamin = 4)
bonus_reagents = list(/datum/reagent/consumable/nutriment = 1, /datum/reagent/consumable/nutriment/vitamin = 3)
tastes = list("tuna" = 4, "mayonnaise" = 2, "bread" = 2)
foodtype = GRAIN | MEAT
@@ -179,3 +179,14 @@
id = /datum/reagent/consumable/bbqsauce
results = list(/datum/reagent/consumable/bbqsauce = 5)
required_reagents = list(/datum/reagent/ash = 1, /datum/reagent/consumable/tomatojuice = 1, /datum/reagent/medicine/salglu_solution = 3, /datum/reagent/consumable/blackpepper = 1)
/datum/chemical_reaction/margarine
name = "Margarine"
id = "margarine"
required_reagents = list(/datum/reagent/consumable/cornoil = 5, /datum/reagent/consumable/soymilk = 5, /datum/reagent/consumable/sodiumchloride = 1)
mix_message = "The ingredients solidify into a stick of margarine."
/datum/chemical_reaction/margarine/on_reaction(datum/reagents/holder, multiplier)
var/location = get_turf(holder.my_atom)
for(var/i = 1, i <= multiplier, i++)
new /obj/item/reagent_containers/food/snacks/butter/margarine(location)
@@ -22,6 +22,15 @@
result = /obj/item/reagent_containers/food/snacks/baconegg
subcategory = CAT_EGG
/datum/crafting_recipe/food/wrap
name = "Egg Wrap"
reqs = list(/datum/reagent/consumable/soysauce = 10,
/obj/item/reagent_containers/food/snacks/friedegg = 1,
/obj/item/reagent_containers/food/snacks/grown/cabbage = 1,
)
result = /obj/item/reagent_containers/food/snacks/eggwrap
subcategory = CAT_EGG
/datum/crafting_recipe/food/omelette
name = "Omelette"
reqs = list(
@@ -14,15 +14,6 @@
result = /obj/item/reagent_containers/food/snacks/chawanmushi
subcategory = CAT_MISCFOOD
/datum/crafting_recipe/food/wrap
name = "Egg Wrap"
reqs = list(/datum/reagent/consumable/soysauce = 10,
/obj/item/reagent_containers/food/snacks/friedegg = 1,
/obj/item/reagent_containers/food/snacks/grown/cabbage = 1,
)
result = /obj/item/reagent_containers/food/snacks/eggwrap
subcategory = CAT_MISCFOOD
/datum/crafting_recipe/food/khachapuri
name = "Khachapuri"
reqs = list(
@@ -93,6 +84,16 @@
result = /obj/item/reagent_containers/food/snacks/cheesyfries
subcategory = CAT_MISCFOOD
/datum/crafting_recipe/food/chilicheesefries
name = "Chilli cheese fries"
reqs = list(
/obj/item/reagent_containers/food/snacks/fries = 1,
/obj/item/reagent_containers/food/snacks/cheesewedge = 1,
/obj/item/reagent_containers/food/snacks/grown/chili = 1
)
result = /obj/item/reagent_containers/food/snacks/chilicheesefries
subcategory = CAT_MISCFOOD
/datum/crafting_recipe/food/eggplantparm
name ="Eggplant parmigiana"
reqs = list(
@@ -25,6 +25,17 @@
result = /obj/item/reagent_containers/food/snacks/grilledcheese
subcategory = CAT_SANDWICH
/datum/crafting_recipe/food/baconlettucetomato
name = "BLT sandwich"
reqs = list(
/obj/item/reagent_containers/food/snacks/meat/bacon = 2,
/obj/item/reagent_containers/food/snacks/grown/cabbage = 1,
/obj/item/reagent_containers/food/snacks/grown/tomato = 1,
/datum/reagent/consumable/mayonnaise = 5
)
result = /obj/item/reagent_containers/food/snacks/baconlettucetomato
subcategory = CAT_SANDWICH
/datum/crafting_recipe/food/slimesandwich
name = "Jelly sandwich"
reqs = list(
@@ -99,7 +110,7 @@
/obj/item/reagent_containers/food/snacks/breadslice/plain = 2,
/obj/item/reagent_containers/food/snacks/tuna = 1,
/obj/item/reagent_containers/food/snacks/grown/onion = 1,
/obj/item/reagent_containers/food/condiment/mayonnaise = 5
/datum/reagent/consumable/mayonnaise = 5
)
result = /obj/item/reagent_containers/food/snacks/tuna_sandwich
subcategory = CAT_SANDWICH
+8 -8
View File
@@ -277,7 +277,7 @@
growing_icon = 'icons/obj/hydroponics/growing_flowers.dmi'
icon_grow = "bee_balm-grow"
icon_dead = "bee_balm-dead"
mutatelist = list(/obj/item/seeds/poppy/geranium, /obj/item/seeds/bee_balm/honey) //Lower odds of becoming honey
mutatelist = list(/obj/item/seeds/poppy/geranium, /obj/item/seeds/bee_balm/honey_balm) //Lower odds of becoming honey
reagents_add = list(/datum/reagent/medicine/spaceacillin = 0.1, /datum/reagent/space_cleaner/sterilizine = 0.05)
/obj/item/reagent_containers/food/snacks/grown/bee_balm
@@ -291,11 +291,11 @@
foodtype = GROSS
// Beebalm
/obj/item/seeds/bee_balm/honey
/obj/item/seeds/bee_balm/honey_balm
name = "pack of Honey Balm seeds"
desc = "These seeds grow into Honey Balms."
icon_state = "seed-bee_balmalt"
species = "seed-bee_balm_alt"
icon_state = "seed-honey_balm"
species = "honey_balm"
plantname = "Honey Balm Pods"
product = /obj/item/reagent_containers/food/snacks/grown/bee_balm/honey
endurance = 1
@@ -304,16 +304,16 @@
potency = 1
growthstages = 3
growing_icon = 'icons/obj/hydroponics/growing_flowers.dmi'
icon_grow = "bee_balmalt-grow"
icon_dead = "bee_balmalt-dead"
icon_grow = "honey_balm-grow"
icon_dead = "honey_balm-dead"
reagents_add = list(/datum/reagent/consumable/honey = 0.1, /datum/reagent/lye = 0.3) //To make wax
rarity = 30
/obj/item/reagent_containers/food/snacks/grown/bee_balm/honey
seed = /obj/item/seeds/bee_balm/honey
seed = /obj/item/seeds/bee_balm/honey_balm
name = "honey balm"
desc = "A large honey filled pod of a flower."
icon_state = "bee_balmalt"
icon_state = "honey_balm"
filling_color = "#FF6347"
bitesize_mod = 8
tastes = list("wax" = 1)
+1
View File
@@ -61,6 +61,7 @@
filling_color = "#ee7bee"
bitesize_mod = 2
foodtype = VEGETABLES
juice_results = list (/datum/reagent/consumable/laughsyrup = 0)
tastes = list ("a prancing rabbit" = 1) //Vib Ribbon sends her regards.. wherever she is.
wine_power = 90
wine_flavor = "a vector-graphic rabbit dancing on your tongue"
+1 -1
View File
@@ -392,7 +392,7 @@
/datum/plant_gene/trait/battery/on_attackby(obj/item/reagent_containers/food/snacks/grown/G, obj/item/I, mob/user)
if(istype(I, /obj/item/stack/cable_coil))
if(I.use_tool(src, user, 0, 5, max_level = JOB_SKILL_EXPERT))
if(I.use_tool(src, user, 0, 5, skill_gain_mult = TRIVIAL_USE_TOOL_MULT))
to_chat(user, "<span class='notice'>You add some cable to [G] and slide it inside the battery encasing.</span>")
var/obj/item/stock_parts/cell/potato/pocell = new /obj/item/stock_parts/cell/potato(user.loc)
pocell.icon_state = G.icon_state
+1 -1
View File
@@ -16,7 +16,7 @@
access = list(ACCESS_MAINT_TUNNELS, ACCESS_MAILSORTING, ACCESS_CARGO, ACCESS_CARGO_BOT, ACCESS_MINING,
ACCESS_MINING_STATION, ACCESS_MINERAL_STOREROOM)
minimal_access = list(ACCESS_MINING, ACCESS_MINING_STATION, ACCESS_MAILSORTING, ACCESS_MINERAL_STOREROOM)
paycheck = PAYCHECK_HARD
paycheck = PAYCHECK_EASY ///Not necessarily easy itself, but it can be trivial to make lot of cash on this job.
paycheck_department = ACCOUNT_CAR
display_order = JOB_DISPLAY_ORDER_SHAFT_MINER
@@ -25,6 +25,17 @@
var/mob/living/L = user.mob
L.keybind_stop_active_blocking()
/datum/keybinding/living/active_block_toggle
name = "active_block_toggle"
full_name = "Block (Toggle)"
category = CATEGORY_COMBAT
description = "Toggles active blocking system using currenet in hand object, or any found object if applicable."
/datum/keybinding/living/active_block_toggle/down(client/user)
var/mob/living/L = user.mob
L.keybind_toggle_active_blocking()
return TRUE
/datum/keybinding/living/active_parry
hotkey_keys = list("Insert", "G")
name = "active_parry"
+1 -1
View File
@@ -390,7 +390,7 @@ GLOBAL_LIST_INIT(sand_recipes, list(\
to_chat(user, "<span class='warning'>There already is a string attached to this coin!</span>")
return
if (W.use_tool(src, user, 0, 1, max_level = JOB_SKILL_BASIC))
if (W.use_tool(src, user, 0, 1, skill_gain_mult = BARE_USE_TOOL_MULT))
add_overlay("coin_string_overlay")
string_attached = 1
to_chat(user, "<span class='notice'>You attach a string to the coin.</span>")
+54 -41
View File
@@ -158,7 +158,7 @@
//Returns if a certain item can be equipped to a certain slot.
// Currently invalid for two-handed items - call obj/item/mob_can_equip() instead.
/mob/proc/can_equip(obj/item/I, slot, disable_warning = FALSE, bypass_equip_delay_self = FALSE)
/mob/proc/can_equip(obj/item/I, slot, disable_warning = FALSE, bypass_equip_delay_self = FALSE, clothing_check = FALSE, list/return_warning)
return FALSE
/mob/proc/can_put_in_hand(I, hand_index)
@@ -338,50 +338,63 @@
return FALSE
return TRUE
//This is a SAFE proc. Use this instead of equip_to_slot()!
//set qdel_on_fail to have it delete W if it fails to equip
//set disable_warning to disable the 'you are unable to equip that' warning.
//unset redraw_mob to prevent the mob from being redrawn at the end.
/mob/proc/equip_to_slot_if_possible(obj/item/W, slot, qdel_on_fail = FALSE, disable_warning = FALSE, redraw_mob = TRUE, bypass_equip_delay_self = FALSE, clothing_check = FALSE)
if(!istype(W))
return FALSE
var/list/warning = list("<span class='warning'>You are unable to equip that!</span>")
if(!W.mob_can_equip(src, null, slot, disable_warning, bypass_equip_delay_self, clothing_check, warning))
if(qdel_on_fail)
qdel(W)
else if(!disable_warning)
to_chat(src, warning[1])
return FALSE
equip_to_slot(W, slot, redraw_mob) //This proc should not ever fail.
return TRUE
//This is an UNSAFE proc. It merely handles the actual job of equipping. All the checks on whether you can or can't equip need to be done before! Use mob_can_equip() for that task.
//In most cases you will want to use equip_to_slot_if_possible()
/mob/proc/equip_to_slot(obj/item/W, slot)
return
//This is just a commonly used configuration for the equip_to_slot_if_possible() proc, used to equip people when the round starts and when events happen and such.
//Also bypasses equip delay checks, since the mob isn't actually putting it on.
/mob/proc/equip_to_slot_or_del(obj/item/W, slot)
return equip_to_slot_if_possible(W, slot, TRUE, TRUE, FALSE, TRUE)
//puts the item "W" into an appropriate slot in a human's inventory
//returns 0 if it cannot, 1 if successful
/mob/proc/equip_to_appropriate_slot(obj/item/W, clothing_check = FALSE)
if(!istype(W))
return 0
var/slot_priority = W.slot_equipment_priority
if(!slot_priority)
slot_priority = list( \
SLOT_BACK, SLOT_WEAR_ID,\
SLOT_W_UNIFORM, SLOT_WEAR_SUIT,\
SLOT_WEAR_MASK, SLOT_HEAD, SLOT_NECK,\
SLOT_SHOES, SLOT_GLOVES,\
SLOT_EARS, SLOT_GLASSES,\
SLOT_BELT, SLOT_S_STORE,\
SLOT_L_STORE, SLOT_R_STORE,\
SLOT_GENERC_DEXTROUS_STORAGE\
)
for(var/slot in slot_priority)
if(equip_to_slot_if_possible(W, slot, FALSE, TRUE, TRUE, FALSE, clothing_check)) //qdel_on_fail = 0; disable_warning = 1; redraw_mob = 1
return 1
return 0
//Outdated but still in use apparently. This should at least be a human proc.
//Daily reminder to murder this - Remie.
/mob/living/proc/get_equipped_items(include_pockets = FALSE)
return
/mob/living/carbon/get_equipped_items(include_pockets = FALSE)
var/list/items = list()
if(back)
items += back
if(head)
items += head
if(wear_mask)
items += wear_mask
if(wear_neck)
items += wear_neck
return items
/mob/living/carbon/human/get_equipped_items(include_pockets = FALSE)
var/list/items = ..()
if(belt)
items += belt
if(ears)
items += ears
if(glasses)
items += glasses
if(gloves)
items += gloves
if(shoes)
items += shoes
if(wear_id)
items += wear_id
if(wear_suit)
items += wear_suit
if(w_uniform)
items += w_uniform
if(include_pockets)
if(l_store)
items += l_store
if(r_store)
items += r_store
if(s_store)
items += s_store
return items
/mob/living/proc/unequip_everything()
var/list/items = list()
items |= get_equipped_items(TRUE)
@@ -394,7 +407,7 @@
to_chat(M, "<span class='warning'>You are not holding anything to equip!</span>")
return FALSE
if(M.equip_to_appropriate_slot(src))
if(M.equip_to_appropriate_slot(src, TRUE))
M.update_inv_hands()
return TRUE
else
@@ -1,5 +0,0 @@
/mob/living/carbon/alien/humanoid/doUnEquip(obj/item/I)
. = ..()
if(!. || !I)
return
@@ -88,6 +88,7 @@
Die()
/obj/item/clothing/mask/facehugger/equipped(mob/M)
. = ..()
Attach(M)
/obj/item/clothing/mask/facehugger/Crossed(atom/target)
@@ -254,7 +255,7 @@
return FALSE
if(AmBloodsucker(M))
return FALSE
if(ismonkey(M))
return 1
+14 -1
View File
@@ -179,7 +179,7 @@
to_chat(src, "<span class='notice'>You gently let go of [throwable_mob].</span>")
return
adjustStaminaLossBuffered(25)//CIT CHANGE - throwing an entire person shall be very tiring
adjustStaminaLossBuffered(STAM_COST_THROW_MOB * ((throwable_mob.mob_size+1)**2))// throwing an entire person shall be very tiring
var/turf/start_T = get_turf(loc) //Get the start and target tile for the descriptors
var/turf/end_T = get_turf(target)
if(start_T && end_T)
@@ -1157,3 +1157,16 @@
dna.features["body_model"] = MALE
if(update_icon)
update_body()
/mob/living/carbon/check_obscured_slots()
if(head)
if(head.flags_inv & HIDEMASK)
LAZYOR(., SLOT_WEAR_MASK)
if(head.flags_inv & HIDEEYES)
LAZYOR(., SLOT_GLASSES)
if(head.flags_inv & HIDEEARS)
LAZYOR(., SLOT_EARS)
if(wear_mask)
if(wear_mask.flags_inv & HIDEEYES)
LAZYOR(., SLOT_GLASSES)
+27 -26
View File
@@ -152,8 +152,12 @@
dat += "<tr><td>&nbsp;</td></tr>"
dat += "<tr><td><B>Exosuit:</B></td><td><A href='?src=[REF(src)];item=[SLOT_WEAR_SUIT]'>[(wear_suit && !(wear_suit.item_flags & ABSTRACT)) ? wear_suit : "<font color=grey>Empty</font>"]</A></td></tr>"
dat += "<tr><td><B>Exosuit:</B></td><td><A href='?src=[REF(src)];item=[SLOT_WEAR_SUIT]'>[(wear_suit && !(wear_suit.item_flags & ABSTRACT)) ? wear_suit : "<font color=grey>Empty</font>"]</A>"
if(wear_suit)
if(istype(wear_suit, /obj/item/clothing/suit/space/hardsuit))
var/hardsuit_head = head && istype(head, /obj/item/clothing/head/helmet/space/hardsuit)
dat += "&nbsp;<A href='?src=[REF(src)];toggle_helmet=[SLOT_WEAR_SUIT]'>[hardsuit_head ? "Retract Helmet" : "Extend Helmet"]</A>"
dat += "</td></tr>"
dat += "<tr><td>&nbsp;&#8627;<B>Suit Storage:</B></td><td><A href='?src=[REF(src)];item=[SLOT_S_STORE]'>[(s_store && !(s_store.item_flags & ABSTRACT)) ? s_store : "<font color=grey>Empty</font>"]</A>"
if(has_breathable_mask && istype(s_store, /obj/item/tank))
dat += "&nbsp;<A href='?src=[REF(src)];internal=[SLOT_S_STORE]'>[internal ? "Disable Internals" : "Set Internals"]</A>"
@@ -222,13 +226,28 @@
return
SEND_SIGNAL(src, COMSIG_CARBON_EMBED_RIP, I, L)
return
if(href_list["toggle_helmet"])
if(!istype(head, /obj/item/clothing/head/helmet/space/hardsuit))
return
var/obj/item/clothing/head/helmet/space/hardsuit/hardsuit_head = head
visible_message("<span class='danger'>[usr] tries to [hardsuit_head ? "retract" : "extend"] [src]'s helmet.</span>", \
"<span class='userdanger'>[usr] tries to [hardsuit_head ? "retract" : "extend"] [src]'s helmet.</span>", \
target = usr, target_message = "<span class='danger'>You try to [hardsuit_head ? "retract" : "extend"] [src]'s helmet.</span>")
if(!do_mob(usr, src, hardsuit_head ? head.strip_delay : POCKET_STRIP_DELAY))
return
if(!istype(wear_suit, /obj/item/clothing/suit/space/hardsuit) || (hardsuit_head ? (!head || head != hardsuit_head) : head))
return
var/obj/item/clothing/suit/space/hardsuit/hardsuit = wear_suit //This should be an hardsuit given all our checks
if(hardsuit.ToggleHelmet(FALSE))
visible_message("<span class='danger'>[usr] [hardsuit_head ? "retract" : "extend"] [src]'s helmet</span>", \
"<span class='userdanger'>[usr] [hardsuit_head ? "retract" : "extend"] [src]'s helmet</span>", \
target = usr, target_message = "<span class='danger'>You [hardsuit_head ? "retract" : "extend"] [src]'s helmet.</span>")
return
if(href_list["item"])
var/slot = text2num(href_list["item"])
if(slot in check_obscured_slots())
to_chat(usr, "<span class='warning'>You can't reach that! Something is covering it.</span>")
return
if(href_list["pockets"])
var/strip_mod = 1
var/strip_silence = FALSE
@@ -511,33 +530,15 @@
// Might need re-wording.
to_chat(user, "<span class='alert'>There is no exposed flesh or thin material [above_neck(target_zone) ? "on [p_their()] head" : "on [p_their()] body"].</span>")
/mob/living/carbon/human/proc/check_obscured_slots()
var/list/obscured = list()
/mob/living/carbon/human/check_obscured_slots()
. = ..()
if(wear_suit)
if(wear_suit.flags_inv & HIDEGLOVES)
obscured |= SLOT_GLOVES
LAZYOR(., SLOT_GLOVES)
if(wear_suit.flags_inv & HIDEJUMPSUIT)
obscured |= SLOT_W_UNIFORM
LAZYOR(., SLOT_W_UNIFORM)
if(wear_suit.flags_inv & HIDESHOES)
obscured |= SLOT_SHOES
if(head)
if(head.flags_inv & HIDEMASK)
obscured |= SLOT_WEAR_MASK
if(head.flags_inv & HIDEEYES)
obscured |= SLOT_GLASSES
if(head.flags_inv & HIDEEARS)
obscured |= SLOT_EARS
if(wear_mask)
if(wear_mask.flags_inv & HIDEEYES)
obscured |= SLOT_GLASSES
if(obscured.len)
return obscured
else
return null
LAZYOR(., SLOT_SHOES)
/mob/living/carbon/human/assess_threat(judgement_criteria, lasercolor = "", datum/callback/weaponcheck=null)
if(judgement_criteria & JUDGE_EMAGGED)
@@ -85,8 +85,11 @@
FP.entered_dirs |= dir
FP.bloodiness = S.bloody_shoes[S.blood_state]
if(S.last_bloodtype)
FP.blood_DNA += list(S.last_blood_DNA = S.last_bloodtype)
FP.blood_DNA["color"] += S.last_blood_color
FP.blood_DNA[S.last_blood_DNA] = S.last_bloodtype
if(!FP.blood_DNA["color"])
FP.blood_DNA["color"] = S.last_blood_color
else
FP.blood_DNA["color"] = BlendRGB(FP.blood_DNA["color"], S.last_blood_color)
FP.update_icon()
update_inv_shoes()
//End bloody footprints
@@ -1,5 +1,32 @@
/mob/living/carbon/human/can_equip(obj/item/I, slot, disable_warning = FALSE, bypass_equip_delay_self = FALSE)
return dna.species.can_equip(I, slot, disable_warning, src, bypass_equip_delay_self)
/mob/living/carbon/human/can_equip(obj/item/I, slot, disable_warning = FALSE, bypass_equip_delay_self = FALSE, clothing_check = FALSE, list/return_warning)
return dna.species.can_equip(I, slot, disable_warning, src, bypass_equip_delay_self, clothing_check, return_warning)
/mob/living/carbon/human/get_equipped_items(include_pockets = FALSE)
var/list/items = ..()
if(belt)
items += belt
if(ears)
items += ears
if(glasses)
items += glasses
if(gloves)
items += gloves
if(shoes)
items += shoes
if(wear_id)
items += wear_id
if(wear_suit)
items += wear_suit
if(w_uniform)
items += w_uniform
if(include_pockets)
if(l_store)
items += l_store
if(r_store)
items += r_store
if(s_store)
items += s_store
return items
// Return the item currently in the slot ID
/mob/living/carbon/human/get_item_by_slot(slot_id)
+20 -15
View File
@@ -1066,11 +1066,16 @@ GLOBAL_LIST_EMPTY(roundstart_race_names)
// handles the equipping of species-specific gear
return
/datum/species/proc/can_equip(obj/item/I, slot, disable_warning, mob/living/carbon/human/H, bypass_equip_delay_self = FALSE)
/datum/species/proc/can_equip(obj/item/I, slot, disable_warning, mob/living/carbon/human/H, bypass_equip_delay_self = FALSE, clothing_check = FALSE, list/return_warning)
if(slot in no_equip)
if(!I.species_exception || !is_type_in_list(src, I.species_exception))
return FALSE
if(clothing_check && (slot in H.check_obscured_slots()))
if(return_warning)
return_warning[1] = "<span class='warning'>You are unable to equip that with your current garments in the way!</span>"
return FALSE
var/num_arms = H.get_num_arms(FALSE)
var/num_legs = H.get_num_legs(FALSE)
@@ -1132,8 +1137,8 @@ GLOBAL_LIST_EMPTY(roundstart_race_names)
if(!CHECK_BITFIELD(I.item_flags, NO_UNIFORM_REQUIRED))
var/obj/item/bodypart/O = H.get_bodypart(BODY_ZONE_CHEST)
if(!H.w_uniform && !nojumpsuit && (!O || O.status != BODYPART_ROBOTIC))
if(!disable_warning)
to_chat(H, "<span class='warning'>You need a jumpsuit before you can attach this [I.name]!</span>")
if(return_warning)
return_warning[1] = "<span class='warning'>You need a jumpsuit before you can attach this [I.name]!</span>"
return FALSE
if(!(I.slot_flags & ITEM_SLOT_BELT))
return
@@ -1174,8 +1179,8 @@ GLOBAL_LIST_EMPTY(roundstart_race_names)
if(!CHECK_BITFIELD(I.item_flags, NO_UNIFORM_REQUIRED))
var/obj/item/bodypart/O = H.get_bodypart(BODY_ZONE_CHEST)
if(!H.w_uniform && !nojumpsuit && (!O || O.status != BODYPART_ROBOTIC))
if(!disable_warning)
to_chat(H, "<span class='warning'>You need a jumpsuit before you can attach this [I.name]!</span>")
if(return_warning)
return_warning[1] = "<span class='warning'>You need a jumpsuit before you can attach this [I.name]!</span>"
return FALSE
if( !(I.slot_flags & ITEM_SLOT_ID) )
return FALSE
@@ -1189,8 +1194,8 @@ GLOBAL_LIST_EMPTY(roundstart_race_names)
var/obj/item/bodypart/O = H.get_bodypart(BODY_ZONE_L_LEG)
if(!H.w_uniform && !nojumpsuit && (!O || O.status != BODYPART_ROBOTIC))
if(!disable_warning)
to_chat(H, "<span class='warning'>You need a jumpsuit before you can attach this [I.name]!</span>")
if(return_warning)
return_warning[1] = "<span class='warning'>You need a jumpsuit before you can attach this [I.name]!</span>"
return FALSE
if(I.slot_flags & ITEM_SLOT_DENYPOCKET)
return FALSE
@@ -1205,8 +1210,8 @@ GLOBAL_LIST_EMPTY(roundstart_race_names)
var/obj/item/bodypart/O = H.get_bodypart(BODY_ZONE_R_LEG)
if(!H.w_uniform && !nojumpsuit && (!O || O.status != BODYPART_ROBOTIC))
if(!disable_warning)
to_chat(H, "<span class='warning'>You need a jumpsuit before you can attach this [I.name]!</span>")
if(return_warning)
return_warning[1] = "<span class='warning'>You need a jumpsuit before you can attach this [I.name]!</span>"
return FALSE
if(I.slot_flags & ITEM_SLOT_DENYPOCKET)
return FALSE
@@ -1219,16 +1224,16 @@ GLOBAL_LIST_EMPTY(roundstart_race_names)
if(H.s_store)
return FALSE
if(!H.wear_suit)
if(!disable_warning)
to_chat(H, "<span class='warning'>You need a suit before you can attach this [I.name]!</span>")
if(return_warning)
return_warning[1] = "<span class='warning'>You need a suit before you can attach this [I.name]!</span>"
return FALSE
if(!H.wear_suit.allowed)
if(!disable_warning)
to_chat(H, "You somehow have a suit with no defined allowed items for suit storage, stop that.")
if(return_warning)
return_warning[1] = "You somehow have a suit with no defined allowed items for suit storage, stop that."
return FALSE
if(I.w_class > WEIGHT_CLASS_BULKY)
if(!disable_warning)
to_chat(H, "The [I.name] is too big to attach.") //should be src?
if(return_warning)
return_warning[1] = "The [I.name] is too big to attach."
return FALSE
if( istype(I, /obj/item/pda) || istype(I, /obj/item/pen) || is_type_in_list(I, H.wear_suit.allowed) )
return TRUE
@@ -117,6 +117,18 @@
if(!QDELETED(src))
update_inv_legcuffed()
/mob/living/carbon/get_equipped_items(include_pockets = FALSE)
var/list/items = list()
if(back)
items += back
if(head)
items += head
if(wear_mask)
items += wear_mask
if(wear_neck)
items += wear_neck
return items
//handle stuff to update when a mob equips/unequips a mask.
/mob/living/proc/wear_mask_update(obj/item/clothing/C, toggle_off = 1)
update_inv_wear_mask()
+1 -1
View File
@@ -517,7 +517,7 @@ GLOBAL_LIST_INIT(ballmer_windows_me_msg, list("Yo man, what if, we like, uh, put
/mob/living/carbon/handle_status_effects()
..()
if(getStaminaLoss() && !SEND_SIGNAL(src, COMSIG_COMBAT_MODE_CHECK, COMBAT_MODE_ACTIVE)) //CIT CHANGE - prevents stamina regen while combat mode is active
adjustStaminaLoss(!CHECK_MOBILITY(src, MOBILITY_STAND) ? ((combat_flags & COMBAT_FLAG_HARD_STAMCRIT) ? -7.5 : -6) : -3)//CIT CHANGE - decreases adjuststaminaloss to stop stamina damage from being such a joke
adjustStaminaLoss(!CHECK_MOBILITY(src, MOBILITY_STAND) ? ((combat_flags & COMBAT_FLAG_HARD_STAMCRIT) ? STAM_RECOVERY_STAM_CRIT : STAM_RECOVERY_RESTING) : STAM_RECOVERY_NORMAL)
if(!(combat_flags & COMBAT_FLAG_HARD_STAMCRIT) && incomingstammult != 1)
incomingstammult = max(0.01, incomingstammult)
@@ -81,7 +81,7 @@
/mob/living/carbon/monkey/proc/pickup_and_wear(obj/item/I)
if(QDELETED(I) || I.loc != src)
return
equip_to_appropriate_slot(I)
equip_to_appropriate_slot(I, TRUE)
/mob/living/carbon/monkey/resist_restraints()
var/obj/item/I = null
@@ -1,4 +1,9 @@
/mob/living/carbon/monkey/can_equip(obj/item/I, slot, disable_warning = FALSE, bypass_equip_delay_self = FALSE)
/mob/living/carbon/monkey/can_equip(obj/item/I, slot, disable_warning = FALSE, bypass_equip_delay_self = FALSE, clothing_check = FALSE, list/return_warning)
if(clothing_check && (slot in check_obscured_slots()))
if(return_warning)
return_warning[1] = "<span class='warning'>You are unable to equip that with your current garments in the way!</span>"
return FALSE
switch(slot)
if(SLOT_HANDS)
if(get_empty_held_indexes())
+13 -6
View File
@@ -14,14 +14,14 @@
changeNext_move(data.block_end_click_cd_add)
return TRUE
/mob/living/proc/start_active_blocking(obj/item/I)
/mob/living/proc/ACTIVE_BLOCK_START(obj/item/I)
if(combat_flags & (COMBAT_FLAG_ACTIVE_BLOCK_STARTING | COMBAT_FLAG_ACTIVE_BLOCKING))
return FALSE
if(!(I in held_items))
return FALSE
var/datum/block_parry_data/data = I.get_block_parry_data()
if(!istype(data)) //Typecheck because if an admin/coder screws up varediting or something we do not want someone being broken forever, the CRASH logs feedback so we know what happened.
CRASH("start_active_blocking called with an item with no valid data: [I] --> [I.block_parry_data]!")
CRASH("ACTIVE_BLOCK_START called with an item with no valid data: [I] --> [I.block_parry_data]!")
combat_flags |= COMBAT_FLAG_ACTIVE_BLOCKING
active_block_item = I
if(data.block_lock_attacking)
@@ -83,9 +83,15 @@
return FALSE
// QOL: Instead of trying to just block with held item, grab first available item.
var/obj/item/I = find_active_block_item()
if(!I)
to_chat(src, "<span class='warning'>You can't block with your bare hands!</span>")
var/list/other_items = list()
if(SEND_SIGNAL(src, COMSIG_LIVING_ACTIVE_BLOCK_START, I, other_items) & COMPONENT_PREVENT_BLOCK_START)
to_chat(src, "<span class='warning'>Something is preventing you from blocking!</span>")
return
if(!I)
if(!length(other_items))
to_chat(src, "<span class='warning'>You can't block with your bare hands!</span>")
return
I = other_items[1]
if(!I.can_active_block())
to_chat(src, "<span class='warning'>[I] is either not capable of being used to actively block, or is not currently in a state that can! (Try wielding it if it's twohanded, for example.)</span>")
return
@@ -104,7 +110,7 @@
animate(src, pixel_x = get_standard_pixel_x_offset(), pixel_y = get_standard_pixel_y_offset(), time = 2.5, FALSE, SINE_EASING | EASE_IN, ANIMATION_END_NOW)
return
combat_flags &= ~(COMBAT_FLAG_ACTIVE_BLOCK_STARTING)
start_active_blocking(I)
ACTIVE_BLOCK_START(I)
/**
* Gets the first item we can that can block, but if that fails, default to active held item.COMSIG_ENABLE_COMBAT_MODE
@@ -115,7 +121,8 @@
for(var/obj/item/I in held_items - held)
if(I.can_active_block())
return I
return held
else
return held
/**
* Proc called by keybindings to stop active blocking.
+19 -5
View File
@@ -24,25 +24,39 @@
// yanderedev else if time
var/obj/item/using_item = get_active_held_item()
var/datum/block_parry_data/data
var/datum/tool
var/method
if(using_item?.can_active_parry())
data = using_item.block_parry_data
method = ITEM_PARRY
tool = using_item
else if(mind?.martial_art?.can_martial_parry)
data = mind.martial_art.block_parry_data
method = MARTIAL_PARRY
tool = mind.martial_art
else if(combat_flags & COMBAT_FLAG_UNARMED_PARRY)
data = block_parry_data
method = UNARMED_PARRY
tool = src
else
// QOL: If none of the above work, try to find another item.
var/obj/item/backup = find_backup_parry_item()
if(!backup)
to_chat(src, "<span class='warning'>You have nothing to parry with!</span>")
return FALSE
data = backup.block_parry_data
using_item = backup
if(backup)
tool = backup
data = backup.block_parry_data
using_item = backup
method = ITEM_PARRY
var/list/other_items = list()
if(SEND_SIGNAL(src, COMSIG_LIVING_ACTIVE_PARRY_START, method, tool, other_items) & COMPONENT_PREVENT_PARRY_START)
to_chat(src, "<span class='warning'>Something is preventing you from parrying!</span>")
return
if(!using_item && !method && length(other_items))
using_item = other_items[1]
method = ITEM_PARRY
data = using_item.block_parry_data
if(!method)
to_chat(src, "<span class='warning'>You have nothing to parry with!</span>")
return FALSE
//QOL: Try to enable combat mode if it isn't already
SEND_SIGNAL(src, COMSIG_ENABLE_COMBAT_MODE)
if(!SEND_SIGNAL(src, COMSIG_COMBAT_MODE_CHECK, COMBAT_MODE_ACTIVE))

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