diff --git a/_maps/map_files/Cerestation/cerestation.dmm b/_maps/map_files/Cerestation/cerestation.dmm
index f10211f5b1..860ff65d60 100644
--- a/_maps/map_files/Cerestation/cerestation.dmm
+++ b/_maps/map_files/Cerestation/cerestation.dmm
@@ -7034,8 +7034,8 @@
"anI" = (
/obj/docking_port/stationary/random{
dir = 1;
- id = "pod_asteroid1";
- name = "asteroid"
+ id = "pod_lavaland1";
+ name = "lavaland"
},
/turf/open/space,
/area/space)
@@ -8103,7 +8103,7 @@
/obj/machinery/computer/shuttle/pod{
pixel_x = -32;
pixel_y = 0;
- possible_destinations = "pod_asteroid1";
+ possible_destinations = "pod_lavaland1";
shuttleId = "pod1"
},
/obj/machinery/light/small{
@@ -40738,7 +40738,7 @@
/obj/machinery/computer/shuttle/pod{
pixel_x = 0;
pixel_y = 32;
- possible_destinations = "pod_asteroid3";
+ possible_destinations = "pod_lavaland3";
shuttleId = "pod3"
},
/obj/item/device/radio/intercom{
@@ -40760,8 +40760,8 @@
"btw" = (
/obj/docking_port/stationary/random{
dir = 4;
- id = "pod_asteroid3";
- name = "asteroid"
+ id = "pod_lavaland3";
+ name = "lavaland"
},
/turf/open/space,
/area/space)
@@ -68963,8 +68963,8 @@
"crd" = (
/obj/docking_port/stationary/random{
dir = 8;
- id = "pod_asteroid2";
- name = "asteroid"
+ id = "pod_lavaland2";
+ name = "lavaland"
},
/turf/open/space,
/area/space)
@@ -68979,7 +68979,7 @@
/obj/machinery/computer/shuttle/pod{
pixel_x = 0;
pixel_y = -32;
- possible_destinations = "pod_asteroid2";
+ possible_destinations = "pod_lavaland2";
shuttleId = "pod2"
},
/obj/structure/chair{
diff --git a/_maps/map_files/Deltastation/DeltaStation2.dmm b/_maps/map_files/Deltastation/DeltaStation2.dmm
index f5e6964696..d44eef655f 100644
--- a/_maps/map_files/Deltastation/DeltaStation2.dmm
+++ b/_maps/map_files/Deltastation/DeltaStation2.dmm
@@ -142,15 +142,15 @@
/area/solar/auxstarboard)
"aap" = (
/obj/docking_port/stationary/random{
- id = "pod_asteroid1";
- name = "asteroid"
+ id = "pod_lavaland1";
+ name = "lavaland"
},
/turf/open/space,
/area/space)
"aaq" = (
/obj/docking_port/stationary/random{
- id = "pod_asteroid2";
- name = "asteroid"
+ id = "pod_lavaland2";
+ name = "lavaland"
},
/turf/open/space,
/area/space)
@@ -203,7 +203,7 @@
},
/obj/machinery/computer/shuttle/pod{
pixel_x = -32;
- possible_destinations = "pod_asteroid1";
+ possible_destinations = "pod_lavaland1";
shuttleId = "pod1"
},
/obj/effect/turf_decal/stripes/line{
@@ -226,7 +226,7 @@
},
/obj/machinery/computer/shuttle/pod{
pixel_x = -32;
- possible_destinations = "pod_asteroid2";
+ possible_destinations = "pod_lavaland2";
shuttleId = "pod2"
},
/obj/effect/turf_decal/stripes/line{
@@ -10753,7 +10753,7 @@
/obj/effect/decal/cleanable/dirt,
/obj/effect/decal/cleanable/dirt,
/turf/open/floor/plasteel/loadingarea{
- baseturf = /turf/open/floor/plating/lava/smooth/lava_land_surface;
+ baseturf = /turf/open/space;
dir = 8
},
/area/quartermaster/storage)
@@ -11240,7 +11240,7 @@
/area/quartermaster/storage)
"awJ" = (
/turf/open/floor/plasteel/loadingarea{
- baseturf = /turf/open/floor/plating/lava/smooth/lava_land_surface;
+ baseturf = /turf/open/space;
dir = 8
},
/area/quartermaster/storage)
@@ -25977,7 +25977,7 @@
},
/obj/machinery/computer/shuttle/pod{
pixel_y = -32;
- possible_destinations = "pod_asteroid3";
+ possible_destinations = "pod_lavaland3";
shuttleId = "pod3"
},
/obj/effect/turf_decal/stripes/line{
@@ -25996,8 +25996,8 @@
"aXK" = (
/obj/docking_port/stationary/random{
dir = 4;
- id = "pod_asteroid4";
- name = "asteroid"
+ id = "pod_lavaland4";
+ name = "lavaland"
},
/turf/open/space,
/area/space)
@@ -31236,7 +31236,7 @@
icon_state = "1-4"
},
/turf/open/floor/plasteel/loadingarea{
- baseturf = /turf/open/floor/plating/lava/smooth/lava_land_surface;
+ baseturf = /turf/open/space;
dir = 8
},
/area/quartermaster/miningdock{
@@ -34793,7 +34793,6 @@
dir = 4
},
/turf/open/floor/plasteel{
- desc = "";
icon_state = "L14"
},
/area/hallway/primary/central)
@@ -52476,7 +52475,7 @@
name = "Queue Shutters"
},
/turf/open/floor/plasteel/loadingarea{
- baseturf = /turf/open/floor/plating/lava/smooth/lava_land_surface;
+ baseturf = /turf/open/space;
dir = 8
},
/area/hallway/primary/central)
@@ -70988,7 +70987,6 @@
"cDW" = (
/obj/machinery/atmospherics/pipe/manifold/supply/hidden,
/turf/open/floor/plasteel{
- desc = "";
icon_state = "L13";
name = "floor"
},
@@ -79514,8 +79512,13 @@
name = "Medbay Central"
})
"cUf" = (
-/obj/machinery/smartfridge/chemistry,
-/turf/closed/wall,
+/obj/structure/grille,
+/obj/machinery/door/poddoor/shutters/preopen{
+ id = "chemisttop";
+ name = "Chemisty Lobby Shutters"
+ },
+/obj/structure/window/reinforced/fulltile,
+/turf/open/floor/plating,
/area/medical/medbay{
name = "Medbay Central"
})
@@ -79538,14 +79541,9 @@
name = "Medbay Central"
})
"cUh" = (
-/obj/structure/grille,
-/obj/structure/window/reinforced/fulltile,
-/obj/machinery/door/poddoor/shutters/preopen{
- id = "chemisttop";
- name = "Chemisty Lobby Shutters"
- },
/obj/structure/disposalpipe/segment,
-/turf/open/floor/plating,
+/obj/machinery/smartfridge/chemistry,
+/turf/closed/wall,
/area/medical/medbay{
name = "Medbay Central"
})
@@ -82191,6 +82189,7 @@
/obj/item/weapon/grenade/chem_grenade,
/obj/item/weapon/grenade/chem_grenade,
/obj/item/weapon/grenade/chem_grenade,
+/obj/item/weapon/screwdriver,
/turf/open/floor/plasteel/whiteyellow/corner{
icon_state = "whiteyellowcorner";
dir = 8
@@ -96355,7 +96354,6 @@
},
/area/medical/morgue)
"dAn" = (
-/turf/open/floor/plating,
/obj/effect/decal/cleanable/dirt,
/obj/machinery/atmospherics/pipe/manifold/supply/hidden{
icon_state = "manifold";
@@ -104162,7 +104160,7 @@
name = "emergency shower"
},
/turf/open/floor/plasteel/whiteblue/side{
- baseturf = /turf/open/floor/plating/lava/smooth/lava_land_surface;
+ baseturf = /turf/open/space;
dir = 4
},
/area/shuttle/escape)
diff --git a/_maps/map_files/MetaStation/MetaStation.dmm b/_maps/map_files/MetaStation/MetaStation.dmm
index abc3eccf3d..c70792e686 100644
--- a/_maps/map_files/MetaStation/MetaStation.dmm
+++ b/_maps/map_files/MetaStation/MetaStation.dmm
@@ -1910,8 +1910,8 @@
/area/shuttle/pod_3)
"adG" = (
/obj/docking_port/stationary/random{
- id = "pod_asteroid2";
- name = "asteroid"
+ id = "pod_lavaland2";
+ name = "lavaland"
},
/turf/open/space,
/area/space)
@@ -1927,7 +1927,7 @@
},
/obj/machinery/computer/shuttle/pod{
pixel_x = -32;
- possible_destinations = "pod_asteroid2";
+ possible_destinations = "pod_lavaland2";
shuttleId = "pod2"
},
/turf/open/floor/mineral/titanium/blue,
@@ -23696,7 +23696,7 @@
},
/obj/machinery/computer/shuttle/pod{
pixel_y = -32;
- possible_destinations = "pod_asteroid3";
+ possible_destinations = "pod_lavaland3";
shuttleId = "pod3"
},
/turf/open/floor/mineral/titanium/blue,
@@ -27963,7 +27963,6 @@
dir = 4
},
/turf/open/floor/plasteel{
- desc = "";
icon_state = "L13";
name = "floor"
},
@@ -28813,7 +28812,6 @@
icon_state = "4-8"
},
/turf/open/floor/plasteel{
- desc = "";
icon_state = "L14"
},
/area/hallway/primary/central)
@@ -34140,8 +34138,8 @@
"bii" = (
/obj/docking_port/stationary/random{
dir = 4;
- id = "pod_asteroid3";
- name = "asteroid"
+ id = "pod_lavaland3";
+ name = "lavaland"
},
/turf/open/space,
/area/space)
@@ -86090,8 +86088,8 @@
/area/toxins/xenobiology)
"cSP" = (
/obj/docking_port/stationary/random{
- id = "pod_asteroid1";
- name = "asteroid"
+ id = "pod_lavaland1";
+ name = "lavaland"
},
/turf/open/space,
/area/space)
@@ -86181,7 +86179,7 @@
},
/obj/machinery/computer/shuttle/pod{
pixel_x = -32;
- possible_destinations = "pod_asteroid1";
+ possible_destinations = "pod_lavaland1";
shuttleId = "pod1"
},
/turf/open/floor/mineral/titanium/blue,
@@ -86374,7 +86372,7 @@
},
/obj/machinery/computer/shuttle/pod{
pixel_y = -32;
- possible_destinations = "pod_asteroid4";
+ possible_destinations = "pod_lavaland4";
shuttleId = "pod4"
},
/turf/open/floor/mineral/titanium/blue,
@@ -87168,8 +87166,8 @@
"cUL" = (
/obj/docking_port/stationary/random{
dir = 4;
- id = "pod_asteroid4";
- name = "asteroid"
+ id = "pod_lavaland4";
+ name = "lavaland"
},
/turf/open/space,
/area/space)
diff --git a/_maps/map_files/Mining/Lavaland.dmm b/_maps/map_files/Mining/Lavaland.dmm
index 778fb50c88..c37c4ca3a3 100644
--- a/_maps/map_files/Mining/Lavaland.dmm
+++ b/_maps/map_files/Mining/Lavaland.dmm
@@ -513,7 +513,7 @@
/obj/structure/cable{
d1 = 1;
d2 = 4;
- icon_state = "1-4";
+ icon_state = "1-4"
},
/obj/structure/cable{
d1 = 1;
@@ -1040,7 +1040,7 @@
/obj/machinery/atmospherics/pipe/simple/supply/hidden,
/turf/open/floor/plasteel/brown{
baseturf = /turf/open/floor/plating/lava/smooth/lava_land_surface;
- dir = 1;
+ dir = 1
},
/area/mine/living_quarters)
"cg" = (
@@ -1074,7 +1074,7 @@
/obj/structure/cable{
d1 = 1;
d2 = 4;
- icon_state = "1-4";
+ icon_state = "1-4"
},
/turf/open/floor/plasteel{
baseturf = /turf/open/floor/plating/lava/smooth/lava_land_surface
@@ -1497,10 +1497,21 @@
/area/mine/living_quarters)
"dd" = (
/obj/structure/table,
-/obj/item/weapon/reagent_containers/food/drinks/beer,
+/obj/item/weapon/reagent_containers/food/drinks/beer{
+ pixel_x = 7;
+ pixel_y = 5
+ },
/obj/machinery/atmospherics/pipe/simple/supply/hidden{
dir = 5
},
+/obj/item/weapon/reagent_containers/food/drinks/beer{
+ pixel_x = -1;
+ pixel_y = 9
+ },
+/obj/item/weapon/reagent_containers/food/drinks/beer{
+ pixel_x = -8;
+ pixel_y = 0
+ },
/turf/open/floor/plasteel/bar{
baseturf = /turf/open/floor/plating/lava/smooth/lava_land_surface
},
@@ -1772,6 +1783,9 @@
pixel_x = -5;
pixel_y = 30
},
+/obj/machinery/shower{
+ dir = 8
+ },
/turf/open/floor/plasteel/purple/corner{
baseturf = /turf/open/floor/plating/lava/smooth/lava_land_surface
},
@@ -2192,7 +2206,7 @@
},
/turf/open/floor/plasteel/vault{
baseturf = /turf/open/floor/plating/lava/smooth/lava_land_surface;
- dir = 8;
+ dir = 8
},
/area/mine/maintenance)
"ez" = (
@@ -2214,13 +2228,13 @@
/obj/machinery/iv_drip,
/turf/open/floor/plasteel/whiteblue/side{
baseturf = /turf/open/floor/plating/lava/smooth/lava_land_surface;
- dir = 1;
+ dir = 1
},
/area/mine/living_quarters)
"eB" = (
/turf/open/floor/plasteel/whiteblue/side{
baseturf = /turf/open/floor/plating/lava/smooth/lava_land_surface;
- dir = 1;
+ dir = 1
},
/area/mine/living_quarters)
"eC" = (
@@ -2231,7 +2245,7 @@
},
/turf/open/floor/plasteel/whiteblue/side{
baseturf = /turf/open/floor/plating/lava/smooth/lava_land_surface;
- dir = 5;
+ dir = 5
},
/area/mine/living_quarters)
"eD" = (
@@ -2398,7 +2412,7 @@
/obj/item/weapon/storage/firstaid/regular,
/turf/open/floor/plasteel/whiteblue/side{
baseturf = /turf/open/floor/plating/lava/smooth/lava_land_surface;
- dir = 4;
+ dir = 4
},
/area/mine/living_quarters)
"eU" = (
@@ -2512,6 +2526,7 @@
dir = 2;
network = list("MINE")
},
+/obj/structure/reagent_dispensers/watertank,
/turf/open/floor/plasteel/brown{
baseturf = /turf/open/floor/plating/lava/smooth/lava_land_surface;
dir = 5
@@ -2520,7 +2535,7 @@
"fe" = (
/turf/open/floor/plasteel/brown/corner{
baseturf = /turf/open/floor/plating/lava/smooth/lava_land_surface;
- dir = 1;
+ dir = 1
},
/area/mine/production)
"ff" = (
@@ -2578,7 +2593,7 @@
},
/turf/open/floor/plasteel/brown{
baseturf = /turf/open/floor/plating/lava/smooth/lava_land_surface;
- dir = 1;
+ dir = 1
},
/area/mine/living_quarters)
"fm" = (
@@ -2600,7 +2615,7 @@
/obj/machinery/atmospherics/pipe/simple/supply/hidden,
/turf/open/floor/plasteel/brown{
baseturf = /turf/open/floor/plating/lava/smooth/lava_land_surface;
- dir = 1;
+ dir = 1
},
/area/mine/living_quarters)
"fp" = (
@@ -2674,7 +2689,7 @@
/obj/structure/cable{
d1 = 1;
d2 = 4;
- icon_state = "1-4";
+ icon_state = "1-4"
},
/turf/open/floor/plasteel{
baseturf = /turf/open/floor/plating/lava/smooth/lava_land_surface
@@ -2712,6 +2727,10 @@
/obj/machinery/light/small{
dir = 1
},
+/obj/structure/extinguisher_cabinet{
+ pixel_x = -5;
+ pixel_y = 30
+ },
/turf/open/floor/plasteel/purple/corner{
baseturf = /turf/open/floor/plating/lava/smooth/lava_land_surface;
dir = 4
@@ -2794,6 +2813,41 @@
/turf/open/floor/plating/asteroid/basalt/lava_land_surface,
/turf/closed/indestructible/riveted,
/area/space)
+"fQ" = (
+/obj/machinery/shower{
+ dir = 8
+ },
+/obj/effect/turf_decal/delivery,
+/turf/open/floor/plasteel/white,
+/area/mine/laborcamp)
+"fR" = (
+/obj/structure/sink/kitchen{
+ dir = 4;
+ icon_state = "sink_alt";
+ pixel_x = -13;
+ tag = "icon-sink_alt (EAST)"
+ },
+/turf/open/floor/plasteel{
+ baseturf = /turf/open/floor/plating/lava/smooth/lava_land_surface
+ },
+/area/mine/laborcamp)
+"fS" = (
+/obj/structure/reagent_dispensers/watertank,
+/turf/open/floor/plasteel/purple/corner{
+ baseturf = /turf/open/floor/plating/lava/smooth/lava_land_surface
+ },
+/area/mine/production)
+"fT" = (
+/obj/structure/sink{
+ dir = 4;
+ icon_state = "sink";
+ pixel_x = 11;
+ tag = "icon-sink (EAST)"
+ },
+/turf/open/floor/plasteel/bar{
+ baseturf = /turf/open/floor/plating/lava/smooth/lava_land_surface
+ },
+/area/mine/living_quarters)
(1,1,1) = {"
aa
@@ -8919,7 +8973,7 @@ aA
at
at
at
-at
+fR
at
au
fH
@@ -9175,7 +9229,7 @@ an
an
at
at
-at
+fQ
at
dr
an
@@ -14594,8 +14648,8 @@ fj
ee
cT
cZ
-dg
dk
+fT
ee
al
al
@@ -18433,7 +18487,7 @@ af
ab
ab
dx
-dC
+fS
dK
bI
bS
diff --git a/_maps/map_files/OmegaStation/OmegaStation.dmm b/_maps/map_files/OmegaStation/OmegaStation.dmm
index 0e3fea852f..9ea8f8e2c7 100644
--- a/_maps/map_files/OmegaStation/OmegaStation.dmm
+++ b/_maps/map_files/OmegaStation/OmegaStation.dmm
@@ -7303,7 +7303,6 @@
icon_state = "1-2"
},
/turf/open/floor/plasteel{
- desc = "";
icon_state = "L14"
},
/area/hallway/primary/central{
@@ -9155,7 +9154,7 @@
},
/obj/effect/landmark/start/shaft_miner,
/turf/open/floor/plasteel/loadingarea{
- baseturf = /turf/open/floor/plating/lava/smooth/lava_land_surface;
+ baseturf = /turf/open/space;
dir = 8
},
/area/quartermaster/miningdock)
@@ -16523,6 +16522,9 @@
/obj/machinery/status_display{
pixel_x = -32
},
+/obj/machinery/light{
+ dir = 8
+ },
/turf/open/floor/mineral/plastitanium/brig,
/area/shuttle/escape)
"aAb" = (
@@ -16558,6 +16560,9 @@
"aAf" = (
/obj/structure/table/reinforced,
/obj/item/weapon/storage/fancy/donut_box,
+/obj/machinery/light{
+ dir = 4
+ },
/turf/open/floor/plasteel/vault{
dir = 8
},
@@ -24133,6 +24138,9 @@
},
/obj/effect/decal/cleanable/dirt,
/obj/effect/turf_decal/delivery,
+/obj/machinery/light{
+ dir = 8
+ },
/turf/open/floor/plasteel,
/area/shuttle/escape)
"aME" = (
@@ -24187,6 +24195,9 @@
/obj/machinery/status_display{
pixel_x = 32
},
+/obj/machinery/light{
+ dir = 4
+ },
/turf/open/floor/plasteel/whiteblue/side{
dir = 5
},
@@ -25964,7 +25975,6 @@
icon_state = "4-8"
},
/turf/open/floor/plasteel{
- desc = "";
icon_state = "L13";
name = "floor"
},
@@ -41920,6 +41930,38 @@
/area/ruin/unpowered{
name = "Asteroid"
})
+"bvO" = (
+/obj/machinery/light{
+ dir = 1
+ },
+/turf/open/floor/plasteel/neutral/side{
+ dir = 1
+ },
+/area/shuttle/escape)
+"bvP" = (
+/obj/structure/chair{
+ dir = 8
+ },
+/obj/effect/turf_decal/bot,
+/obj/machinery/light/small{
+ dir = 4
+ },
+/turf/open/floor/plasteel,
+/area/shuttle/escape)
+"bvQ" = (
+/obj/structure/chair{
+ dir = 4
+ },
+/obj/effect/turf_decal/bot,
+/obj/machinery/light/small{
+ dir = 8
+ },
+/turf/open/floor/plasteel,
+/area/shuttle/escape)
+"bvR" = (
+/obj/machinery/light,
+/turf/open/floor/plasteel/neutral/side,
+/area/shuttle/escape)
(1,1,1) = {"
aaa
@@ -94203,7 +94245,7 @@ aAb
axY
aDl
aEi
-aEi
+bvP
aEi
aEi
aEi
@@ -94715,13 +94757,13 @@ axY
aAc
axY
aCp
-aDl
+bvO
aEk
aEj
aGd
aEl
aEk
-aJf
+bvR
aKn
aLz
axY
@@ -95231,7 +95273,7 @@ aAd
aCq
aDl
aEm
-aEm
+bvQ
aEm
aEm
aEm
diff --git a/_maps/map_files/PubbyStation/PubbyStation.dmm b/_maps/map_files/PubbyStation/PubbyStation.dmm
index 2de3a5e8dc..56bcff286e 100644
--- a/_maps/map_files/PubbyStation/PubbyStation.dmm
+++ b/_maps/map_files/PubbyStation/PubbyStation.dmm
@@ -32850,10 +32850,6 @@
/turf/open/floor/plasteel/white,
/area/toxins/xenobiology)
"bnU" = (
-/obj/machinery/door/airlock/research{
- name = "Kill Room Access";
- req_access_txt = "55"
- },
/obj/structure/disposalpipe/segment{
dir = 4
},
diff --git a/_maps/map_files/TgStation/tgstation.2.1.3.dmm b/_maps/map_files/TgStation/tgstation.2.1.3.dmm
index 1f112c85f1..220c1bd671 100644
--- a/_maps/map_files/TgStation/tgstation.2.1.3.dmm
+++ b/_maps/map_files/TgStation/tgstation.2.1.3.dmm
@@ -2501,7 +2501,7 @@
"afq" = (
/obj/machinery/computer/shuttle/pod{
pixel_y = -32;
- possible_destinations = "pod_asteroid3";
+ possible_destinations = "pod_lavaland3";
shuttleId = "pod3"
},
/obj/structure/chair{
@@ -7787,8 +7787,8 @@
"aqG" = (
/obj/docking_port/stationary/random{
dir = 4;
- id = "pod_asteroid3";
- name = "asteroid"
+ id = "pod_lavaland3";
+ name = "lavaland"
},
/turf/open/space,
/area/space)
@@ -17330,7 +17330,6 @@
/area/hallway/primary/central)
"aMf" = (
/turf/open/floor/plasteel{
- desc = "";
icon_state = "L13";
name = "floor"
},
@@ -17836,7 +17835,6 @@
/area/hallway/primary/central)
"aNB" = (
/turf/open/floor/plasteel{
- desc = "";
icon_state = "L14"
},
/area/hallway/primary/central)
@@ -53829,8 +53827,8 @@
"cpe" = (
/obj/docking_port/stationary/random{
dir = 8;
- id = "pod_asteroid2";
- name = "asteroid"
+ id = "pod_lavaland2";
+ name = "lavaland"
},
/turf/open/space,
/area/space)
@@ -54085,7 +54083,7 @@
/obj/machinery/computer/shuttle/pod{
pixel_x = 0;
pixel_y = -32;
- possible_destinations = "pod_asteroid2";
+ possible_destinations = "pod_lavaland2";
shuttleId = "pod2"
},
/obj/structure/chair{
@@ -57400,8 +57398,8 @@
"cwV" = (
/obj/docking_port/stationary/random{
dir = 8;
- id = "pod_asteroid1";
- name = "asteroid"
+ id = "pod_lavaland1";
+ name = "lavaland"
},
/turf/open/space,
/area/space)
@@ -57514,7 +57512,7 @@
/obj/machinery/computer/shuttle/pod{
pixel_x = 0;
pixel_y = -32;
- possible_destinations = "pod_asteroid1";
+ possible_destinations = "pod_lavaland1";
shuttleId = "pod1"
},
/obj/structure/chair{
@@ -58430,7 +58428,7 @@
"czL" = (
/obj/machinery/computer/shuttle/pod{
pixel_y = -32;
- possible_destinations = "pod_asteroid4";
+ possible_destinations = "pod_lavaland4";
shuttleId = "pod4"
},
/obj/structure/chair{
@@ -58461,8 +58459,8 @@
"czN" = (
/obj/docking_port/stationary/random{
dir = 4;
- id = "pod_asteroid4";
- name = "asteroid"
+ id = "pod_lavaland4";
+ name = "lavaland"
},
/turf/open/space,
/area/space)
diff --git a/code/__DEFINES/clockcult.dm b/code/__DEFINES/clockcult.dm
index 9c86e031ab..acc0cdc9ab 100644
--- a/code/__DEFINES/clockcult.dm
+++ b/code/__DEFINES/clockcult.dm
@@ -37,15 +37,15 @@ GLOBAL_LIST_EMPTY(all_scripture) //a list containing scripture instances; not us
#define JUDGEMENT_CV_REQ 300
//general component/cooldown things
-#define SLAB_PRODUCTION_TIME 900 //how long(deciseconds) slabs require to produce a single component; defaults to 1 minute 30 seconds
+#define SLAB_PRODUCTION_TIME 450 //how long(deciseconds) slabs require to produce a single component; defaults to 45 seconds
-#define SLAB_SERVANT_SLOWDOWN 300 //how much each servant above 5 slows down slab-based generation; defaults to 30 seconds per sevant
+#define SLAB_SERVANT_SLOWDOWN 150 //how much each servant above 5 slows down slab-based generation; defaults to 15 seconds per sevant
-#define SLAB_SLOWDOWN_MAXIMUM 2700 //maximum slowdown from additional servants; defaults to 4 minutes 30 seconds
+#define SLAB_SLOWDOWN_MAXIMUM 1350 //maximum slowdown from additional servants; defaults to 2 minutes 15 seconds
-#define CACHE_PRODUCTION_TIME 600 //how long(deciseconds) caches require to produce a component; defaults to 1 minute
+#define CACHE_PRODUCTION_TIME 300 //how long(deciseconds) caches require to produce a component; defaults to 30 seconds
-#define ACTIVE_CACHE_SLOWDOWN 100 //how many additional deciseconds caches take to produce a component for each linked cache; defaults to 10 seconds
+#define ACTIVE_CACHE_SLOWDOWN 50 //how many additional deciseconds caches take to produce a component for each linked cache; defaults to 5 seconds
#define LOWER_PROB_PER_COMPONENT 10 //how much each component in the cache reduces the weight of getting another of that component type
@@ -87,9 +87,9 @@ GLOBAL_LIST_EMPTY(all_scripture) //a list containing scripture instances; not us
#define GATEWAY_RATVAR_ARRIVAL 300 //when progress is at or above this, game over ratvar's here everybody go home
-#define ARK_SUMMON_COST 3 //how many of each component an Ark costs to summon
+#define ARK_SUMMON_COST 5 //how many of each component an Ark costs to summon
-#define ARK_CONSUME_COST 7 //how many of each component an Ark needs to consume to activate
+#define ARK_CONSUME_COST 15 //how many of each component an Ark needs to consume to activate
//Objective text define
#define CLOCKCULT_OBJECTIVE "Construct the Ark of the Clockwork Justicar and free Ratvar."
diff --git a/code/__HELPERS/unsorted.dm b/code/__HELPERS/unsorted.dm
index 1da1b50aa3..d0fcb3bcbe 100644
--- a/code/__HELPERS/unsorted.dm
+++ b/code/__HELPERS/unsorted.dm
@@ -1342,6 +1342,7 @@ GLOBAL_DATUM_INIT(dview_mob, /mob/dview, new)
//This prevents RCEs from badmins
//kevinz000 if you touch this I will hunt you down
GLOBAL_VAR_INIT(valid_HTTPSGet, FALSE)
+GLOBAL_PROTECT(valid_HTTPSGet)
/proc/HTTPSGet(url)
if(findtext(url, "\""))
GLOB.valid_HTTPSGet = FALSE
diff --git a/code/_globalvars/lists/objects.dm b/code/_globalvars/lists/objects.dm
index be771e0676..e82976d4a3 100644
--- a/code/_globalvars/lists/objects.dm
+++ b/code/_globalvars/lists/objects.dm
@@ -29,6 +29,7 @@ GLOBAL_LIST_EMPTY(zombie_infection_list) // A list of all zombie_infection org
GLOBAL_LIST_EMPTY(meteor_list) // List of all meteors.
GLOBAL_LIST_EMPTY(active_jammers) // List of active radio jammers
GLOBAL_LIST_EMPTY(ladders)
+GLOBAL_LIST_EMPTY(trophy_cases)
GLOBAL_LIST_EMPTY(wire_color_directory)
GLOBAL_LIST_EMPTY(wire_name_directory)
\ No newline at end of file
diff --git a/code/_onclick/hud/hud.dm b/code/_onclick/hud/hud.dm
index b1b4a1cbb3..f6a3688626 100644
--- a/code/_onclick/hud/hud.dm
+++ b/code/_onclick/hud/hud.dm
@@ -208,7 +208,6 @@
mymob.reload_fullscreen()
update_parallax_pref(screenmob)
-
/datum/hud/human/show_hud(version = 0,mob/viewmob)
..()
hidden_inventory_update(viewmob)
@@ -266,3 +265,6 @@
E.screen_loc = ui_equip_position(mymob)
if(mymob.hud_used)
show_hud(HUD_STYLE_STANDARD,mymob)
+
+/datum/hud/proc/update_locked_slots()
+ return
\ No newline at end of file
diff --git a/code/_onclick/hud/human.dm b/code/_onclick/hud/human.dm
index f35579c16b..8453b12085 100644
--- a/code/_onclick/hud/human.dm
+++ b/code/_onclick/hud/human.dm
@@ -124,7 +124,6 @@
inv_box.icon = ui_style
inv_box.slot_id = slot_w_uniform
inv_box.icon_state = "uniform"
-// inv_box.icon_full = "template"
inv_box.screen_loc = ui_iclothing
toggleable_inventory += inv_box
@@ -133,7 +132,6 @@
inv_box.icon = ui_style
inv_box.slot_id = slot_wear_suit
inv_box.icon_state = "suit"
-// inv_box.icon_full = "template"
inv_box.screen_loc = ui_oclothing
toggleable_inventory += inv_box
@@ -155,7 +153,6 @@
inv_box.name = "id"
inv_box.icon = ui_style
inv_box.icon_state = "id"
-// inv_box.icon_full = "template_small"
inv_box.screen_loc = ui_id
inv_box.slot_id = slot_wear_id
static_inventory += inv_box
@@ -164,7 +161,6 @@
inv_box.name = "mask"
inv_box.icon = ui_style
inv_box.icon_state = "mask"
-// inv_box.icon_full = "template"
inv_box.screen_loc = ui_mask
inv_box.slot_id = slot_wear_mask
toggleable_inventory += inv_box
@@ -173,7 +169,6 @@
inv_box.name = "neck"
inv_box.icon = ui_style
inv_box.icon_state = "neck"
-// inv_box.icon_full = "template"
inv_box.screen_loc = ui_neck
inv_box.slot_id = slot_neck
toggleable_inventory += inv_box
@@ -182,7 +177,6 @@
inv_box.name = "back"
inv_box.icon = ui_style
inv_box.icon_state = "back"
-// inv_box.icon_full = "template_small"
inv_box.screen_loc = ui_back
inv_box.slot_id = slot_back
static_inventory += inv_box
@@ -191,7 +185,6 @@
inv_box.name = "storage1"
inv_box.icon = ui_style
inv_box.icon_state = "pocket"
-// inv_box.icon_full = "template_small"
inv_box.screen_loc = ui_storage1
inv_box.slot_id = slot_l_store
static_inventory += inv_box
@@ -200,7 +193,6 @@
inv_box.name = "storage2"
inv_box.icon = ui_style
inv_box.icon_state = "pocket"
-// inv_box.icon_full = "template_small"
inv_box.screen_loc = ui_storage2
inv_box.slot_id = slot_r_store
static_inventory += inv_box
@@ -209,7 +201,6 @@
inv_box.name = "suit storage"
inv_box.icon = ui_style
inv_box.icon_state = "suit_storage"
-// inv_box.icon_full = "template"
inv_box.screen_loc = ui_sstore1
inv_box.slot_id = slot_s_store
static_inventory += inv_box
@@ -233,7 +224,6 @@
inv_box.name = "gloves"
inv_box.icon = ui_style
inv_box.icon_state = "gloves"
-// inv_box.icon_full = "template"
inv_box.screen_loc = ui_gloves
inv_box.slot_id = slot_gloves
toggleable_inventory += inv_box
@@ -242,7 +232,6 @@
inv_box.name = "eyes"
inv_box.icon = ui_style
inv_box.icon_state = "glasses"
-// inv_box.icon_full = "template"
inv_box.screen_loc = ui_glasses
inv_box.slot_id = slot_glasses
toggleable_inventory += inv_box
@@ -251,7 +240,6 @@
inv_box.name = "ears"
inv_box.icon = ui_style
inv_box.icon_state = "ears"
-// inv_box.icon_full = "template"
inv_box.screen_loc = ui_ears
inv_box.slot_id = slot_ears
toggleable_inventory += inv_box
@@ -260,7 +248,6 @@
inv_box.name = "head"
inv_box.icon = ui_style
inv_box.icon_state = "head"
-// inv_box.icon_full = "template"
inv_box.screen_loc = ui_head
inv_box.slot_id = slot_head
toggleable_inventory += inv_box
@@ -269,7 +256,6 @@
inv_box.name = "shoes"
inv_box.icon = ui_style
inv_box.icon_state = "shoes"
-// inv_box.icon_full = "template"
inv_box.screen_loc = ui_shoes
inv_box.slot_id = slot_shoes
toggleable_inventory += inv_box
@@ -327,6 +313,18 @@
inv_slots[inv.slot_id] = inv
inv.update_icon()
+/datum/hud/human/update_locked_slots()
+ if(!mymob)
+ return
+ var/mob/living/carbon/human/H = mymob
+ var/datum/species/S = H.dna.species
+ for(var/obj/screen/inventory/inv in (static_inventory + toggleable_inventory))
+ if(inv.slot_id)
+ if(inv.slot_id in S.no_equip)
+ inv.alpha = 128
+ else
+ inv.alpha = initial(inv.alpha)
+
/datum/hud/human/hidden_inventory_update(mob/viewer)
if(!mymob)
return
diff --git a/code/controllers/subsystem/persistence.dm b/code/controllers/subsystem/persistence.dm
index e1cf992e8b..6b3e47054c 100644
--- a/code/controllers/subsystem/persistence.dm
+++ b/code/controllers/subsystem/persistence.dm
@@ -11,10 +11,14 @@ SUBSYSTEM_DEF(persistence)
var/list/saved_messages = list()
var/savefile/chisel_messages_sav
+ var/savefile/trophy_sav
+ var/list/saved_trophies = list()
+
/datum/controller/subsystem/persistence/Initialize()
LoadSatchels()
LoadPoly()
LoadChiselMessages()
+ LoadTrophies()
..()
/datum/controller/subsystem/persistence/proc/LoadSatchels()
@@ -105,10 +109,49 @@ SUBSYSTEM_DEF(persistence)
M.persists = FALSE
qdel(M)
+/datum/controller/subsystem/persistence/proc/LoadTrophies()
+ trophy_sav = new /savefile("data/npc_saves/TrophyItems.sav")
+ var/saved_json
+ trophy_sav >> saved_json
+
+ var/decoded_json = json_decode(saved_json)
+
+ if(!islist(decoded_json))
+ return
+
+ saved_trophies = decoded_json
+
+ SetUpTrophies(saved_trophies.Copy())
+
+/datum/controller/subsystem/persistence/proc/SetUpTrophies(list/trophy_items)
+ for(var/A in GLOB.trophy_cases)
+ var/obj/structure/displaycase/trophy/T = A
+ T.added_roundstart = TRUE
+
+ var/trophy_data = pick_n_take(trophy_items)
+
+ if(!islist(trophy_data))
+ continue
+
+ var/list/chosen_trophy = trophy_data
+
+ if(!chosen_trophy || isemptylist(chosen_trophy)) //Malformed
+ continue
+
+ var/path = text2path(chosen_trophy["path"]) //If the item no longer exist, this returns null
+ if(!path)
+ continue
+
+ T.showpiece = new /obj/item/showpiece_dummy(T, path)
+ T.trophy_message = chosen_trophy["message"]
+ T.placer_key = chosen_trophy["placer_key"]
+ T.update_icon()
+
/datum/controller/subsystem/persistence/proc/CollectData()
CollectChiselMessages()
CollectSecretSatchels()
+ CollectTrophies()
/datum/controller/subsystem/persistence/proc/CollectSecretSatchels()
for(var/A in new_secret_satchels)
@@ -135,4 +178,16 @@ SUBSYSTEM_DEF(persistence)
chisel_messages_sav[SSmapping.config.map_name] << json_encode(saved_messages)
/datum/controller/subsystem/persistence/proc/SaveChiselMessage(obj/structure/chisel_message/M)
- saved_messages += list(M.pack()) // dm eats one list.
+ saved_messages += list(M.pack()) // dm eats one list
+
+
+/datum/controller/subsystem/persistence/proc/CollectTrophies()
+ trophy_sav << json_encode(saved_trophies)
+
+/datum/controller/subsystem/persistence/proc/SaveTrophy(obj/structure/displaycase/trophy/T)
+ if(!T.added_roundstart && T.showpiece)
+ var/list/data = list()
+ data["path"] = T.showpiece.type
+ data["message"] = T.trophy_message
+ data["placer_key"] = T.placer_key
+ saved_trophies += list(data)
\ No newline at end of file
diff --git a/code/controllers/subsystem/processing/flightpacks.dm b/code/controllers/subsystem/processing/flightpacks.dm
index 1d85811878..0639f64810 100644
--- a/code/controllers/subsystem/processing/flightpacks.dm
+++ b/code/controllers/subsystem/processing/flightpacks.dm
@@ -5,7 +5,7 @@ PROCESSING_SUBSYSTEM_DEF(flightpacks)
stat_tag = "FM"
flags = SS_NO_INIT|SS_TICKER|SS_KEEP_TIMING
- var/flightsuit_processing = FLIGHTSUIT_PROCESSING_FULL
+ var/flightsuit_processing = FLIGHTSUIT_PROCESSING_NONE
/datum/controller/subsystem/processing/flightpacks/Initialize()
sync_flightsuit_processing()
diff --git a/code/controllers/subsystem/ticker.dm b/code/controllers/subsystem/ticker.dm
index f3ac66e001..abf05aad72 100644
--- a/code/controllers/subsystem/ticker.dm
+++ b/code/controllers/subsystem/ticker.dm
@@ -625,8 +625,8 @@ SUBSYSTEM_DEF(ticker)
if(selected_tip)
m = selected_tip
else
- var/list/randomtips = world.file2list("config/tips.txt")
- var/list/memetips = world.file2list("config/sillytips.txt")
+ var/list/randomtips = world.file2list("strings/tips.txt")
+ var/list/memetips = world.file2list("strings/sillytips.txt")
if(randomtips.len && prob(95))
m = pick(randomtips)
else if(memetips.len)
diff --git a/code/datums/antagonists/datum_cult.dm.rej b/code/datums/antagonists/datum_cult.dm.rej
deleted file mode 100644
index 0fc846a73c..0000000000
--- a/code/datums/antagonists/datum_cult.dm.rej
+++ /dev/null
@@ -1,25 +0,0 @@
-diff a/code/datums/antagonists/datum_cult.dm b/code/datums/antagonists/datum_cult.dm (rejected hunks)
-@@ -5,13 +5,20 @@
- qdel(communion)
- return ..()
-
-+/datum/antagonist/cult/can_be_owned(datum/mind/new_owner)
-+ . = ..()
-+ if(.)
-+ . = is_convertable_to_cult(new_owner.current)
-+
- /datum/antagonist/cult/on_gain()
- . = ..()
-- if(!owner)
-- return
-+ SSticker.mode.cult += owner
-+ SSticker.mode.update_cult_icons_added(owner)
-+ if(istype(SSticker.mode, /datum/game_mode/cult))
-+ var/datum/game_mode/cult/C = SSticker.mode
-+ C.memorize_cult_objectives(owner)
- if(jobban_isbanned(owner.current, ROLE_CULTIST))
- addtimer(CALLBACK(SSticker.mode, /datum/game_mode.proc/replace_jobbaned_player, owner.current, ROLE_CULTIST, ROLE_CULTIST), 0)
-- SSticker.mode.update_cult_icons_added(owner)
- owner.current.log_message("Has been converted to the cult of Nar'Sie!", INDIVIDUAL_ATTACK_LOG)
-
- /datum/antagonist/cult/apply_innate_effects(mob/living/mob_override)
diff --git a/code/datums/holocall.dm b/code/datums/holocall.dm
new file mode 100644
index 0000000000..6d6b1104dc
--- /dev/null
+++ b/code/datums/holocall.dm
@@ -0,0 +1,159 @@
+#define HOLOPAD_MAX_DIAL_TIME 200
+
+/mob/camera/aiEye/remote/holo/setLoc()
+ . = ..()
+ var/obj/machinery/holopad/H = origin
+ H.move_hologram(eye_user, loc)
+
+//this datum manages it's own references
+
+/datum/holocall
+ var/mob/living/user //the one that called
+ var/obj/machinery/holopad/calling_holopad //the one that sent the call
+ var/obj/machinery/holopad/connected_holopad //the one that answered the call (may be null)
+ var/list/dialed_holopads //all things called, will be cleared out to just connected_holopad once answered
+
+ var/mob/camera/aiEye/remote/holo/eye //user's eye, once connected
+ var/obj/effect/overlay/holo_pad_hologram/hologram //user's hologram, once connected
+
+ var/call_start_time
+
+//creates a holocall made by `caller` from `calling_pad` to `callees`
+/datum/holocall/New(mob/living/caller, obj/machinery/holopad/calling_pad, list/callees)
+ call_start_time = world.time
+ user = caller
+ calling_pad.outgoing_call = src
+ calling_holopad = calling_pad
+ dialed_holopads = list()
+
+ for(var/I in callees)
+ var/obj/machinery/holopad/H = I
+ if(!QDELETED(H) && H.is_operational())
+ dialed_holopads += H
+ LAZYADD(H.holo_calls, src)
+
+ if(!dialed_holopads.len)
+ calling_pad.say("Connection failure.")
+ qdel(src)
+
+ testing("Holocall started")
+
+//cleans up ALL references :)
+/datum/holocall/Destroy()
+ QDEL_NULL(eye)
+
+ user.reset_perspective()
+
+ user = null
+ hologram.HC = null
+ hologram = null
+ calling_holopad.outgoing_call = null
+
+ for(var/I in dialed_holopads)
+ var/obj/machinery/holopad/H = I
+ LAZYREMOVE(H.holo_calls, src)
+ dialed_holopads.Cut()
+
+ if(calling_holopad)
+ calling_holopad.SetLightsAndPower()
+ calling_holopad = null
+ if(connected_holopad)
+ connected_holopad.SetLightsAndPower()
+ connected_holopad = null
+
+ testing("Holocall destroyed")
+
+ return ..()
+
+//Gracefully disconnects a holopad `H` from a call. Pads not in the call are ignored. Notifies participants of the disconnection
+/datum/holocall/proc/Disconnect(obj/machinery/holopad/H)
+ testing("Holocall disconnect")
+ if(H == connected_holopad)
+ calling_holopad.say("[usr] disconnected.")
+ else if(H == calling_holopad && connected_holopad)
+ connected_holopad.say("[usr] disconnected.")
+
+ ConnectionFailure(H, TRUE)
+
+//Forcefully disconnects a holopad `H` from a call. Pads not in the call are ignored.
+/datum/holocall/proc/ConnectionFailure(obj/machinery/holopad/H, graceful = FALSE)
+ testing("Holocall connection failure: graceful [graceful]")
+ if(H == connected_holopad || H == calling_holopad)
+ if(!graceful)
+ calling_holopad.say("Connection failure.")
+ qdel(src)
+ return
+
+ LAZYREMOVE(H.holo_calls, src)
+ dialed_holopads -= H
+ if(!dialed_holopads.len)
+ if(graceful)
+ calling_holopad.say("Call rejected.")
+ testing("No recipients, terminating")
+ qdel(src)
+
+//Answers a call made to a holopad `H` which cannot be the calling holopad. Pads not in the call are ignored
+/datum/holocall/proc/Answer(obj/machinery/holopad/H)
+ testing("Holocall answer")
+ if(H == calling_holopad)
+ CRASH("How cute, a holopad tried to answer itself.")
+
+ if(!(H in dialed_holopads))
+ return
+
+ if(connected_holopad)
+ CRASH("Multi-connection holocall")
+
+ connected_holopad = H
+ for(var/I in dialed_holopads)
+ if(I == H)
+ continue
+ var/obj/machinery/holopad/Holo = I
+ LAZYREMOVE(Holo.holo_calls, src)
+ dialed_holopads -= Holo
+
+ for(var/I in H.holo_calls)
+ var/datum/holocall/HC = I
+ if(HC != src)
+ HC.Disconnect(H)
+
+ if(!Check())
+ return
+
+ hologram = H.activate_holo(user)
+ hologram.HC = src
+
+ //eyeobj code is horrid, this is the best copypasta I could make
+ eye = new
+ eye.origin = H
+ eye.eye_initialized = TRUE
+ eye.eye_user = user
+ eye.name = "Camera Eye ([user.name])"
+ user.remote_control = eye
+ user.reset_perspective(eye)
+ eye.setLoc(H.loc)
+
+//Checks the validity of a holocall and qdels itself if it's not. Returns TRUE if valid, FALSE otherwise
+/datum/holocall/proc/Check()
+ for(var/I in dialed_holopads)
+ var/obj/machinery/holopad/H = I
+ if(!H.is_operational())
+ ConnectionFailure(H)
+
+ if(QDELETED(src))
+ return FALSE
+
+ . = !QDELETED(user) && !user.incapacitated() && !QDELETED(calling_holopad) && calling_holopad.is_operational() && user.loc == calling_holopad.loc
+
+ if(.)
+ if(connected_holopad)
+ . = !QDELETED(connected_holopad) && connected_holopad.is_operational()
+ else
+ . = world.time < (call_start_time + HOLOPAD_MAX_DIAL_TIME)
+ if(!.)
+ calling_holopad.say("No answer recieved.")
+ calling_holopad.temp = ""
+
+ if(!.)
+ testing("Holocall Check fail")
+ qdel(src)
diff --git a/code/datums/mind.dm b/code/datums/mind.dm
index 421cecc95b..e99d5bb59a 100644
--- a/code/datums/mind.dm
+++ b/code/datums/mind.dm
@@ -44,9 +44,7 @@
var/datum/job/assigned_job
var/list/datum/objective/objectives = list()
- var/list/datum/objective/special_verbs = list()
- var/list/cult_words = list()
var/list/spell_list = list() // Wizard mode & "Give Spell" badmin button.
var/datum/faction/faction //associated faction
diff --git a/code/datums/ruins/lavaland.dm b/code/datums/ruins/lavaland.dm
index 3a54db4e0a..011363f001 100644
--- a/code/datums/ruins/lavaland.dm
+++ b/code/datums/ruins/lavaland.dm
@@ -42,6 +42,7 @@
However, all the inhabitants seem to do is grow drugs and guns."
suffix = "lavaland_surface_seed_vault.dmm"
cost = 10
+ allow_duplicates = FALSE
/datum/map_template/ruin/lavaland/ash_walker
name = "Ash Walker Nest"
diff --git a/code/datums/status_effects/status_effect.dm b/code/datums/status_effects/status_effect.dm
index 51b4f8fc5f..ec725885a9 100644
--- a/code/datums/status_effects/status_effect.dm
+++ b/code/datums/status_effects/status_effect.dm
@@ -10,6 +10,7 @@
var/status_type = STATUS_EFFECT_UNIQUE //How many of the effect can be on one mob, and what happens when you try to add another
var/on_remove_on_mob_delete = FALSE //if we call on_remove() when the mob is deleted
var/alert_type = /obj/screen/alert/status_effect //the alert thrown by the status effect, contains name and description
+ var/obj/screen/alert/status_effect/linked_alert = null //the alert itself, if it exists
/datum/status_effect/New(mob/living/new_owner)
if(new_owner)
@@ -40,6 +41,7 @@
if(alert_type)
var/obj/screen/alert/status_effect/A = owner.throw_alert(id, alert_type)
A.attached_effect = src //so the alert can reference us, if it needs to
+ linked_alert = A //so we can reference the alert, if we need to
START_PROCESSING(SSfastprocess, src)
/datum/status_effect/process()
diff --git a/code/game/gamemodes/changeling/changeling_power.dm b/code/game/gamemodes/changeling/changeling_power.dm
index 67eb216d58..489228a30c 100644
--- a/code/game/gamemodes/changeling/changeling_power.dm
+++ b/code/game/gamemodes/changeling/changeling_power.dm
@@ -13,8 +13,6 @@
var/req_dna = 0 //amount of dna needed to use this ability. Changelings always have atleast 1
var/req_human = 0 //if you need to be human to use this ability
var/req_stat = CONSCIOUS // CONSCIOUS, UNCONSCIOUS or DEAD
- var/genetic_damage = 0 // genetic damage caused by using the sting. Nothing to do with cloneloss.
- var/max_genetic_damage = 100 // hard counter for spamming abilities. Not used/balanced much yet.
var/always_keep = 0 // important for abilities like revive that screw you if you lose them.
var/ignores_fakedeath = FALSE // usable with the FAKEDEATH flag
@@ -39,7 +37,7 @@
if(sting_action(user, target))
SSblackbox.add_details("changeling_powers",name)
sting_feedback(user, target)
- take_chemical_cost(c)
+ c.chem_charges -= chemical_cost
/obj/effect/proc_holder/changeling/proc/sting_action(mob/user, mob/target)
return 0
@@ -47,10 +45,6 @@
/obj/effect/proc_holder/changeling/proc/sting_feedback(mob/user, mob/target)
return 0
-/obj/effect/proc_holder/changeling/proc/take_chemical_cost(datum/changeling/changeling)
- changeling.chem_charges -= chemical_cost
- changeling.geneticdamage += genetic_damage
-
//Fairly important to remember to return 1 on success >.<
/obj/effect/proc_holder/changeling/proc/can_sting(mob/user, mob/target)
if(!ishuman(user) && !ismonkey(user)) //typecast everything from mob to carbon from this point onwards
@@ -71,9 +65,6 @@
if((user.status_flags & FAKEDEATH) && (!ignores_fakedeath))
to_chat(user, "We are incapacitated.")
return 0
- if(c.geneticdamage > max_genetic_damage)
- to_chat(user, "Our genomes are still reassembling. We need time to recover first.")
- return 0
return 1
//used in /mob/Stat()
diff --git a/code/game/gamemodes/changeling/powers/absorb.dm b/code/game/gamemodes/changeling/powers/absorb.dm
index 6a52ab9312..b6b3372ae3 100644
--- a/code/game/gamemodes/changeling/powers/absorb.dm
+++ b/code/game/gamemodes/changeling/powers/absorb.dm
@@ -4,7 +4,6 @@
chemical_cost = 0
dna_cost = 0
req_human = 1
- max_genetic_damage = 100
/obj/effect/proc_holder/changeling/absorbDNA/can_sting(mob/living/carbon/user)
if(!..())
diff --git a/code/game/gamemodes/changeling/powers/biodegrade.dm b/code/game/gamemodes/changeling/powers/biodegrade.dm
index 453dec9375..6e2d6b0ddd 100644
--- a/code/game/gamemodes/changeling/powers/biodegrade.dm
+++ b/code/game/gamemodes/changeling/powers/biodegrade.dm
@@ -5,9 +5,6 @@
chemical_cost = 30 //High cost to prevent spam
dna_cost = 2
req_human = 1
- genetic_damage = 10
- max_genetic_damage = 0
-
/obj/effect/proc_holder/changeling/biodegrade/sting_action(mob/living/carbon/human/user)
var/used = FALSE // only one form of shackles removed per use
diff --git a/code/game/gamemodes/changeling/powers/chameleon_skin.dm b/code/game/gamemodes/changeling/powers/chameleon_skin.dm
index 1f18f628a8..3be5103105 100644
--- a/code/game/gamemodes/changeling/powers/chameleon_skin.dm
+++ b/code/game/gamemodes/changeling/powers/chameleon_skin.dm
@@ -5,9 +5,6 @@
dna_cost = 2
chemical_cost = 25
req_human = 1
- genetic_damage = 10
- max_genetic_damage = 50
-
/obj/effect/proc_holder/changeling/chameleon_skin/sting_action(mob/user)
var/mob/living/carbon/human/H = user //SHOULD always be human, because req_human = 1
diff --git a/code/game/gamemodes/changeling/powers/fakedeath.dm b/code/game/gamemodes/changeling/powers/fakedeath.dm
index 798f8030e0..e35f04d9e7 100644
--- a/code/game/gamemodes/changeling/powers/fakedeath.dm
+++ b/code/game/gamemodes/changeling/powers/fakedeath.dm
@@ -5,8 +5,6 @@
dna_cost = 0
req_dna = 1
req_stat = DEAD
- max_genetic_damage = 100
-
//Fake our own death and fully heal. You will appear to be dead but regenerate fully after a short delay.
/obj/effect/proc_holder/changeling/fakedeath/sting_action(mob/living/user)
diff --git a/code/game/gamemodes/changeling/powers/humanform.dm b/code/game/gamemodes/changeling/powers/humanform.dm
index 743dbc91e9..d92e622c2d 100644
--- a/code/game/gamemodes/changeling/powers/humanform.dm
+++ b/code/game/gamemodes/changeling/powers/humanform.dm
@@ -2,10 +2,7 @@
name = "Human Form"
desc = "We change into a human."
chemical_cost = 5
- genetic_damage = 3
req_dna = 1
- max_genetic_damage = 3
-
//Transform into a human.
/obj/effect/proc_holder/changeling/humanform/sting_action(mob/living/carbon/user)
diff --git a/code/game/gamemodes/changeling/powers/lesserform.dm b/code/game/gamemodes/changeling/powers/lesserform.dm
index 538803de00..06824f9bed 100644
--- a/code/game/gamemodes/changeling/powers/lesserform.dm
+++ b/code/game/gamemodes/changeling/powers/lesserform.dm
@@ -3,7 +3,6 @@
desc = "We debase ourselves and become lesser. We become a monkey."
chemical_cost = 5
dna_cost = 1
- genetic_damage = 3
req_human = 1
//Transform into a monkey.
diff --git a/code/game/gamemodes/changeling/powers/linglink.dm b/code/game/gamemodes/changeling/powers/linglink.dm
index fc4b91b650..232774c937 100644
--- a/code/game/gamemodes/changeling/powers/linglink.dm
+++ b/code/game/gamemodes/changeling/powers/linglink.dm
@@ -4,7 +4,6 @@
chemical_cost = 0
dna_cost = 0
req_human = 1
- max_genetic_damage = 100
/obj/effect/proc_holder/changeling/linglink/can_sting(mob/living/carbon/user)
if(!..())
diff --git a/code/game/gamemodes/changeling/powers/mutations.dm b/code/game/gamemodes/changeling/powers/mutations.dm
index 54e8ea1e38..aef9b6f1d2 100644
--- a/code/game/gamemodes/changeling/powers/mutations.dm
+++ b/code/game/gamemodes/changeling/powers/mutations.dm
@@ -16,7 +16,6 @@
helptext = "Yell at Miauw and/or Perakp"
chemical_cost = 1000
dna_cost = -1
- genetic_damage = 1000
var/silent = FALSE
var/weapon_type
@@ -67,7 +66,6 @@
helptext = "Yell at Miauw and/or Perakp"
chemical_cost = 1000
dna_cost = -1
- genetic_damage = 1000
var/helmet_type = /obj/item
var/suit_type = /obj/item
@@ -89,7 +87,7 @@
return 1
var/mob/living/carbon/human/H = user
if(istype(H.wear_suit, suit_type) || istype(H.head, helmet_type))
- H.visible_message("[H] casts off their [suit_name_simple]!", "We cast off our [suit_name_simple][genetic_damage > 0 ? ", temporarily weakening our genomes." : "."]", "You hear the organic matter ripping and tearing!")
+ H.visible_message("[H] casts off their [suit_name_simple]!", "We cast off our [suit_name_simple].", "You hear the organic matter ripping and tearing!")
H.temporarilyRemoveItemFromInventory(H.head, TRUE) //The qdel on dropped() takes care of it
H.temporarilyRemoveItemFromInventory(H.wear_suit, TRUE)
H.update_inv_wear_suit()
@@ -100,7 +98,6 @@
H.add_splatter_floor()
playsound(H.loc, 'sound/effects/splat.ogg', 50, 1) //So real sounds
- changeling.geneticdamage += genetic_damage //Casting off a space suit leaves you weak for a few seconds.
changeling.chem_recharge_slowdown -= recharge_slowdown
return 1
@@ -139,9 +136,7 @@
helptext = "We may retract our armblade in the same manner as we form it. Cannot be used while in lesser form."
chemical_cost = 20
dna_cost = 2
- genetic_damage = 10
req_human = 1
- max_genetic_damage = 20
weapon_type = /obj/item/weapon/melee/arm_blade
weapon_name_simple = "blade"
@@ -217,9 +212,7 @@
and Harm will stun it, and stab it if we're also holding a sharp weapon. Cannot be used while in lesser form."
chemical_cost = 10
dna_cost = 2
- genetic_damage = 5
req_human = 1
- max_genetic_damage = 10
weapon_type = /obj/item/weapon/gun/magic/tentacle
weapon_name_simple = "tentacle"
silent = TRUE
@@ -381,9 +374,7 @@
helptext = "Organic tissue cannot resist damage forever; the shield will break after it is hit too much. The more genomes we absorb, the stronger it is. Cannot be used while in lesser form."
chemical_cost = 20
dna_cost = 1
- genetic_damage = 12
req_human = 1
- max_genetic_damage = 20
weapon_type = /obj/item/weapon/shield/changeling
weapon_name_simple = "shield"
@@ -430,12 +421,10 @@
/obj/effect/proc_holder/changeling/suit/organic_space_suit
name = "Organic Space Suit"
desc = "We grow an organic suit to protect ourselves from space exposure."
- helptext = "We must constantly repair our form to make it space-proof, reducing chemical production while we are protected. Retreating the suit damages our genomes. Cannot be used in lesser form."
+ helptext = "We must constantly repair our form to make it space-proof, reducing chemical production while we are protected. Cannot be used in lesser form."
chemical_cost = 20
dna_cost = 2
- genetic_damage = 8
req_human = 1
- max_genetic_damage = 20
suit_type = /obj/item/clothing/suit/space/changeling
helmet_type = /obj/item/clothing/head/helmet/space/changeling
@@ -477,12 +466,10 @@
/obj/effect/proc_holder/changeling/suit/armor
name = "Chitinous Armor"
desc = "We turn our skin into tough chitin to protect us from damage."
- helptext = "Upkeep of the armor requires a low expenditure of chemicals. The armor is strong against brute force, but does not provide much protection from lasers. Retreating the armor damages our genomes. Cannot be used in lesser form."
+ helptext = "Upkeep of the armor requires a low expenditure of chemicals. The armor is strong against brute force, but does not provide much protection from lasers. Cannot be used in lesser form."
chemical_cost = 20
dna_cost = 1
- genetic_damage = 11
req_human = 1
- max_genetic_damage = 20
recharge_slowdown = 0.25
suit_type = /obj/item/clothing/suit/armor/changeling
diff --git a/code/game/gamemodes/changeling/powers/tiny_prick.dm b/code/game/gamemodes/changeling/powers/tiny_prick.dm
index c44a32c24d..ad6bf81e7c 100644
--- a/code/game/gamemodes/changeling/powers/tiny_prick.dm
+++ b/code/game/gamemodes/changeling/powers/tiny_prick.dm
@@ -40,10 +40,9 @@
return
if(!AStar(user, target.loc, /turf/proc/Distance, user.mind.changeling.sting_range, simulated_only = 0))
return
- if(target.mind && target.mind.changeling)
- sting_feedback(user,target)
- take_chemical_cost(user.mind.changeling)
- return
+ if(target.mind && target.mind.changeling)
+ sting_feedback(user, target)
+ user.mind.changeling.chem_charges -= chemical_cost
return 1
/obj/effect/proc_holder/changeling/sting/sting_feedback(mob/user, mob/target)
@@ -62,7 +61,6 @@
sting_icon = "sting_transform"
chemical_cost = 40
dna_cost = 3
- genetic_damage = 100
var/datum/changelingprofile/selected_dna = null
/obj/effect/proc_holder/changeling/sting/transformation/Click()
@@ -117,8 +115,6 @@
sting_icon = "sting_armblade"
chemical_cost = 20
dna_cost = 1
- genetic_damage = 20
- max_genetic_damage = 10
/obj/item/weapon/melee/arm_blade/false
desc = "A grotesque mass of flesh that used to be your arm. Although it looks dangerous at first, you can tell it's actually quite dull and useless."
diff --git a/code/game/gamemodes/changeling/powers/transform.dm b/code/game/gamemodes/changeling/powers/transform.dm
index f9aca83d04..9d0b095cc2 100644
--- a/code/game/gamemodes/changeling/powers/transform.dm
+++ b/code/game/gamemodes/changeling/powers/transform.dm
@@ -5,7 +5,6 @@
dna_cost = 0
req_dna = 1
req_human = 1
- max_genetic_damage = 3
/obj/item/clothing/glasses/changeling
name = "flesh"
diff --git a/code/game/gamemodes/clock_cult/clock_effects/clock_sigils.dm b/code/game/gamemodes/clock_cult/clock_effects/clock_sigils.dm
index 6c56295c05..cf709f09b0 100644
--- a/code/game/gamemodes/clock_cult/clock_effects/clock_sigils.dm
+++ b/code/game/gamemodes/clock_cult/clock_effects/clock_sigils.dm
@@ -54,8 +54,11 @@
clockwork_desc = "A sigil that will stun the next non-Servant to cross it."
icon_state = "sigildull"
layer = HIGH_SIGIL_LAYER
- alpha = 60
+ alpha = 75
color = "#FAE48C"
+ light_range = 1.4
+ light_power = 1
+ light_color = "#FAE48C"
sigil_name = "Sigil of Transgression"
/obj/effect/clockwork/sigil/transgression/sigil_effects(mob/living/L)
@@ -93,10 +96,6 @@
sigil_name = "Sigil of Submission"
var/glow_type
-/obj/effect/clockwork/sigil/submission/New()
- ..()
- update_light()
-
/obj/effect/clockwork/sigil/submission/proc/post_channel(mob/living/L)
/obj/effect/clockwork/sigil/submission/sigil_effects(mob/living/L)
@@ -202,6 +201,21 @@
and [structure_number] Clockwork Structure[structure_number == 1 ? "":"s"] [structure_number == 1 ? "is":"are"] in range.")
if(iscyborg(user))
to_chat(user, "You can recharge from the [sigil_name] by crossing it.")
+ else if(!GLOB.ratvar_awakens)
+ to_chat(user, "Hitting the [sigil_name] with brass sheets will convert them to power at a rate of 1 brass sheet to [POWER_FLOOR]W power.")
+ if(!GLOB.ratvar_awakens)
+ to_chat(user, "You can recharge Clockwork Proselytizers from the [sigil_name].")
+
+/obj/effect/clockwork/sigil/transmission/attackby(obj/item/I, mob/living/user, params)
+ if(is_servant_of_ratvar(user) && istype(I, /obj/item/stack/tile/brass) && !GLOB.ratvar_awakens)
+ var/obj/item/stack/tile/brass/B = I
+ user.visible_message("[user] places [B] on [src], causing it to disintegrate into glowing orange energy!", \
+ "You charge the [sigil_name] with [B], providing it with [B.amount * POWER_FLOOR]W of power.")
+ modify_charge(-(B.amount * POWER_FLOOR))
+ playsound(src, 'sound/effects/light_flicker.ogg', (B.amount * POWER_FLOOR) * 0.01, 1)
+ qdel(B)
+ return TRUE
+ return ..()
/obj/effect/clockwork/sigil/transmission/sigil_effects(mob/living/L)
if(is_servant_of_ratvar(L))
@@ -214,9 +228,7 @@
if(!cyborg_checks(cyborg))
return
to_chat(cyborg, "You start to charge from the [sigil_name]...")
- if(!do_after(cyborg, 50, target = src))
- return
- if(!cyborg_checks(cyborg))
+ if(!do_after(cyborg, 50, target = src, extra_checks = CALLBACK(src, .proc/cyborg_checks, cyborg, TRUE)))
return
var/giving_power = min(Floor(cyborg.cell.maxcharge - cyborg.cell.charge, MIN_CLOCKCULT_POWER), power_charge) //give the borg either all our power or their missing power floored to MIN_CLOCKCULT_POWER
if(modify_charge(giving_power))
@@ -228,23 +240,27 @@
animate(cyborg, color = previous_color, time = 100)
addtimer(CALLBACK(cyborg, /atom/proc/update_atom_colour), 100)
-/obj/effect/clockwork/sigil/transmission/proc/cyborg_checks(mob/living/silicon/robot/cyborg)
+/obj/effect/clockwork/sigil/transmission/proc/cyborg_checks(mob/living/silicon/robot/cyborg, silent)
if(!cyborg.cell)
- to_chat(cyborg, "You have no cell!")
+ if(!silent)
+ to_chat(cyborg, "You have no cell!")
return FALSE
if(!power_charge)
- to_chat(cyborg, "The [sigil_name] has no stored power!")
+ if(!silent)
+ to_chat(cyborg, "The [sigil_name] has no stored power!")
return FALSE
if(cyborg.cell.charge > cyborg.cell.maxcharge - MIN_CLOCKCULT_POWER)
- to_chat(cyborg, "You are already at maximum charge!")
+ if(!silent)
+ to_chat(cyborg, "You are already at maximum charge!")
return FALSE
if(cyborg.has_status_effect(STATUS_EFFECT_POWERREGEN))
- to_chat(cyborg, "You are already regenerating power!")
+ if(!silent)
+ to_chat(cyborg, "You are already regenerating power!")
return FALSE
return TRUE
-/obj/effect/clockwork/sigil/transmission/New()
- ..()
+/obj/effect/clockwork/sigil/transmission/Initialize()
+ . = ..()
update_glow()
/obj/effect/clockwork/sigil/transmission/proc/modify_charge(amount)
@@ -265,7 +281,7 @@
if(!power_charge)
set_light(0)
else
- set_light(round(alpha*0.02, 1), round(alpha*0.005, 1))
+ set_light(max(alpha*0.02, 1.4), max(alpha*0.01, 0.1))
//Vitality Matrix: Drains health from non-servants to heal or even revive servants.
/obj/effect/clockwork/sigil/vitality
@@ -299,8 +315,7 @@
if((is_servant_of_ratvar(L) && L.suiciding) || sigil_active)
return
visible_message("[src] begins to glow bright blue!")
- animate(src, alpha = 255, time = 10)
- addtimer(CALLBACK(src, .proc/update_alpha), 10)
+ animate(src, alpha = 255, time = 10, flags = ANIMATION_END_NOW) //we may have a previous animation going. finish it first, then do this one without delay.
sleep(10)
//as long as they're still on the sigil and are either not a servant or they're a servant AND it has remaining vitality
while(L && (!is_servant_of_ratvar(L) || (is_servant_of_ratvar(L) && (GLOB.ratvar_awakens || vitality))) && get_turf(L) == get_turf(src))
@@ -369,12 +384,4 @@
animation_number = initial(animation_number)
sigil_active = FALSE
visible_message("[src] slowly stops glowing!")
- if(sigil_active || alpha == 255)
- animate(src, alpha = initial(alpha), time = 10)
- addtimer(CALLBACK(src, .proc/update_alpha), 10)
-
-/obj/effect/clockwork/sigil/vitality/proc/update_alpha()
- if(sigil_active)
- alpha = 255
- else
- alpha = initial(alpha)
+ animate(src, alpha = initial(alpha), time = 10, flags = ANIMATION_END_NOW)
diff --git a/code/game/gamemodes/clock_cult/clock_effects/spatial_gateway.dm b/code/game/gamemodes/clock_cult/clock_effects/spatial_gateway.dm
index 1c49d36693..5c1d3fb5fb 100644
--- a/code/game/gamemodes/clock_cult/clock_effects/spatial_gateway.dm
+++ b/code/game/gamemodes/clock_cult/clock_effects/spatial_gateway.dm
@@ -180,17 +180,26 @@
return procure_gateway(invoker, time_duration, gateway_uses, two_way)
var/istargetobelisk = istype(target, /obj/structure/destructible/clockwork/powered/clockwork_obelisk)
var/issrcobelisk = istype(src, /obj/structure/destructible/clockwork/powered/clockwork_obelisk)
- if(issrcobelisk && !anchored)
- to_chat(invoker, "[src] is no longer secured!")
- return FALSE
+ if(issrcobelisk)
+ if(!anchored)
+ to_chat(invoker, "[src] is no longer secured!")
+ return FALSE
+ var/obj/structure/destructible/clockwork/powered/clockwork_obelisk/CO = src //foolish as I am, how I set this proc up makes substypes unfeasible
+ if(CO.active)
+ to_chat(invoker, "[src] is now sustaining a gateway!")
+ return FALSE
if(istargetobelisk)
if(!target.anchored)
to_chat(invoker, "That [target.name] is no longer secured!")
return procure_gateway(invoker, time_duration, gateway_uses, two_way)
var/obj/structure/destructible/clockwork/powered/clockwork_obelisk/CO = target
+ if(CO.active)
+ to_chat(invoker, "That [target.name] is sustaining a gateway, and cannot recieve another!")
+ return procure_gateway(invoker, time_duration, gateway_uses, two_way)
var/efficiency = CO.get_efficiency_mod()
gateway_uses = round(gateway_uses * (2 * efficiency), 1)
time_duration = round(time_duration * (2 * efficiency), 1)
+ CO.active = TRUE //you'd be active in a second but you should update immediately
invoker.visible_message("The air in front of [invoker] ripples before suddenly tearing open!", \
"With a word, you rip open a [two_way ? "two-way":"one-way"] rift to [input_target_key]. It will last for [time_duration / 10] seconds and has [gateway_uses] use[gateway_uses > 1 ? "s" : ""].")
var/obj/effect/clockwork/spatial_gateway/S1 = new(issrcobelisk ? get_turf(src) : get_step(get_turf(invoker), invoker.dir))
diff --git a/code/game/gamemodes/clock_cult/clock_helpers/proselytizer_helpers.dm b/code/game/gamemodes/clock_cult/clock_helpers/proselytizer_helpers.dm
index c6954bb67e..529f38d832 100644
--- a/code/game/gamemodes/clock_cult/clock_helpers/proselytizer_helpers.dm
+++ b/code/game/gamemodes/clock_cult/clock_helpers/proselytizer_helpers.dm
@@ -286,6 +286,28 @@
user.visible_message("[user]'s [proselytizer.name] stops covering [src] with glowing orange energy.", \
"You finish repairing [src]. It is now at [obj_integrity]/[max_integrity] integrity.")
+//Hitting a sigil of transmission will try to charge from it.
+/obj/effect/clockwork/sigil/transmission/proselytize_vals(mob/living/user, obj/item/clockwork/clockwork_proselytizer/proselytizer)
+ . = TRUE
+ var/list/charge_values = list()
+ if(!proselytizer.sigil_charge_checks(charge_values, src, user))
+ return
+ user.visible_message("[user]'s [proselytizer.name] starts draining glowing orange energy from [src]...", \
+ "You start recharging your [proselytizer.name]...")
+ proselytizer.recharging = src
+ while(proselytizer && user && src)
+ if(!do_after(user, 10, target = src, extra_checks = CALLBACK(proselytizer, /obj/item/clockwork/clockwork_proselytizer.proc/sigil_charge_checks, charge_values, src, user, TRUE)))
+ break
+ modify_charge(charge_values["power_gain"])
+ proselytizer.modify_stored_power(charge_values["power_gain"])
+ playsound(src, 'sound/effects/light_flicker.ogg', charge_values["power_gain"] * 0.1, 1)
+
+ if(proselytizer)
+ proselytizer.recharging = null
+ if(user)
+ user.visible_message("[user]'s [proselytizer.name] stops draining glowing orange energy from [src].", \
+ "You finish recharging your [proselytizer.name]. It now contains [proselytizer.get_power()]W/[proselytizer.get_max_power()]W power.")
+
//Proselytizer mob heal proc, to avoid as much copypaste as possible.
/mob/living/proc/proselytizer_heal(mob/living/user, obj/item/clockwork/clockwork_proselytizer/proselytizer)
var/list/repair_values = list()
diff --git a/code/game/gamemodes/clock_cult/clock_items/clockwork_proselytizer.dm b/code/game/gamemodes/clock_cult/clock_items/clockwork_proselytizer.dm
index 25e2138b81..60df56b6ef 100644
--- a/code/game/gamemodes/clock_cult/clock_items/clockwork_proselytizer.dm
+++ b/code/game/gamemodes/clock_cult/clock_items/clockwork_proselytizer.dm
@@ -12,6 +12,7 @@
var/uses_power = TRUE
var/metal_to_power = FALSE
var/repairing = null //what we're currently repairing, if anything
+ var/obj/effect/clockwork/sigil/transmission/recharging = null //the sigil we're charging from, if any
var/speed_multiplier = 1 //how fast this proselytizer works
var/charge_rate = MIN_CLOCKCULT_POWER //how much power we gain every two seconds
var/charge_delay = 2 //how many proccess ticks remain before we can start to charge
@@ -140,10 +141,11 @@
/obj/item/clockwork/clockwork_proselytizer/attack_self(mob/living/user)
if(is_servant_of_ratvar(user))
- if(!can_use_power(POWER_WALL_TOTAL))
- to_chat(user, "[src] requires [POWER_WALL_TOTAL]W of power to produce brass sheets!")
- return
- modify_stored_power(-POWER_WALL_TOTAL)
+ if(uses_power)
+ if(!can_use_power(POWER_WALL_TOTAL))
+ to_chat(user, "[src] requires [POWER_WALL_TOTAL]W of power to produce brass sheets!")
+ return
+ modify_stored_power(-POWER_WALL_TOTAL)
playsound(src, 'sound/items/Deconstruct.ogg', 50, 1)
new/obj/item/stack/tile/brass(user.loc, 5)
to_chat(user, "You user [stored_power ? "some":"all"] of [src]'s power to produce some brass sheets. It now stores [get_power()]W/[get_max_power()]W of power.")
@@ -182,6 +184,9 @@
if(repairing)
to_chat(user, "You are currently repairing [repairing] with [src]!")
return FALSE
+ if(recharging)
+ to_chat(user, "You are currently recharging [src] from the [recharging.sigil_name]!")
+ return FALSE
var/list/proselytize_values = target.proselytize_vals(user, src) //relevant values for proselytizing stuff, given as an associated list
if(!islist(proselytize_values))
if(proselytize_values != TRUE) //if we get true, fail, but don't send a message for whatever reason
@@ -237,7 +242,7 @@
/obj/item/clockwork/clockwork_proselytizer/proc/proselytize_checks(list/proselytize_values, atom/target, expected_type, mob/user, silent) //checked constantly while proselytizing
if(!islist(proselytize_values) || !target || QDELETED(target) || !user)
return FALSE
- if(repairing)
+ if(repairing || recharging)
return FALSE
if(target.type != expected_type)
return FALSE
@@ -296,3 +301,20 @@
[round(repair_values["amount_to_heal"]*MIN_CLOCKCULT_POWER, MIN_CLOCKCULT_POWER)]W to fully repair [target == user ? "yourself" : "[target.p_them()]"]!")
return FALSE
return TRUE
+
+//checked constantly while charging from a sigil
+/obj/item/clockwork/clockwork_proselytizer/proc/sigil_charge_checks(list/charge_values, obj/effect/clockwork/sigil/transmission/sigil, mob/user, silent)
+ if(!islist(charge_values) || !sigil || QDELETED(sigil) || !user)
+ return FALSE
+ if(can_use_power(RATVAR_POWER_CHECK))
+ return FALSE
+ charge_values["power_gain"] = Clamp(sigil.power_charge, 0, POWER_WALL_MINUS_FLOOR)
+ if(!charge_values["power_gain"])
+ if(!silent)
+ to_chat(user, "The [sigil.sigil_name] contains no power!")
+ return FALSE
+ if(stored_power + charge_values["power_gain"] > max_power)
+ if(!silent)
+ to_chat(user, "Your [name] contains too much power to charge from the [sigil.sigil_name]!")
+ return FALSE
+ return TRUE
diff --git a/code/game/gamemodes/clock_cult/clock_items/clockwork_slab.dm b/code/game/gamemodes/clock_cult/clock_items/clockwork_slab.dm
index 35caabab5a..8b3aa01533 100644
--- a/code/game/gamemodes/clock_cult/clock_items/clockwork_slab.dm
+++ b/code/game/gamemodes/clock_cult/clock_items/clockwork_slab.dm
@@ -326,13 +326,19 @@
if(production_time != SLAB_PRODUCTION_TIME+SLAB_SLOWDOWN_MAXIMUM)
production_text_addon = ", which increases for each human or silicon servant above [SCRIPT_SERVANT_REQ]"
production_time = production_time/600
- var/production_text = "[round(production_time)] minute\s"
+ var/list/production_text
+ if(round(production_time))
+ production_text = list("[round(production_time)] minute\s")
if(production_time != round(production_time))
production_time -= round(production_time)
production_time *= 60
- production_text += " and [round(production_time, 1)] second\s"
+ if(!LAZYLEN(production_text))
+ production_text = list("[round(production_time, 1)] second\s")
+ else
+ production_text += " and [round(production_time, 1)] second\s"
production_text += ""
production_text += production_text_addon
+ production_text = production_text.Join()
textlist = list("
Chetr nyy hagehguf-naq-ubabe Ratvar.
\
\
diff --git a/code/game/gamemodes/clock_cult/clock_scriptures/scripture_applications.dm b/code/game/gamemodes/clock_cult/clock_scriptures/scripture_applications.dm
index 25576f5710..c1b5c0cfff 100644
--- a/code/game/gamemodes/clock_cult/clock_scriptures/scripture_applications.dm
+++ b/code/game/gamemodes/clock_cult/clock_scriptures/scripture_applications.dm
@@ -10,7 +10,7 @@
It will penetrate mindshield implants once before disappearing."
invocations = list("Divinity, enslave...", "...all who trespass here!")
channel_time = 70
- consumed_components = list(BELLIGERENT_EYE = 2, GEIS_CAPACITOR = 1, HIEROPHANT_ANSIBLE = 1)
+ consumed_components = list(BELLIGERENT_EYE = 4, GEIS_CAPACITOR = 2, HIEROPHANT_ANSIBLE = 2)
whispered = TRUE
object_path = /obj/effect/clockwork/sigil/submission/accession
prevent_path = /obj/effect/clockwork/sigil/submission
@@ -32,7 +32,7 @@
It grows faster to invoke with more adjacent Servants."
invocations = list("Shield us...", "...with the...", "... fragments of Engine!")
channel_time = 100
- consumed_components = list(VANGUARD_COGWHEEL = 2, REPLICANT_ALLOY = 1, HIEROPHANT_ANSIBLE = 1)
+ consumed_components = list(VANGUARD_COGWHEEL = 4, REPLICANT_ALLOY = 2, HIEROPHANT_ANSIBLE = 2)
usage_tip = "This scripture will replace all weaker armor worn by affected Servants."
tier = SCRIPTURE_APPLICATION
multiple_invokers_used = TRUE
@@ -99,7 +99,7 @@
If it remains close to you, you will gradually regain health up to a low amount, but it will die if it goes too far from you."
invocations = list("Fright's will...", "...call forth...")
channel_time = 100
- consumed_components = list(BELLIGERENT_EYE = 1, VANGUARD_COGWHEEL = 1, GEIS_CAPACITOR = 2)
+ consumed_components = list(BELLIGERENT_EYE = 2, VANGUARD_COGWHEEL = 2, GEIS_CAPACITOR = 4)
usage_tip = "Marauders are useful as personal bodyguards and frontline warriors."
tier = SCRIPTURE_APPLICATION
primary_component = GEIS_CAPACITOR
@@ -160,7 +160,7 @@
and exceptional speed, though taking damage will temporarily slow it down."
invocations = list("Call forth...", "...the soldiers of Armorer.")
channel_time = 80
- consumed_components = list(BELLIGERENT_EYE = 1, VANGUARD_COGWHEEL = 1, REPLICANT_ALLOY = 2)
+ consumed_components = list(BELLIGERENT_EYE = 2, VANGUARD_COGWHEEL = 2, REPLICANT_ALLOY = 4)
object_path = /obj/structure/destructible/clockwork/shell/fragment
creator_message = "You form an anima fragment, a powerful soul vessel receptacle."
observer_message = "The slab disgorges a puddle of black metal that expands and forms into a strange shell!"
@@ -179,7 +179,7 @@
desc = "Places a sigil that stores energy to power clockwork structures."
invocations = list("Divinity...", "...power our creations!")
channel_time = 70
- consumed_components = list(VANGUARD_COGWHEEL = 1, GEIS_CAPACITOR = 1, HIEROPHANT_ANSIBLE = 2)
+ consumed_components = list(VANGUARD_COGWHEEL = 2, GEIS_CAPACITOR = 2, HIEROPHANT_ANSIBLE = 4)
whispered = TRUE
object_path = /obj/effect/clockwork/sigil/transmission
creator_message = "A sigil silently appears below you. It will automatically power clockwork structures near it."
@@ -199,7 +199,7 @@
desc = "Creates a clockwork totem that sabotages nearby machinery and funnels drained power into nearby Sigils of Transmission or the area's APC."
invocations = list("May this totem...", "...shroud the false suns!")
channel_time = 80
- consumed_components = list(BELLIGERENT_EYE = 3, REPLICANT_ALLOY = 1, HIEROPHANT_ANSIBLE = 1)
+ consumed_components = list(BELLIGERENT_EYE = 5, REPLICANT_ALLOY = 2, HIEROPHANT_ANSIBLE = 2)
object_path = /obj/structure/destructible/clockwork/powered/interdiction_lens
creator_message = "You form an interdiction lens, which disrupts cameras and radios and drains power."
observer_message = "A brass totem rises from the ground, a purple gem appearing in its center!"
@@ -221,7 +221,7 @@
desc = "Creates a mania motor which will cause brain damage and hallucinations in nearby non-Servant humans. It will also try to convert humans directly adjecent to the motor."
invocations = list("May this transmitter...", "...break the will of all who oppose us!")
channel_time = 80
- consumed_components = list(GEIS_CAPACITOR = 3, REPLICANT_ALLOY = 1, HIEROPHANT_ANSIBLE = 1)
+ consumed_components = list(GEIS_CAPACITOR = 5, REPLICANT_ALLOY = 2, HIEROPHANT_ANSIBLE = 2)
object_path = /obj/structure/destructible/clockwork/powered/mania_motor
creator_message = "You form a mania motor which will cause brain damage and hallucinations in nearby humans while active."
observer_message = "A two-pronged machine rises from the ground!"
@@ -244,7 +244,7 @@
and there is at least one existing cache."
invocations = list("May this generator...", "...collect Engine parts that yet hold greatness!")
channel_time = 80
- consumed_components = list(BELLIGERENT_EYE = 1, GEIS_CAPACITOR = 1, REPLICANT_ALLOY = 3)
+ consumed_components = list(BELLIGERENT_EYE = 2, GEIS_CAPACITOR = 2, REPLICANT_ALLOY = 5)
object_path = /obj/structure/destructible/clockwork/powered/tinkerers_daemon
creator_message = "You form a tinkerer's daemon which can rapidly collect components at a power cost."
invokers_required = 2
@@ -278,7 +278,7 @@
desc = "Creates a clockwork obelisk that can broadcast messages over the Hierophant Network or open a Spatial Gateway to any living Servant or clockwork obelisk."
invocations = list("May this obelisk...", "...take us to all places!")
channel_time = 80
- consumed_components = list(BELLIGERENT_EYE = 1, VANGUARD_COGWHEEL = 1, HIEROPHANT_ANSIBLE = 3)
+ consumed_components = list(BELLIGERENT_EYE = 2, VANGUARD_COGWHEEL = 2, HIEROPHANT_ANSIBLE = 5)
object_path = /obj/structure/destructible/clockwork/powered/clockwork_obelisk
creator_message = "You form a clockwork obelisk which can broadcast messages or produce Spatial Gateways."
observer_message = "A brass obelisk appears hanging in midair!"
diff --git a/code/game/gamemodes/clock_cult/clock_scriptures/scripture_drivers.dm b/code/game/gamemodes/clock_cult/clock_scriptures/scripture_drivers.dm
index 023cd50dd1..f246034884 100644
--- a/code/game/gamemodes/clock_cult/clock_scriptures/scripture_drivers.dm
+++ b/code/game/gamemodes/clock_cult/clock_scriptures/scripture_drivers.dm
@@ -272,7 +272,7 @@
var/static/prev_cost = 0
/datum/clockwork_scripture/create_object/tinkerers_cache/creation_update()
- var/cache_cost_increase = min(round(GLOB.clockwork_caches*0.25), 5)
+ var/cache_cost_increase = min(round(GLOB.clockwork_caches*0.4), 10)
if(cache_cost_increase != prev_cost)
prev_cost = cache_cost_increase
consumed_components = list(BELLIGERENT_EYE = 0, VANGUARD_COGWHEEL = 0, GEIS_CAPACITOR = 0, REPLICANT_ALLOY = 1, HIEROPHANT_ANSIBLE = 0)
diff --git a/code/game/gamemodes/clock_cult/clock_scriptures/scripture_revenant.dm b/code/game/gamemodes/clock_cult/clock_scriptures/scripture_revenant.dm
index 0dbd2d46e8..25bedd79d3 100644
--- a/code/game/gamemodes/clock_cult/clock_scriptures/scripture_revenant.dm
+++ b/code/game/gamemodes/clock_cult/clock_scriptures/scripture_revenant.dm
@@ -9,7 +9,7 @@
desc = "Taps the limitless power of Inath-neq, one of Ratvar's four generals. The benevolence of Inath-Neq will grant complete invulnerability to all Servants in range for fifteen seconds."
invocations = list("I call upon you, Vanguard!!", "Let the Resonant Cogs turn once more!!", "Grant me and my allies the strength to vanquish our foes!!")
channel_time = 100
- consumed_components = list(VANGUARD_COGWHEEL = 4, GEIS_CAPACITOR = 2, REPLICANT_ALLOY = 2, HIEROPHANT_ANSIBLE = 2)
+ consumed_components = list(VANGUARD_COGWHEEL = 10, GEIS_CAPACITOR = 3, REPLICANT_ALLOY = 3, HIEROPHANT_ANSIBLE = 3)
usage_tip = "Servants affected by this scripture are only weak to things that outright destroy bodies, such as bombs or the singularity."
tier = SCRIPTURE_REVENANT
primary_component = VANGUARD_COGWHEEL
@@ -44,7 +44,7 @@
for all non-servant humans on the same z-level as them. The power of this scripture falls off somewhat with distance, and certain things may reduce its effects."
invocations = list("I call upon you, Fright!!", "Let your power shatter the sanity of the weak-minded!!", "Let your tendrils hold sway over all!!")
channel_time = 150
- consumed_components = list(BELLIGERENT_EYE = 3, VANGUARD_COGWHEEL = 3, GEIS_CAPACITOR = 6, HIEROPHANT_ANSIBLE = 3)
+ consumed_components = list(BELLIGERENT_EYE = 6, VANGUARD_COGWHEEL = 6, GEIS_CAPACITOR = 10, HIEROPHANT_ANSIBLE = 6)
usage_tip = "Causes brain damage, hallucinations, confusion, and dizziness in massive amounts."
tier = SCRIPTURE_REVENANT
sort_priority = 3
@@ -108,7 +108,7 @@
clockwork proselytizers will charge very rapidly."
invocations = list("I call upon you, Armorer!!", "Let your machinations reign on this miserable station!!", "Let your power flow through the tools of your master!!")
channel_time = 150
- consumed_components = list(BELLIGERENT_EYE = 3, VANGUARD_COGWHEEL = 3, GEIS_CAPACITOR = 3, REPLICANT_ALLOY = 6)
+ consumed_components = list(BELLIGERENT_EYE = 6, VANGUARD_COGWHEEL = 6, GEIS_CAPACITOR = 6, REPLICANT_ALLOY = 10)
usage_tip = "Ocular wardens will become empowered, clockwork proselytizers will require no alloy, tinkerer's daemons will produce twice as quickly, \
and interdiction lenses, mania motors, tinkerer's daemons, and clockwork obelisks will all require no power."
tier = SCRIPTURE_REVENANT
@@ -153,7 +153,7 @@
will be struck by devastating lightning bolts."
invocations = list("I call upon you, Amperage!!", "Let your energy flow through me!!", "Let your boundless power shatter stars!!")
channel_time = 100
- consumed_components = list(BELLIGERENT_EYE = 2, GEIS_CAPACITOR = 2, REPLICANT_ALLOY = 2, HIEROPHANT_ANSIBLE = 4)
+ consumed_components = list(BELLIGERENT_EYE = 3, GEIS_CAPACITOR = 3, REPLICANT_ALLOY = 3, HIEROPHANT_ANSIBLE = 10)
usage_tip = "Struck targets will also be knocked down for about sixteen seconds."
tier = SCRIPTURE_REVENANT
primary_component = HIEROPHANT_ANSIBLE
diff --git a/code/game/gamemodes/clock_cult/clock_scriptures/scripture_scripts.dm b/code/game/gamemodes/clock_cult/clock_scriptures/scripture_scripts.dm
index f7fcc8c299..bc5ec1b9d8 100644
--- a/code/game/gamemodes/clock_cult/clock_scriptures/scripture_scripts.dm
+++ b/code/game/gamemodes/clock_cult/clock_scriptures/scripture_scripts.dm
@@ -9,7 +9,7 @@
desc = "Forms an automatic short-range turret which will automatically attack nearby unrestrained non-Servants that can see it."
invocations = list("Guardians...", "...of the Engine...", "...defend us!")
channel_time = 120
- consumed_components = list(BELLIGERENT_EYE = 1, REPLICANT_ALLOY = 1)
+ consumed_components = list(BELLIGERENT_EYE = 2, REPLICANT_ALLOY = 1)
object_path = /obj/structure/destructible/clockwork/ocular_warden
creator_message = "You form an ocular warden, which will automatically attack nearby unrestrained non-Servants that can see it."
observer_message = "A brass eye takes shape and slowly rises into the air, its red iris glaring!"
@@ -36,7 +36,7 @@
desc = "Creates a small shell fitted for soul vessels. Adding an active soul vessel to it results in a small construct with tools and an inbuilt proselytizer."
invocations = list("Call forth...", "...the workers of Armorer.")
channel_time = 60
- consumed_components = list(BELLIGERENT_EYE = 1, HIEROPHANT_ANSIBLE = 1)
+ consumed_components = list(BELLIGERENT_EYE = 2, HIEROPHANT_ANSIBLE = 1)
object_path = /obj/structure/destructible/clockwork/shell/cogscarab
creator_message = "You form a cogscarab, a constructor soul vessel receptacle."
observer_message = "The slab disgorges a puddle of black metal that contracts and forms into a strange shell!"
@@ -56,7 +56,7 @@
Matrices have drained from non-Servants. Dead Servants can be revived by this sigil if there is vitality equal to the target Servant's non-oxygen damage."
invocations = list("Divinity...", "...steal their life...", "...for these shells!")
channel_time = 60
- consumed_components = list(BELLIGERENT_EYE = 1, VANGUARD_COGWHEEL = 1)
+ consumed_components = list(BELLIGERENT_EYE = 1, VANGUARD_COGWHEEL = 2)
whispered = TRUE
object_path = /obj/effect/clockwork/sigil/vitality
creator_message = "A vitality matrix appears below you. It will drain life from non-Servants and heal Servants that cross it."
@@ -77,7 +77,7 @@
chant_invocations = list("Mend our dents!", "Heal our scratches!", "Repair our gears!")
chant_amount = 10
chant_interval = 20
- consumed_components = list(VANGUARD_COGWHEEL = 1, REPLICANT_ALLOY = 1)
+ consumed_components = list(VANGUARD_COGWHEEL = 2, REPLICANT_ALLOY = 1)
usage_tip = "This is a very effective way to rapidly reinforce a base after an attack."
tier = SCRIPTURE_SCRIPT
primary_component = VANGUARD_COGWHEEL
@@ -177,6 +177,7 @@
new /obj/effect/overlay/temp/heal(T, "#1E8CE1")
else
break
+ new /obj/effect/overlay/temp/ratvar/mending_mantra(get_turf(invoker))
return TRUE
@@ -187,7 +188,7 @@
desc = "Places a luminous sigil that will enslave any valid beings standing on it after a time."
invocations = list("Divinity, enlighten...", "...those who trespass here!")
channel_time = 60
- consumed_components = list(BELLIGERENT_EYE = 1, GEIS_CAPACITOR = 1)
+ consumed_components = list(BELLIGERENT_EYE = 1, GEIS_CAPACITOR = 2)
whispered = TRUE
object_path = /obj/effect/clockwork/sigil/submission
creator_message = "A luminous sigil appears below you. The next non-servant to cross it will be enslaved after a brief time if they do not move."
@@ -207,7 +208,7 @@
desc = "Forms an ancient positronic brain with an overriding directive to serve Ratvar."
invocations = list("Herd the souls of...", "...the blasphemous damned!")
channel_time = 30
- consumed_components = list(VANGUARD_COGWHEEL = 1, GEIS_CAPACITOR = 1)
+ consumed_components = list(VANGUARD_COGWHEEL = 1, GEIS_CAPACITOR = 2)
whispered = TRUE
object_path = /obj/item/device/mmi/posibrain/soul_vessel
creator_message = "You form a soul vessel, which can be used in-hand to attract spirits, or used on an unconscious or dead human to extract their consciousness."
@@ -227,7 +228,7 @@
desc = "Forms a device that, when used on certain objects, converts them into their Ratvarian equivalents. It requires power to function."
invocations = list("With this device...", "...his presence shall be made known.")
channel_time = 20
- consumed_components = list(GEIS_CAPACITOR = 1, REPLICANT_ALLOY = 1)
+ consumed_components = list(GEIS_CAPACITOR = 1, REPLICANT_ALLOY = 2)
whispered = TRUE
object_path = /obj/item/clockwork/clockwork_proselytizer/preloaded
creator_message = "You form a clockwork proselytizer."
@@ -248,7 +249,7 @@
vanish three minutes after being summoned."
invocations = list("Grant me...", "...the might of brass!")
channel_time = 20
- consumed_components = list(REPLICANT_ALLOY = 1, HIEROPHANT_ANSIBLE = 1)
+ consumed_components = list(REPLICANT_ALLOY = 2, HIEROPHANT_ANSIBLE = 1)
whispered = TRUE
usage_tip = "You can impale human targets with the spear by pulling them, then attacking. Throwing the spear at a mob will do massive damage and stun them, but break the spear."
tier = SCRIPTURE_SCRIPT
@@ -307,7 +308,7 @@
Each servant assisting in the invocation adds one additional use and four additional seconds to the gateway's uses and duration."
invocations = list("Spatial Gateway...", "...activate!")
channel_time = 80
- consumed_components = list(VANGUARD_COGWHEEL = 1, HIEROPHANT_ANSIBLE = 1)
+ consumed_components = list(VANGUARD_COGWHEEL = 1, HIEROPHANT_ANSIBLE = 2)
multiple_invokers_used = TRUE
multiple_invokers_optional = TRUE
usage_tip = "This gateway is strictly one-way and will only allow things through the invoker's portal."
@@ -356,7 +357,7 @@
chant_invocations = list("Use charge to kill!", "Slay with power!", "Hunt with energy!")
chant_amount = 4
chant_interval = 5
- consumed_components = list(GEIS_CAPACITOR = 1, HIEROPHANT_ANSIBLE = 1)
+ consumed_components = list(GEIS_CAPACITOR = 1, HIEROPHANT_ANSIBLE = 2)
usage_tip = "Though it requires you to stand still, this scripture can do massive damage."
tier = SCRIPTURE_SCRIPT
primary_component = HIEROPHANT_ANSIBLE
diff --git a/code/game/gamemodes/clock_cult/clock_structures/clockwork_obelisk.dm b/code/game/gamemodes/clock_cult/clock_structures/clockwork_obelisk.dm
index 2bebb4c9a5..580f5fbed5 100644
--- a/code/game/gamemodes/clock_cult/clock_structures/clockwork_obelisk.dm
+++ b/code/game/gamemodes/clock_cult/clock_structures/clockwork_obelisk.dm
@@ -58,7 +58,7 @@
var/input = stripped_input(usr, "Please choose a message to send over the Hierophant Network.", "Hierophant Broadcast", "")
if(!is_servant_of_ratvar(user) || !input || !user.canUseTopic(src, !issilicon(user)))
return
- if(anchored)
+ if(!anchored)
to_chat(user, "[src] is no longer secured!")
return FALSE
if(active)
@@ -84,7 +84,8 @@
return
if(procure_gateway(user, round(100 * get_efficiency_mod(), 1), round(5 * get_efficiency_mod(), 1), 1))
process()
- if(!active)
+ if(!active) //we won't be active if nobody has sent a gateway to us
+ active = TRUE
clockwork_say(user, text2ratvar("Spatial Gateway, activate!"))
return
return_power(gateway_cost) //if we didn't return above, ie, successfully create a gateway, we give the power back
@@ -92,7 +93,8 @@
/obj/structure/destructible/clockwork/powered/clockwork_obelisk/process()
if(!anchored)
return
- if(locate(/obj/effect/clockwork/spatial_gateway) in loc)
+ var/obj/effect/clockwork/spatial_gateway/SG = locate(/obj/effect/clockwork/spatial_gateway)
+ if(SG && SG.timerid) //it's a valid gateway, we're active
icon_state = active_icon
density = 0
active = TRUE
diff --git a/code/game/gamemodes/clock_cult/clock_structures/ratvar_the_clockwork_justicar.dm b/code/game/gamemodes/clock_cult/clock_structures/ratvar_the_clockwork_justicar.dm
index 614a22a6f5..4beaf226d6 100644
--- a/code/game/gamemodes/clock_cult/clock_structures/ratvar_the_clockwork_justicar.dm
+++ b/code/game/gamemodes/clock_cult/clock_structures/ratvar_the_clockwork_justicar.dm
@@ -28,7 +28,7 @@
var/mutable_appearance/alert_overlay = mutable_appearance('icons/effects/clockwork_effects.dmi', "ratvar_alert")
var/area/A = get_area(src)
notify_ghosts("The Justiciar's light calls to you! Reach out to Ratvar in [A.name] to be granted a shell to spread his glory!", null, source = src, alert_overlay = alert_overlay)
- INVOKE_ASYNC(SSshuttle.emergency, /obj/docking_port/mobile/emergency..proc/request, null, 0)
+ INVOKE_ASYNC(SSshuttle.emergency, /obj/docking_port/mobile/emergency..proc/request, null, 0, 0)
/obj/structure/destructible/clockwork/massive/ratvar/Destroy()
GLOB.ratvar_awakens--
diff --git a/code/game/gamemodes/clock_cult/clock_structures/tinkerers_daemon.dm b/code/game/gamemodes/clock_cult/clock_structures/tinkerers_daemon.dm
index 22ea9e2ce5..b0a17338ff 100644
--- a/code/game/gamemodes/clock_cult/clock_structures/tinkerers_daemon.dm
+++ b/code/game/gamemodes/clock_cult/clock_structures/tinkerers_daemon.dm
@@ -18,7 +18,7 @@
var/static/mutable_appearance/component_glow = mutable_appearance('icons/obj/clockwork_objects.dmi', "t_random_component")
var/component_id_to_produce
var/production_time = 0 //last time we produced a component
- var/production_cooldown = 120
+ var/production_cooldown = 60
/obj/structure/destructible/clockwork/powered/tinkerers_daemon/Initialize()
. = ..()
diff --git a/code/game/gamemodes/cult/ritual.dm b/code/game/gamemodes/cult/ritual.dm
index 843d16592a..ce4abced72 100644
--- a/code/game/gamemodes/cult/ritual.dm
+++ b/code/game/gamemodes/cult/ritual.dm
@@ -133,7 +133,7 @@ This file contains the arcane tome files.
text += "Talisman of Armaments
The Talisman of Arming will equip the user with armored robes, a backpack, an eldritch longsword, an empowered bola, and a pair of boots. Any items that cannot \
be equipped will not be summoned. Attacking a fellow cultist with it will instead equip them.
"
- text += "Talisman of Horrors
The Talisman of Horror must be applied directly to the victim, it will shatter your victim's mind with visions of the endtimes that may incapitate them.
"
+ text += "Talisman of Horrors
The Talisman of Horror, unlike other talismans, can be applied at range, without the victim noticing. It will cause the victim to have severe hallucinations after a short while.
"
text += "Talisman of Shackling
The Talisman of Shackling must be applied directly to the victim, it has 4 uses and cuffs victims with magic shackles that disappear when removed.
"
diff --git a/code/game/gamemodes/cult/talisman.dm b/code/game/gamemodes/cult/talisman.dm
index 2411f0c40d..9645b4bbce 100644
--- a/code/game/gamemodes/cult/talisman.dm
+++ b/code/game/gamemodes/cult/talisman.dm
@@ -293,12 +293,12 @@
invocation = "Lo'Nab Na'Dm!"
creation_time = 80
-/obj/item/weapon/paper/talisman/horror/attack(mob/living/target, mob/living/user)
- if(iscultist(user))
- to_chat(user, "You disturb [target] with visons of the end!")
+/obj/item/weapon/paper/talisman/horror/afterattack(mob/living/target, mob/living/user)
+ if(iscultist(user) && (get_dist(user, target) < 7))
+ to_chat(user, "You disturb [target] with visions of madness!")
if(iscarbon(target))
var/mob/living/carbon/H = target
- H.reagents.add_reagent("mindbreaker", 25)
+ H.reagents.add_reagent("mindbreaker", 12)
if(is_servant_of_ratvar(target))
to_chat(target, "You see a brief but horrible vision of Ratvar, rusted and scrapped, being torn apart.")
target.emote("scream")
diff --git a/code/game/gamemodes/gang/gang_datum.dm b/code/game/gamemodes/gang/gang_datum.dm
index 3c54d5436b..805cac552f 100644
--- a/code/game/gamemodes/gang/gang_datum.dm
+++ b/code/game/gamemodes/gang/gang_datum.dm
@@ -13,6 +13,7 @@
var/list/territory = list()
var/list/territory_new = list()
var/list/territory_lost = list()
+ var/recalls = 1
var/dom_attempts = 2
var/points = 15
var/datum/atom_hud/antag/gang/ganghud
@@ -262,4 +263,4 @@
ganghud = new()
/datum/gang/multiverse/income()
- return
\ No newline at end of file
+ return
diff --git a/code/game/gamemodes/gang/recaller.dm b/code/game/gamemodes/gang/recaller.dm
index 0885b32612..f67bcad50a 100644
--- a/code/game/gamemodes/gang/recaller.dm
+++ b/code/game/gamemodes/gang/recaller.dm
@@ -168,6 +168,9 @@
if(recalling)
to_chat(usr, "Error: Recall already in progress.")
return 0
+
+ if(!gang.recalls)
+ to_chat(usr, "Error: Unable to access communication arrays. Firewall has logged our signature and is blocking all further attempts.")
gang.message_gangtools("[usr] is attempting to recall the emergency shuttle.")
recalling = 1
@@ -209,6 +212,7 @@
userturf = get_turf(user)
if(userturf.z == 1) //Check one more time that they are on station.
if(SSshuttle.cancelEvac(user))
+ gang.recalls -= 1
return 1
to_chat(loc, "\icon[src]No response recieved. Emergency shuttle cannot be recalled at this time.")
diff --git a/code/game/gamemodes/miniantags/revenant/revenant.dm b/code/game/gamemodes/miniantags/revenant/revenant.dm
index 7260d8221f..265688a15b 100644
--- a/code/game/gamemodes/miniantags/revenant/revenant.dm
+++ b/code/game/gamemodes/miniantags/revenant/revenant.dm
@@ -14,6 +14,7 @@
var/icon_reveal = "revenant_revealed"
var/icon_stun = "revenant_stun"
var/icon_drain = "revenant_draining"
+ var/stasis = 0
incorporeal_move = 3
invisibility = INVISIBILITY_REVENANT
health = INFINITY //Revenants don't use health, they use essence instead
@@ -94,6 +95,8 @@
//Life, Stat, Hud Updates, and Say
/mob/living/simple_animal/revenant/Life()
+ if(stasis)
+ return
if(revealed && essence <= 0)
death()
if(unreveal_time && world.time >= unreveal_time)
@@ -200,9 +203,8 @@
death()
/mob/living/simple_animal/revenant/death()
- if(!revealed || stat == DEAD) //Revenants cannot die if they aren't revealed //or are already dead
+ if(!revealed || stasis) //Revenants cannot die if they aren't revealed //or are already dead
return 0
- ..(1)
to_chat(src, "NO! No... it's too late, you can feel your essence [pick("breaking apart", "drifting away")]...")
notransform = TRUE
revealed = TRUE
@@ -217,9 +219,12 @@
var/reforming_essence = essence_regen_cap //retain the gained essence capacity
var/obj/item/weapon/ectoplasm/revenant/R = new(get_turf(src))
R.essence = max(reforming_essence - 15 * perfectsouls, 75) //minus any perfect souls
- R.client_to_revive = src.client //If the essence reforms, the old revenant is put back in the body
- ghostize()
- qdel(src)
+ R.client_to_revive = client //If the essence reforms, the old revenant is put back in the body
+ R.revenant = src
+ invisibility = INVISIBILITY_ABSTRACT
+ revealed = 0
+ stasis = 1
+ ghostize(0)//Don't re-enter invisible corpse
return
@@ -302,6 +307,18 @@
to_chat(src, "Lost [essence_amt]E[source ? " from [source]":""].")
return 1
+/mob/living/simple_animal/revenant/proc/death_reset()
+ revealed = FALSE
+ unreveal_time = 0
+ notransform = 0
+ unstun_time = 0
+ inhibited = FALSE
+ draining = FALSE
+ incorporeal_move = 3
+ invisibility = INVISIBILITY_REVENANT
+ alpha=255
+ stasis = 0
+
//reforming
/obj/item/weapon/ectoplasm/revenant
@@ -314,11 +331,15 @@
var/reforming = TRUE
var/inert = FALSE
var/client/client_to_revive
+ var/mob/living/simple_animal/revenant/revenant
/obj/item/weapon/ectoplasm/revenant/New()
..()
addtimer(CALLBACK(src, .proc/try_reform), 600)
+/obj/item/weapon/ectoplasm/revenant/proc/scatter()
+ qdel(src)
+
/obj/item/weapon/ectoplasm/revenant/proc/try_reform()
if(reforming)
reforming = FALSE
@@ -333,14 +354,14 @@
user.visible_message("[user] scatters [src] in all directions.", \
"You scatter [src] across the area. The particles slowly fade away.")
user.drop_item()
- qdel(src)
+ scatter()
/obj/item/weapon/ectoplasm/revenant/throw_impact(atom/hit_atom)
..()
if(inert)
return
visible_message("[src] breaks into particles upon impact, which fade away to nothingness.")
- qdel(src)
+ scatter()
/obj/item/weapon/ectoplasm/revenant/examine(mob/user)
..()
@@ -350,47 +371,51 @@
to_chat(user, "It is shifting and distorted. It would be wise to destroy this.")
/obj/item/weapon/ectoplasm/revenant/proc/reform()
- if(QDELETED(src) || inert)
+ if(QDELETED(src) || QDELETED(revenant) || inert)
return
var/key_of_revenant
message_admins("Revenant ectoplasm was left undestroyed for 1 minute and is reforming into a new revenant.")
loc = get_turf(src) //In case it's in a backpack or someone's hand
- var/mob/living/simple_animal/revenant/R = new(get_turf(src))
+ revenant.forceMove(loc)
if(client_to_revive)
for(var/mob/M in GLOB.dead_mob_list)
if(M.client == client_to_revive) //Only recreates the mob if the mob the client is in is dead
- R.client = client_to_revive
+ revenant.client = client_to_revive
key_of_revenant = client_to_revive.key
if(!key_of_revenant)
message_admins("The new revenant's old client either could not be found or is in a new, living mob - grabbing a random candidate instead...")
- var/list/candidates = get_candidates(ROLE_REVENANT)
+ var/list/candidates = pollCandidatesForMob("Do you want to be [revenant.name] (reforming)?", "revenant", null, ROLE_REVENANT, 50, revenant)
if(!candidates.len)
- qdel(R)
+ qdel(revenant)
message_admins("No candidates were found for the new revenant. Oh well!")
inert = TRUE
visible_message("[src] settles down and seems lifeless.")
return
var/client/C = pick(candidates)
+ revenant.client = C
key_of_revenant = C.key
if(!key_of_revenant)
- qdel(R)
+ qdel(revenant)
message_admins("No ckey was found for the new revenant. Oh well!")
inert = TRUE
visible_message("[src] settles down and seems lifeless.")
return
- var/datum/mind/player_mind = new /datum/mind(key_of_revenant)
- R.essence_regen_cap = essence
- R.essence = R.essence_regen_cap
- player_mind.active = 1
- player_mind.transfer_to(R)
- player_mind.assigned_role = "revenant"
- player_mind.special_role = "Revenant"
- SSticker.mode.traitors |= player_mind
+
message_admins("[key_of_revenant] has been [client_to_revive ? "re":""]made into a revenant by reforming ectoplasm.")
log_game("[key_of_revenant] was [client_to_revive ? "re":""]made as a revenant by reforming ectoplasm.")
visible_message("[src] suddenly rises into the air before fading away.")
+
+ revenant.essence = essence
+ revenant.essence_regen_cap = essence
+ revenant.death_reset()
+ revenant.key = key_of_revenant
+ revenant = null
qdel(src)
+/obj/item/weapon/ectoplasm/revenant/Destroy()
+ if(!QDELETED(revenant))
+ qdel(revenant)
+ ..()
//objectives
/datum/objective/revenant
diff --git a/code/game/gamemodes/nuclear/pinpointer.dm b/code/game/gamemodes/nuclear/pinpointer.dm
index c66b48a6c8..f3ddb6d4be 100644
--- a/code/game/gamemodes/nuclear/pinpointer.dm
+++ b/code/game/gamemodes/nuclear/pinpointer.dm
@@ -17,6 +17,7 @@
var/atom/movable/constant_target = null //The thing we're always focused on, if we're in the right mode
var/target_x = 0 //The target coordinates if we're tracking those
var/target_y = 0
+ var/minimum_range = 0 //at what range the pinpointer declares you to be at your destination
var/nuke_warning = FALSE // If we've set off a miniature alarm about an armed nuke
var/mode = TRACK_NUKE_DISK //What are we looking for?
@@ -111,7 +112,7 @@
var/mob/living/closest_operative = get_closest_atom(/mob/living/carbon/human, possible_targets, here)
if(closest_operative)
target = closest_operative
- if(TRACK_ATOM)
+ if(TRACK_ATOM)
if(constant_target)
target = constant_target
if(TRACK_COORDINATES)
@@ -129,7 +130,7 @@
if(here.z != there.z)
icon_state = "pinon[nuke_warning ? "alert" : ""]null"
return
- if(here == there)
+ if(get_dist_euclidian(here,there)<=minimum_range)
icon_state = "pinon[nuke_warning ? "alert" : ""]direct"
else
setDir(get_dir(here, there))
@@ -171,3 +172,6 @@
desc = "An integrated tracking device, jury-rigged to search for living Syndicate operatives."
mode = TRACK_OPERATIVES
flags = NODROP
+
+
+
diff --git a/code/game/gamemodes/objective.dm b/code/game/gamemodes/objective.dm
index 6ac0ab8c7c..039b4cc3a4 100644
--- a/code/game/gamemodes/objective.dm
+++ b/code/game/gamemodes/objective.dm
@@ -67,7 +67,14 @@
/datum/objective/proc/update_explanation_text()
//Default does nothing, override where needed
-/datum/objective/proc/give_special_equipment()
+/datum/objective/proc/give_special_equipment(special_equipment)
+ if(owner && owner.current)
+ if(ishuman(owner.current))
+ var/mob/living/carbon/human/H = owner.current
+ var/list/slots = list ("backpack" = slot_in_backpack)
+ for(var/eq_path in special_equipment)
+ var/obj/O = new eq_path
+ H.equip_in_one_of_slots(O, slots)
/datum/objective/assassinate
var/target_role_type=0
@@ -94,6 +101,14 @@
else
explanation_text = "Free Objective"
+/datum/objective/assassinate/internal
+ var/stolen = 0 //Have we already eliminated this target?
+
+/datum/objective/assassinate/internal/update_explanation_text()
+ ..()
+ if(target && !target.current)
+ explanation_text = "Assassinate [target.name], who was obliterated"
+
/datum/objective/mutiny
var/target_role_type=0
@@ -468,7 +483,7 @@ GLOBAL_LIST_EMPTY(possible_items)
steal_target = targetinfo.targetitem
explanation_text = "Steal [targetinfo.name]."
dangerrating = targetinfo.difficulty
- give_special_equipment()
+ give_special_equipment(targetinfo.special_equipment)
return steal_target
else
explanation_text = "Free objective"
@@ -511,15 +526,6 @@ GLOBAL_LIST_EMPTY(possible_items)
return 1
return 0
-/datum/objective/steal/give_special_equipment()
- if(owner && owner.current && targetinfo)
- if(ishuman(owner.current))
- var/mob/living/carbon/human/H = owner.current
- var/list/slots = list ("backpack" = slot_in_backpack)
- for(var/eq_path in targetinfo.special_equipment)
- var/obj/O = new eq_path
- H.equip_in_one_of_slots(O, slots)
-
GLOBAL_LIST_EMPTY(possible_items_special)
/datum/objective/steal/special //ninjas are so special they get their own subtype good for them
@@ -695,6 +701,9 @@ GLOBAL_LIST_EMPTY(possible_items_special)
explanation_text = "Destroy [target.name], the experimental AI."
else
explanation_text = "Free Objective"
+
+/datum/objective/destroy/internal
+ var/stolen = FALSE //Have we already eliminated this target?
/datum/objective/steal_five_of_type
explanation_text = "Steal at least five items!"
diff --git a/code/game/gamemodes/traitor/double_agents.dm b/code/game/gamemodes/traitor/double_agents.dm
index cb6609ebe6..2ee546c7aa 100644
--- a/code/game/gamemodes/traitor/double_agents.dm
+++ b/code/game/gamemodes/traitor/double_agents.dm
@@ -1,9 +1,13 @@
+#define PINPOINTER_MINIMUM_RANGE 15
+#define PINPOINTER_EXTRA_RANDOM_RANGE 10
+#define PINPOINTER_PING_TIME 40
+
/datum/game_mode/traitor/internal_affairs
name = "Internal Affairs"
config_tag = "internal_affairs"
employer = "Internal Affairs"
- required_players = 25
- required_enemies = 5
+ required_players = 25
+ required_enemies = 5
recommended_enemies = 8
reroll_friendly = 0
traitor_name = "Nanotrasen Internal Affairs Agent"
@@ -18,15 +22,189 @@
var/list/target_list = list()
var/list/late_joining_list = list()
+
/datum/game_mode/traitor/internal_affairs/post_setup()
var/i = 0
for(var/datum/mind/traitor in traitors)
i++
if(i + 1 > traitors.len)
i = 0
- target_list[traitor] = traitors[i + 1]
+ target_list[traitor] = traitors[i+1]
..()
+
+/datum/status_effect/agent_pinpointer
+ id = "agent_pinpointer"
+ duration = -1
+ tick_interval = PINPOINTER_PING_TIME
+ alert_type = /obj/screen/alert/status_effect/agent_pinpointer
+ var/minimum_range = PINPOINTER_MINIMUM_RANGE
+ var/mob/scan_target = null
+
+/obj/screen/alert/status_effect/agent_pinpointer
+ name = "Internal Affairs Integrated Pinpointer"
+ desc = "Even stealthier than a normal implant."
+ icon = 'icons/obj/device.dmi'
+ icon_state = "pinon"
+
+/datum/status_effect/agent_pinpointer/proc/point_to_target() //If we found what we're looking for, show the distance and direction
+ if(!scan_target)
+ linked_alert.icon_state = "pinonnull"
+ return
+ var/turf/here = get_turf(owner)
+ var/turf/there = get_turf(scan_target)
+ if(here.z != there.z)
+ linked_alert.icon_state = "pinonnull"
+ return
+ if(get_dist_euclidian(here,there)<=minimum_range + rand(0, PINPOINTER_EXTRA_RANDOM_RANGE))
+ linked_alert.icon_state = "pinondirect"
+ else
+ linked_alert.setDir(get_dir(here, there))
+ switch(get_dist(here, there))
+ if(1 to 8)
+ linked_alert.icon_state = "pinonclose"
+ if(9 to 16)
+ linked_alert.icon_state = "pinonmedium"
+ if(16 to INFINITY)
+ linked_alert.icon_state = "pinonfar"
+
+
+/datum/status_effect/agent_pinpointer/proc/scan_for_target()
+ scan_target = null
+ if(owner)
+ if(owner.mind)
+ if(owner.mind.objectives)
+ for(var/datum/objective/objective_ in owner.mind.objectives)
+ if(!is_internal_objective(objective_))
+ continue
+ var/datum/objective/assassinate/internal/objective = objective_
+ var/mob/current = objective.target.current
+ if(current&¤t.stat!=DEAD)
+ scan_target = current
+ break
+
+
+/datum/status_effect/agent_pinpointer/tick()
+ if(!owner)
+ qdel(src)
+ return
+ scan_for_target()
+ point_to_target()
+
+/proc/give_pinpointer(datum/mind/owner)
+ if(owner && owner.current)
+ owner.current.apply_status_effect(/datum/status_effect/agent_pinpointer)
+
+
+/datum/internal_agent_state
+ var/traitored = FALSE
+ var/datum/mind/owner = null
+ var/list/datum/mind/targets_stolen = list()
+
+/proc/is_internal_objective(datum/objective/O)
+ return (istype(O, /datum/objective/assassinate/internal)||istype(O, /datum/objective/destroy/internal))
+
+/proc/replace_escape_objective(datum/mind/owner)
+ if(!owner||!owner.objectives)
+ return
+ for (var/objective_ in owner.objectives)
+ if(!(istype(objective_, /datum/objective/escape)||istype(objective_,/datum/objective/survive)))
+ continue
+ owner.objectives -= objective_
+ var/datum/objective/martyr/martyr_objective = new
+ martyr_objective.owner = owner
+ owner.objectives += martyr_objective
+
+/proc/reinstate_escape_objective(datum/mind/owner)
+ if(!owner||!owner.objectives)
+ return
+ for (var/objective_ in owner.objectives)
+ if(!istype(objective_, /datum/objective/martyr))
+ continue
+ owner.objectives -= objective_
+ if(issilicon(owner))
+ var/datum/objective/survive/survive_objective = new
+ survive_objective.owner = owner
+ owner.objectives += survive_objective
+ else
+ var/datum/objective/escape/escape_objective = new
+ escape_objective.owner = owner
+ owner.objectives += escape_objective
+
+/datum/internal_agent_state/proc/steal_targets(datum/mind/victim)
+ if(!owner.current||owner.current.stat==DEAD) //Should already be guaranteed if this is only called from steal_targets_timer_func, but better to be safe code than sorry code
+ return
+ var/already_traitored = traitored
+ to_chat(owner.current, " Target eliminated: [victim.name]")
+ for(var/objective_ in victim.objectives)
+ if(istype(objective_, /datum/objective/assassinate/internal))
+ var/datum/objective/assassinate/internal/objective = objective_
+ if(objective.target==owner)
+ traitored = TRUE
+ else if(targets_stolen.Find(objective.target) == 0)
+ var/datum/objective/assassinate/internal/new_objective = new
+ new_objective.owner = owner
+ new_objective.target = objective.target
+ new_objective.update_explanation_text()
+ owner.objectives += new_objective
+ targets_stolen += objective.target
+ var/status_text = objective.check_completion() ? "neutralised" : "active"
+ to_chat(owner.current, " New target added to database: [objective.target.name] ([status_text]) ")
+ else if(istype(objective_, /datum/objective/destroy/internal))
+ var/datum/objective/destroy/internal/objective = objective_
+ var/datum/objective/destroy/internal/new_objective = new
+ if(objective.target==owner)
+ traitored = TRUE
+ else if(targets_stolen.Find(objective.target) == 0)
+ new_objective.owner = owner
+ new_objective.target = objective.target
+ new_objective.update_explanation_text()
+ owner.objectives += new_objective
+ targets_stolen += objective.target
+ var/status_text = objective.check_completion() ? "neutralised" : "active"
+ to_chat(owner.current, " New target added to database: [objective.target.name] ([status_text]) ")
+ if(traitored&&!already_traitored)
+ for(var/objective_ in owner.objectives)
+ if(!is_internal_objective(objective_))
+ continue
+ var/datum/objective/assassinate/internal/objective = objective_
+ if(!objective.check_completion())
+ traitored = FALSE
+ return
+ to_chat(owner.current," All the other agents are dead, and you're the last loose end. Stage a Syndicate terrorist attack to cover up for today's events. You no longer have any limits on collateral damage.")
+ replace_escape_objective(owner)
+
+
+
+/datum/internal_agent_state/proc/steal_targets_timer_func()
+ if(owner&&owner.current&&owner.current.stat!=DEAD)
+ for(var/objective_ in owner.objectives)
+ if(!is_internal_objective(objective_))
+ continue
+ var/datum/objective/assassinate/internal/objective = objective_
+ if(!objective.target)
+ continue
+ if(objective.check_completion())
+ if(objective.stolen)
+ continue
+ else
+ steal_targets(objective.target)
+ objective.stolen = TRUE
+ else
+ if(objective.stolen)
+ var/fail_msg = "Your sensors tell you that [objective.target.current.real_name], one of the targets you were meant to have killed, pulled one over on you, and is still alive - do the job properly this time! "
+ if(traitored)
+ fail_msg += " The truth could still slip out! Cease any terrorist actions as soon as possible, unneeded property damage or loss of employee life will lead to your contract being terminated."
+ reinstate_escape_objective(owner)
+ traitored = FALSE
+ to_chat(owner.current, fail_msg)
+ objective.stolen = FALSE
+ add_steal_targets_timer(owner)
+
+/datum/internal_agent_state/proc/add_steal_targets_timer()
+ var/datum/callback/C = new(src, .steal_targets_timer_func)
+ addtimer(C, 30)
+
/datum/game_mode/traitor/internal_affairs/forge_traitor_objectives(datum/mind/traitor)
if(target_list.len && target_list[traitor]) // Is a double agent
@@ -34,13 +212,13 @@
// Assassinate
var/datum/mind/target_mind = target_list[traitor]
if(issilicon(target_mind.current))
- var/datum/objective/destroy/destroy_objective = new
+ var/datum/objective/destroy/internal/destroy_objective = new
destroy_objective.owner = traitor
destroy_objective.target = target_mind
destroy_objective.update_explanation_text()
traitor.objectives += destroy_objective
else
- var/datum/objective/assassinate/kill_objective = new
+ var/datum/objective/assassinate/internal/kill_objective = new
kill_objective.owner = traitor
kill_objective.target = target_mind
kill_objective.update_explanation_text()
@@ -55,6 +233,11 @@
var/datum/objective/escape/escape_objective = new
escape_objective.owner = traitor
traitor.objectives += escape_objective
+ var/datum/internal_agent_state/state = new
+ state.owner=traitor
+ state.add_steal_targets_timer()
+ if(!issilicon(traitor.current))
+ give_pinpointer(traitor)
else
..() // Give them standard objectives.
@@ -106,14 +289,18 @@
/datum/game_mode/traitor/internal_affairs/greet_traitor(datum/mind/traitor)
var/crime = pick("distribution of contraband" , "unauthorized erotic action on duty", "embezzlement", "piloting under the influence", "dereliction of duty", "syndicate collaboration", "mutiny", "multiple homicides", "corporate espionage", "recieving bribes", "malpractice", "worship of prohbited life forms", "possession of profane texts", "murder", "arson", "insulting their manager", "grand theft", "conspiracy", "attempting to unionize", "vandalism", "gross incompetence")
- to_chat(traitor.current, "You are the [traitor_name].")
- to_chat(traitor.current, "Your target is suspected of [crime], and you have been tasked with eliminating them by any means necessary to avoid a costly and embarrassing public trial.")
+ to_chat(traitor.current, "You are the [traitor_name].")
+ to_chat(traitor.current, "Your target is suspected of [crime], and you have been tasked with eliminating them by any means necessary to avoid a costly and embarrassing public trial.")
to_chat(traitor.current, "While you have a license to kill, unneeded property damage or loss of employee life will lead to your contract being terminated.")
- to_chat(traitor.current, "For the sake of plausible deniability, you have been equipped with an array of captured Syndicate weaponry available via uplink.")
- to_chat(traitor.current, "Finally, watch your back. Your target has friends in high places, and intel suggests someone may have taken out a contract of their own to protect them.")
+ to_chat(traitor.current, "For the sake of plausible deniability, you have been equipped with an array of captured Syndicate weaponry available via uplink.")
+ to_chat(traitor.current, "Finally, watch your back. Your target has friends in high places, and intel suggests someone may have taken out a contract of their own to protect them.")
traitor.announce_objectives()
/datum/game_mode/traitor/internal_affairs/give_codewords(mob/living/traitor_mob)
- return
\ No newline at end of file
+ return
+
+#undef PINPOINTER_EXTRA_RANDOM_RANGE
+#undef PINPOINTER_MINIMUM_RANGE
+#undef PINPOINTER_PING_TIME
diff --git a/code/game/machinery/computer/telecrystalconsoles.dm b/code/game/machinery/computer/telecrystalconsoles.dm
index 4bb872b347..fd026e4686 100644
--- a/code/game/machinery/computer/telecrystalconsoles.dm
+++ b/code/game/machinery/computer/telecrystalconsoles.dm
@@ -58,7 +58,12 @@ GLOBAL_LIST_INIT(possible_uplinker_IDs, list("Alfa","Bravo","Charlie","Delta","E
/obj/machinery/computer/telecrystals/uplinker/proc/donateTC(amt, addLog = 1)
if(uplinkholder && linkedboss)
- if(amt <= uplinkholder.hidden_uplink.telecrystals)
+ if(amt < 0)
+ linkedboss.storedcrystals += uplinkholder.hidden_uplink.telecrystals
+ if(addLog)
+ linkedboss.logTransfer("[src] donated [uplinkholder.hidden_uplink.telecrystals] telecrystals to [linkedboss].")
+ uplinkholder.hidden_uplink.telecrystals = 0
+ else if(amt <= uplinkholder.hidden_uplink.telecrystals)
uplinkholder.hidden_uplink.telecrystals -= amt
linkedboss.storedcrystals += amt
if(addLog)
@@ -66,7 +71,12 @@ GLOBAL_LIST_INIT(possible_uplinker_IDs, list("Alfa","Bravo","Charlie","Delta","E
/obj/machinery/computer/telecrystals/uplinker/proc/giveTC(amt, addLog = 1)
if(uplinkholder && linkedboss)
- if(amt <= linkedboss.storedcrystals)
+ if(amt < 0)
+ uplinkholder.hidden_uplink.telecrystals += linkedboss.storedcrystals
+ if(addLog)
+ linkedboss.logTransfer("[src] received [linkedboss.storedcrystals] telecrystals from [linkedboss].")
+ linkedboss.storedcrystals = 0
+ else if(amt <= linkedboss.storedcrystals)
uplinkholder.hidden_uplink.telecrystals += amt
linkedboss.storedcrystals -= amt
if(addLog)
@@ -89,7 +99,7 @@ GLOBAL_LIST_INIT(possible_uplinker_IDs, list("Alfa","Bravo","Charlie","Delta","E
if(uplinkholder)
dat += "[uplinkholder.hidden_uplink.telecrystals] telecrystals remain in this uplink.
"
if(linkedboss)
- dat += "Donate TC: 1 | 5"
+ dat += "Donate TC: 1 | 5 | All"
dat += "
Eject Uplink"
@@ -103,11 +113,9 @@ GLOBAL_LIST_INIT(possible_uplinker_IDs, list("Alfa","Bravo","Charlie","Delta","E
if(..())
return
- if(href_list["donate1"])
- donateTC(1)
-
- if(href_list["donate5"])
- donateTC(5)
+ if(href_list["donate"])
+ var/tcamt = text2num(href_list["donate"])
+ donateTC(tcamt)
if(href_list["eject"])
ejectuplink()
@@ -162,7 +170,7 @@ GLOBAL_LIST_INIT(possible_uplinker_IDs, list("Alfa","Bravo","Charlie","Delta","E
var/dat = ""
dat += "Scan for TC stations.
"
- dat += "This [src] has [storedcrystals] telecrystals available for distribution.
"
+ dat += "[storedcrystals] telecrystals are available for distribution.
"
dat += "
"
@@ -171,10 +179,10 @@ GLOBAL_LIST_INIT(possible_uplinker_IDs, list("Alfa","Bravo","Charlie","Delta","E
if(A.uplinkholder)
dat += "[A.uplinkholder.hidden_uplink.telecrystals] telecrystals."
if(storedcrystals)
- dat+= "
Add TC: 1 | 5"
+ dat+= "
Add TC: 1 | 5 | 10 | All"
dat += "
"
- if(TCstations.len)
+ if(TCstations.len && storedcrystals)
dat += "
Evenly distribute remaining TC.
"
@@ -195,13 +203,11 @@ GLOBAL_LIST_INIT(possible_uplinker_IDs, list("Alfa","Bravo","Charlie","Delta","E
if(href_list["scan"])
scanUplinkers()
- if(href_list["give1"])
- var/obj/machinery/computer/telecrystals/uplinker/A = locate(href_list["give1"])
- A.giveTC(1)
-
- if(href_list["give5"])
- var/obj/machinery/computer/telecrystals/uplinker/A = locate(href_list["give5"])
- A.giveTC(5)
+ if(href_list["give"])
+ var/tcamt = text2num(href_list["give"])
+ if(TCstations.len) // sanity
+ var/obj/machinery/computer/telecrystals/uplinker/A = locate(href_list["target"]) in TCstations
+ A.giveTC(tcamt)
if(href_list["distrib"])
var/sanity = 0
diff --git a/code/game/machinery/hologram.dm b/code/game/machinery/hologram.dm
index ae8c1ac1c4..bc73c41f08 100644
--- a/code/game/machinery/hologram.dm
+++ b/code/game/machinery/hologram.dm
@@ -26,14 +26,13 @@ Possible to do for anyone motivated enough:
#define HOLOPAD_PASSIVE_POWER_USAGE 1
#define HOLOGRAM_POWER_USAGE 2
-#define RANGE_BASED 4
-#define AREA_BASED 6
+GLOBAL_LIST_EMPTY(holopads)
#define HOLOPAD_MODE RANGE_BASED
/obj/machinery/holopad
- name = "\improper AI holopad"
- desc = "It's a floor-mounted device for projecting holographic images. It is activated remotely."
+ name = "Holopad"
+ desc = "It's a floor-mounted device for projecting holographic images."
icon_state = "holopad0"
layer = LOW_OBJ_LAYER
flags = HEAR
@@ -44,21 +43,32 @@ Possible to do for anyone motivated enough:
obj_integrity = 300
max_integrity = 300
armor = list(melee = 50, bullet = 20, laser = 20, energy = 20, bomb = 0, bio = 0, rad = 0, fire = 50, acid = 0)
- var/list/masters = list()//List of AIs that use the holopad
+ var/list/masters = list()//List of living mobs that use the holopad
var/last_request = 0 //to prevent request spam. ~Carn
var/holo_range = 5 // Change to change how far the AI can move away from the holopad before deactivating.
var/temp = ""
+ var/list/holo_calls //array of /datum/holocalls
+ var/datum/holocall/outgoing_call //do not modify the datums only check and call the public procs
+ var/static/force_answer_call = FALSE //Calls will be automatically answered after a couple rings, here for debugging
var/static/list/holopads = list()
-/obj/machinery/holopad/New()
+/obj/machinery/holopad/Initialize()
..()
var/obj/item/weapon/circuitboard/machine/B = new /obj/item/weapon/circuitboard/machine/holopad(null)
B.apply_default_parts(src)
holopads += src
/obj/machinery/holopad/Destroy()
- for (var/mob/living/silicon/ai/master in masters)
- clear_holo(master)
+ if(outgoing_call)
+ LAZYADD(holo_calls, outgoing_call)
+
+ for(var/I in holo_calls)
+ var/datum/holocall/HC = I
+ HC.ConnectionFailure(src)
+ LAZYCLEARLIST(holo_calls)
+
+ for (var/I in masters)
+ clear_holo(I)
holopads -= src
return ..()
@@ -91,20 +101,58 @@ Possible to do for anyone motivated enough:
return
return ..()
+/obj/machinery/holopad/proc/CheckCallClose()
+ for(var/I in holo_calls)
+ var/datum/holocall/HC = I
+ if(usr == HC.eye)
+ HC.Disconnect(HC.calling_holopad) //disconnect via clicking the called holopad
+ return TRUE
+ return FALSE
+
+/obj/machinery/holopad/Click(location,control,params)
+ if(!CheckCallClose())
+ return ..()
+
/obj/machinery/holopad/AltClick(mob/living/carbon/human/user)
- interact(user)
+ if(!CheckCallClose())
+ interact(user)
/obj/machinery/holopad/interact(mob/living/carbon/human/user) //Carn: Hologram requests.
if(!istype(user))
return
- if(user.stat || !is_operational())
+
+ if(outgoing_call || user.incapacitated() || !is_operational())
return
+
user.set_machine(src)
var/dat
if(temp)
dat = temp
else
- dat = "request an AI's presence."
+ dat = "Request an AI's presence.
"
+ dat += "Call another holopad.
"
+
+ if(LAZYLEN(holo_calls))
+ dat += "=====================================================
"
+
+ var/one_answered_call = FALSE
+ var/one_unanswered_call = FALSE
+ for(var/I in holo_calls)
+ var/datum/holocall/HC = I
+ if(HC.connected_holopad != src)
+ dat += "Answer call from [get_area(HC.calling_holopad)].
"
+ one_unanswered_call = TRUE
+ else
+ one_answered_call = TRUE
+
+ if(one_answered_call && one_unanswered_call)
+ dat += "=====================================================
"
+ //we loop twice for formatting
+ for(var/I in holo_calls)
+ var/datum/holocall/HC = I
+ if(HC.connected_holopad == src)
+ dat += "Disconnect call from [HC.user].
"
+
var/datum/browser/popup = new(user, "holopad", name, 300, 130)
popup.set_content(dat)
@@ -112,7 +160,10 @@ Possible to do for anyone motivated enough:
popup.open()
/obj/machinery/holopad/Topic(href, href_list)
- if(..() || !is_operational())
+ if(..() || isAI(usr))
+ return
+ add_fingerprint(usr)
+ if(!is_operational())
return
if (href_list["AIrequest"])
if(last_request + 200 < world.time)
@@ -120,7 +171,7 @@ Possible to do for anyone motivated enough:
temp = "You requested an AI's presence.
"
temp += "Main Menu"
var/area/area = get_area(src)
- for(var/mob/living/silicon/ai/AI in GLOB.living_mob_list)
+ for(var/mob/living/silicon/ai/AI in GLOB.silicon_mobs)
if(!AI.client)
continue
to_chat(AI, "Your presence is requested at \the [area].")
@@ -128,12 +179,49 @@ Possible to do for anyone motivated enough:
temp = "A request for AI presence was already sent recently.
"
temp += "Main Menu"
- else if(href_list["mainmenu"])
+ else if(href_list["Holocall"])
+ if(outgoing_call)
+ return
+
+ temp = "You must stand on the holopad to make a call!
"
+ temp += "Main Menu"
+ if(usr.loc == loc)
+ var/list/callnames = list()
+ for(var/I in holopads)
+ var/area/A = get_area(I)
+ if(A)
+ LAZYADD(callnames[A], I)
+ callnames -= get_area(src)
+
+ var/result = input(usr, "Choose an area to call", "Holocall") as null|anything in callnames
+ if(QDELETED(usr) || !result || outgoing_call)
+ return
+
+ if(usr.loc == loc)
+ temp = "Dialing...
"
+ temp += "Main Menu"
+ new /datum/holocall(usr, src, callnames[result])
+
+ else if(href_list["connectcall"])
+ var/datum/holocall/call_to_connect = locate(href_list["connectcall"])
+ if(!QDELETED(call_to_connect))
+ call_to_connect.Answer(src)
temp = ""
- updateDialog()
- add_fingerprint(usr)
+ else if(href_list["disconnectcall"])
+ var/datum/holocall/call_to_disconnect = locate(href_list["disconnectcall"])
+ if(!QDELETED(call_to_disconnect))
+ call_to_disconnect.Disconnect(src)
+ temp = ""
+ else if(href_list["mainmenu"])
+ temp = ""
+ if(outgoing_call)
+ outgoing_call.Disconnect()
+
+ updateDialog()
+
+//do not allow AIs to answer calls or people will use it to meta the AI sattelite
/obj/machinery/holopad/attack_ai(mob/living/silicon/ai/user)
if (!istype(user))
return
@@ -148,39 +236,75 @@ Possible to do for anyone motivated enough:
clear_holo(user)
/obj/machinery/holopad/process()
- if(masters.len)//If there is a hologram.
- for (var/mob/living/silicon/ai/master in masters)
- if(master && !master.stat && master.client && master.eyeobj)//If there is an AI attached, it's not incapacitated, it has a client, and the client eye is centered on the projector.
- if(!(stat & NOPOWER))//If the machine has power.
- if(HOLOPAD_MODE == RANGE_BASED)
- if(get_dist(master.eyeobj, src) <= holo_range)
- return TRUE
- else
- var/obj/machinery/holopad/pad_close = get_closest_atom(/obj/machinery/holopad, holopads, master.eyeobj)
- if(get_dist(pad_close, master.eyeobj) <= holo_range)
- var/obj/effect/overlay/holo_pad_hologram/h = masters[master]
- unset_holo(master)
- pad_close.set_holo(master, h)
- return TRUE
+ for(var/I in masters)
+ var/mob/living/master = I
+ var/mob/living/silicon/ai/AI = master
+ if(!istype(AI))
+ AI = null
- else if (HOLOPAD_MODE == AREA_BASED)
+ if(!QDELETED(master) && !master.incapacitated() && master.client && (!AI || AI.eyeobj))//If there is an AI attached, it's not incapacitated, it has a client, and the client eye is centered on the projector.
+ if(is_operational())//If the machine has power.
+ if(AI) //ais are range based
+ if(get_dist(AI.eyeobj, src) <= holo_range)
+ continue
+ else
+ var/obj/machinery/holopad/pad_close = get_closest_atom(/obj/machinery/holopad, holopads, AI.eyeobj)
+ if(get_dist(pad_close, AI.eyeobj) <= holo_range)
+ var/obj/effect/overlay/holo_pad_hologram/h = masters[master]
+ unset_holo(master)
+ pad_close.set_holo(master, h)
+ continue
+ else
+ continue
+ clear_holo(master)//If not, we want to get rid of the hologram.
- var/area/holo_area = get_area(src)
- var/area/eye_area = get_area(master.eyeobj)
+ if(outgoing_call)
+ outgoing_call.Check()
- if(eye_area in holo_area.related)
- return TRUE
+ for(var/I in holo_calls)
+ var/datum/holocall/HC = I
+ if(HC.connected_holopad != src)
+ if(force_answer_call && world.time > (HC.call_start_time + (HOLOPAD_MAX_DIAL_TIME / 2)))
+ HC.Answer(src)
+ break
+ if(outgoing_call)
+ HC.Disconnect(src)//can't answer calls while calling
+ else
+ playsound(src, 'sound/machines/twobeep.ogg', 100) //bring, bring!
- clear_holo(master)//If not, we want to get rid of the hologram.
- return TRUE
+/obj/machinery/holopad/proc/activate_holo(mob/living/user)
+ var/mob/living/silicon/ai/AI = user
+ if(!istype(AI))
+ AI = null
-/obj/machinery/holopad/proc/activate_holo(mob/living/silicon/ai/user)
- if(!(stat & NOPOWER) && user.eyeobj.loc == src.loc)//If the projector has power and client eye is on it
- if (istype(user.current, /obj/machinery/holopad))
+ if(is_operational() && (!AI || AI.eyeobj.loc == loc))//If the projector has power and client eye is on it
+ if (AI && istype(AI.current, /obj/machinery/holopad))
to_chat(user, "ERROR: \black Image feed in progress.")
return
- create_holo(user)//Create one.
- src.visible_message("A holographic image of [user] flicks to life right before your eyes!")
+
+ var/obj/effect/overlay/holo_pad_hologram/Hologram = new(loc)//Spawn a blank effect at the location.
+ if(AI)
+ Hologram.icon = AI.holo_icon
+ else //make it like real life
+ Hologram.icon = user.icon
+ Hologram.icon_state = user.icon_state
+ Hologram.copy_overlays(user, TRUE)
+ //codersprite some holo effects here
+ Hologram.alpha = 100
+ Hologram.add_atom_colour("#77abff", FIXED_COLOUR_PRIORITY)
+ Hologram.Impersonation = user
+
+ Hologram.languages = user.languages
+ Hologram.mouse_opacity = 0//So you can't click on it.
+ Hologram.layer = FLY_LAYER//Above all the other objects/mobs. Or the vast majority of them.
+ Hologram.anchored = 1//So space wind cannot drag it.
+ Hologram.name = "[user.name] (Hologram)"//If someone decides to right click.
+ Hologram.set_light(2) //hologram lighting
+
+ set_holo(user, Hologram)
+ visible_message("A holographic image of [user] flicks to life right before your eyes!")
+
+ return Hologram
else
to_chat(user, "ERROR: \black Unable to project hologram.")
@@ -192,58 +316,80 @@ For the other part of the code, check silicon say.dm. Particularly robot talk.*/
if(masters[master] && speaker != master)
master.relay_speech(message, speaker, message_language, raw_message, radio_freq, spans, message_mode)
-/obj/machinery/holopad/proc/create_holo(mob/living/silicon/ai/A, turf/T = loc)
- var/obj/effect/overlay/holo_pad_hologram/h = new(T)//Spawn a blank effect at the location.
- h.icon = A.holo_icon
- h.mouse_opacity = 0//So you can't click on it.
- h.layer = FLY_LAYER//Above all the other objects/mobs. Or the vast majority of them.
- h.anchored = 1//So space wind cannot drag it.
- h.name = "[A.name] (Hologram)"//If someone decides to right click.
- h.set_light(2) //hologram lighting
- set_holo(A, h)
+ for(var/I in holo_calls)
+ var/datum/holocall/HC = I
+ if(HC.connected_holopad == src && speaker != HC.hologram)
+ HC.user.Hear(message, speaker, message_language, raw_message, radio_freq, spans)
+
+ if(outgoing_call && speaker == outgoing_call.user)
+ outgoing_call.hologram.say(raw_message)
+
+/obj/machinery/holopad/proc/SetLightsAndPower()
+ var/total_users = masters.len + LAZYLEN(holo_calls)
+ use_power = HOLOPAD_PASSIVE_POWER_USAGE + HOLOGRAM_POWER_USAGE * total_users
+ if(total_users)
+ set_light(2)
+ icon_state = "holopad1"
+ else
+ set_light(0)
+ icon_state = "holopad0"
+
+/obj/machinery/holopad/proc/set_holo(mob/living/user, var/obj/effect/overlay/holo_pad_hologram/h)
+ masters[user] = h
+ var/mob/living/silicon/ai/AI = user
+ if(istype(AI))
+ AI.current = src
+ SetLightsAndPower()
return TRUE
-/obj/machinery/holopad/proc/set_holo(mob/living/silicon/ai/A, var/obj/effect/overlay/holo_pad_hologram/h)
- masters[A] = h
- set_light(2) // pad lighting
- icon_state = "holopad1"
- A.current = src
- use_power += HOLOGRAM_POWER_USAGE
- return TRUE
-
-/obj/machinery/holopad/proc/clear_holo(mob/living/silicon/ai/user)
+/obj/machinery/holopad/proc/clear_holo(mob/living/user)
qdel(masters[user]) // Get rid of user's hologram
unset_holo(user)
return TRUE
-/obj/machinery/holopad/proc/unset_holo(mob/living/silicon/ai/user)
- if(user.current == src)
- user.current = null
+/obj/machinery/holopad/proc/unset_holo(mob/living/user)
+ var/mob/living/silicon/ai/AI = user
+ if(istype(AI) && AI.current == src)
+ AI.current = null
masters -= user // Discard AI from the list of those who use holopad
- use_power = max(HOLOPAD_PASSIVE_POWER_USAGE, use_power - HOLOGRAM_POWER_USAGE)//Reduce power usage
- if (!masters.len) // If no users left
- set_light(0) // pad lighting (hologram lighting will be handled automatically since its owner was deleted)
- icon_state = "holopad0"
- use_power = HOLOPAD_PASSIVE_POWER_USAGE
+ SetLightsAndPower()
return TRUE
-/obj/machinery/holopad/proc/move_hologram(mob/living/silicon/ai/user)
+/obj/machinery/holopad/proc/move_hologram(mob/living/user, turf/new_turf)
if(masters[user])
- step_to(masters[user], user.eyeobj)
var/obj/effect/overlay/holo_pad_hologram/H = masters[user]
- H.loc = get_turf(user.eyeobj)
+ step_to(H, new_turf)
+ H.loc = new_turf
+ var/area/holo_area = get_area(src)
+ var/area/eye_area = new_turf.loc
+
+ if(!(eye_area in holo_area.related))
+ clear_holo(user)
return TRUE
+/obj/effect/overlay/holo_pad_hologram
+ var/mob/living/Impersonation
+ var/datum/holocall/HC
+
+/obj/effect/overlay/holo_pad_hologram/Destroy()
+ Impersonation = null
+ if(HC)
+ HC.Disconnect(HC.calling_holopad)
+ return ..()
+
/obj/effect/overlay/holo_pad_hologram/Process_Spacemove(movement_dir = 0)
return 1
+/obj/effect/overlay/holo_pad_hologram/examine(mob/user)
+ if(Impersonation)
+ return Impersonation.examine(user)
+ return ..()
+
/obj/item/weapon/circuitboard/machine/holopad
name = "AI Holopad (Machine Board)"
build_path = /obj/machinery/holopad
origin_tech = "programming=1"
req_components = list(/obj/item/weapon/stock_parts/capacitor = 1)
-#undef RANGE_BASED
-#undef AREA_BASED
#undef HOLOPAD_PASSIVE_POWER_USAGE
-#undef HOLOGRAM_POWER_USAGE
+#undef HOLOGRAM_POWER_USAGE
\ No newline at end of file
diff --git a/code/game/machinery/pipe/construction.dm b/code/game/machinery/pipe/construction.dm
index 6735aa7609..2d3765a934 100644
--- a/code/game/machinery/pipe/construction.dm
+++ b/code/game/machinery/pipe/construction.dm
@@ -251,6 +251,8 @@ GLOBAL_LIST_INIT(pipeID2State, list(
var/mob/living/carbon/C = user
for(var/i=1 to 20)
C.vomit(0,1,0,4,0)
+ if(prob(20))
+ C.spew_organ()
sleep(5)
C.blood_volume = 0
return(OXYLOSS|BRUTELOSS)
diff --git a/code/game/machinery/porta_turret/portable_turret.dm b/code/game/machinery/porta_turret/portable_turret.dm
index b8ba21fd35..727124276b 100644
--- a/code/game/machinery/porta_turret/portable_turret.dm
+++ b/code/game/machinery/porta_turret/portable_turret.dm
@@ -364,6 +364,10 @@
var/list/targets = list()
var/turretview = view(scan_range, base)
for(var/A in turretview)
+ var/atom/AA = A
+ if(AA.invisibility>SEE_INVISIBLE_LIVING)
+ continue
+
if(check_anomalies)//if it's set to check for simple animals
if(istype(A, /mob/living/simple_animal))
var/mob/living/simple_animal/SA = A
diff --git a/code/game/machinery/vending.dm b/code/game/machinery/vending.dm
index 7d02e70671..aad16f7e24 100644
--- a/code/game/machinery/vending.dm
+++ b/code/game/machinery/vending.dm
@@ -56,6 +56,7 @@
var/dish_quants = list() //used by the snack machine's custom compartment to count dishes.
var/obj/item/weapon/vending_refill/refill_canister = null //The type of refill canisters used by this machine.
+ var/refill_count = 3 //The number of canisters the vending machine uses
/obj/machinery/vending/Initialize()
..()
@@ -88,7 +89,9 @@
/obj/machinery/vending/cola = "Robust Softdrinks",
/obj/machinery/vending/cigarette = "ShadyCigs Deluxe",
/obj/machinery/vending/autodrobe = "AutoDrobe",
- /obj/machinery/vending/clothing = "ClothesMate")
+ /obj/machinery/vending/clothing = "ClothesMate",
+ /obj/machinery/vending/medical = "NanoMed Plus",
+ /obj/machinery/vending/wallmed = "NanoMed")
/obj/item/weapon/circuitboard/machine/vendor/attackby(obj/item/I, mob/user, params)
if(istype(I, /obj/item/weapon/screwdriver))
@@ -104,7 +107,7 @@
/obj/item/weapon/circuitboard/machine/vendor/proc/set_type(var/obj/machinery/vending/typepath)
build_path = typepath
name = "[names_paths[build_path]] Vendor (Machine Board)"
- req_components = list(initial(typepath.refill_canister) = 3)
+ req_components = list(initial(typepath.refill_canister) = initial(typepath.refill_count))
/obj/item/weapon/circuitboard/machine/vendor/apply_default_parts(obj/machinery/M)
for(var/typepath in names_paths)
@@ -113,7 +116,6 @@
break
..()
-
/obj/machinery/vending/Destroy()
qdel(wires)
wires = null
@@ -307,7 +309,10 @@
if(panel_open)
attack_hand(user)
return
- else if(istype(W, /obj/item/weapon/coin) && premium.len > 0)
+ else if(istype(W, /obj/item/weapon/coin))
+ if(!premium.len)
+ to_chat(user, "[src] doesn't have a coin slot.")
+ return
if(!user.drop_item())
return
W.loc = src
@@ -874,6 +879,7 @@ IF YOU MODIFY THE PRODUCTS LIST OF A MACHINE, MAKE SURE TO UPDATE ITS RESUPPLY C
premium = list(/obj/item/weapon/storage/box/hug/medical = 1,/obj/item/weapon/reagent_containers/hypospray/medipen = 3, /obj/item/weapon/storage/belt/medical = 3, /obj/item/weapon/wrench/medical = 1)
armor = list(melee = 100, bullet = 100, laser = 100, energy = 100, bomb = 0, bio = 0, rad = 0, fire = 100, acid = 50)
resistance_flags = FIRE_PROOF
+ refill_canister = /obj/item/weapon/vending_refill/medical
//This one's from bay12
/obj/machinery/vending/plasmaresearch
@@ -896,6 +902,8 @@ IF YOU MODIFY THE PRODUCTS LIST OF A MACHINE, MAKE SURE TO UPDATE ITS RESUPPLY C
contraband = list(/obj/item/weapon/reagent_containers/pill/tox = 2,/obj/item/weapon/reagent_containers/pill/morphine = 2)
armor = list(melee = 100, bullet = 100, laser = 100, energy = 100, bomb = 0, bio = 0, rad = 0, fire = 100, acid = 50)
resistance_flags = FIRE_PROOF
+ refill_canister = /obj/item/weapon/vending_refill/medical
+ refill_count = 1
/obj/machinery/vending/security
name = "\improper SecTech"
diff --git a/code/game/mecha/equipment/weapons/weapons.dm b/code/game/mecha/equipment/weapons/weapons.dm
index 7a9d01bb7f..658a6a7692 100644
--- a/code/game/mecha/equipment/weapons/weapons.dm
+++ b/code/game/mecha/equipment/weapons/weapons.dm
@@ -107,7 +107,7 @@
icon_state = "mecha_ion"
origin_tech = "materials=4;engineering=4;combat=6;magnets=6"
energy_drain = 500
- projectile = /obj/item/projectile/energy/tesla_cannon
+ projectile = /obj/item/projectile/energy/tesla/cannon
fire_sound = 'sound/magic/lightningbolt.ogg'
diff --git a/code/game/objects/effects/overlays.dm b/code/game/objects/effects/overlays.dm
index 3935b86c92..a6517ccdb5 100644
--- a/code/game/objects/effects/overlays.dm
+++ b/code/game/objects/effects/overlays.dm
@@ -323,11 +323,30 @@
/obj/effect/overlay/temp/ratvar/grille/broken
icon_state = "ratvarbrokengrilleglow"
+/obj/effect/overlay/temp/ratvar/mending_mantra
+ layer = ABOVE_MOB_LAYER
+ duration = 20
+ alpha = 200
+ icon_state = "mending_mantra"
+ light_range = 1.5
+ light_color = "#1E8CE1"
+
+/obj/effect/overlay/temp/ratvar/mending_mantra/Initialize(mapload)
+ . = ..()
+ transform = matrix()*2
+ var/matrix/M = transform
+ M.Turn(90)
+ animate(src, alpha = 20, time = duration, easing = BOUNCE_EASING, flags = ANIMATION_PARALLEL)
+ animate(src, transform = M, time = duration, flags = ANIMATION_PARALLEL)
+
/obj/effect/overlay/temp/ratvar/volt_hit
name = "volt blast"
layer = ABOVE_MOB_LAYER
duration = 5
icon_state = "volt_hit"
+ light_range = 1.5
+ light_power = 2
+ light_color = LIGHT_COLOR_ORANGE
var/mob/user
var/damage = 20
@@ -336,7 +355,6 @@
damage *= multiplier
duration = max(round(damage * 0.2), 1)
. = ..()
- set_light(1.5, 2, LIGHT_COLOR_ORANGE)
/obj/effect/overlay/temp/ratvar/volt_hit/true/Initialize(mapload, caster, multiplier)
. = ..()
diff --git a/code/game/objects/items/devices/flashlight.dm b/code/game/objects/items/devices/flashlight.dm
index 6955872c27..9131c02240 100644
--- a/code/game/objects/items/devices/flashlight.dm
+++ b/code/game/objects/items/devices/flashlight.dm
@@ -37,9 +37,9 @@
return 1
-/obj/item/device/flashlight/attack(mob/living/carbon/human/M, mob/living/carbon/human/user)
+/obj/item/device/flashlight/attack(mob/living/carbon/M, mob/living/carbon/human/user)
add_fingerprint(user)
- if(on && user.zone_selected == "eyes")
+ if(istype(M) && on && user.zone_selected in list("eyes", "mouth"))
if((user.disabilities & CLUMSY || user.getBrainLoss() >= 60) && prob(50)) //too dumb to use flashlight properly
return ..() //just hit them in the head
@@ -48,28 +48,101 @@
to_chat(user, "You don't have the dexterity to do this!")
return
- var/mob/living/carbon/human/H = M //mob has protective eyewear
- if(ishuman(M) && ((H.head && H.head.flags_cover & HEADCOVERSEYES) || (H.wear_mask && H.wear_mask.flags_cover & MASKCOVERSEYES) || (H.glasses && H.glasses.flags_cover & GLASSESCOVERSEYES)))
- to_chat(user, "You're going to need to remove that [(H.head && H.head.flags_cover & HEADCOVERSEYES) ? "helmet" : (H.wear_mask && H.wear_mask.flags_cover & MASKCOVERSEYES) ? "mask": "glasses"] first.")
+ if(!M.get_bodypart("head"))
+ to_chat(user, "[M] doesn't have a head!")
return
- if(M == user) //they're using it on themselves
- if(M.flash_act(visual = 1))
- M.visible_message("[M] directs [src] to [M.p_their()] eyes.", "You wave the light in front of your eyes! Trippy!")
- else
- M.visible_message("[M] directs [src] to [M.p_their()] eyes.", "You wave the light in front of your eyes.")
- else
- user.visible_message("[user] directs [src] to [M]'s eyes.", \
- "You direct [src] to [M]'s eyes.")
- var/mob/living/carbon/C = M
- if(istype(C))
- if(C.stat == DEAD || (C.disabilities & BLIND)) //mob is dead or fully blind
- to_chat(user, "[C] pupils don't react to the light!")
- else if(C.dna.check_mutation(XRAY)) //mob has X-RAY vision
- to_chat(user, "[C] pupils give an eerie glow!")
- else //they're okay!
- if(C.flash_act(visual = 1))
- to_chat(user, "[C]'s pupils narrow.")
+ switch(user.zone_selected)
+ if("eyes")
+ if((M.head && M.head.flags_cover & HEADCOVERSEYES) || (M.wear_mask && M.wear_mask.flags_cover & MASKCOVERSEYES) || (M.glasses && M.glasses.flags_cover & GLASSESCOVERSEYES))
+ to_chat(user, "You're going to need to remove that [(M.head && M.head.flags_cover & HEADCOVERSEYES) ? "helmet" : (M.wear_mask && M.wear_mask.flags_cover & MASKCOVERSEYES) ? "mask": "glasses"] first.")
+ return
+
+ var/obj/item/organ/eyes/E = M.getorganslot("eye_sight")
+ if(!E)
+ to_chat(user, "[M] doesn't have any eyes!")
+ return
+
+ if(M == user) //they're using it on themselves
+ if(M.flash_act(visual = 1))
+ M.visible_message("[M] directs [src] to [M.p_their()] eyes.", "You wave the light in front of your eyes! Trippy!")
+ else
+ M.visible_message("[M] directs [src] to [M.p_their()] eyes.", "You wave the light in front of your eyes.")
+ else
+ user.visible_message("[user] directs [src] to [M]'s eyes.", \
+ "You direct [src] to [M]'s eyes.")
+ if(M.stat == DEAD || (M.disabilities & BLIND) || !M.flash_act(visual = 1)) //mob is dead or fully blind
+ to_chat(user, "[M]'s pupils don't react to the light!")
+ else if(M.dna && M.dna.check_mutation(XRAY)) //mob has X-RAY vision
+ to_chat(user, "[M]'s pupils give an eerie glow!")
+ else //they're okay!
+ to_chat(user, "[M]'s pupils narrow.")
+
+ if("mouth")
+
+ if((M.head && M.head.flags_cover & HEADCOVERSMOUTH) || (M.wear_mask && M.wear_mask.flags_cover & MASKCOVERSMOUTH))
+ to_chat(user, "You're going to need to remove that [(M.head && M.head.flags_cover & HEADCOVERSMOUTH) ? "helmet" : "mask"] first.")
+ return
+
+ var/their = M.p_their()
+
+ var/list/mouth_organs = new
+ for(var/obj/item/organ/O in M.internal_organs)
+ if(O.zone == "mouth")
+ mouth_organs.Add(O)
+ var/organ_list = ""
+ var/organ_count = LAZYLEN(mouth_organs)
+ if(organ_count)
+ for(var/I in 1 to organ_count)
+ if(I > 1)
+ if(I == mouth_organs.len)
+ organ_list += ", and "
+ else
+ organ_list += ", "
+ var/obj/item/organ/O = mouth_organs[I]
+ organ_list += (O.gender == "plural" ? O.name : "\an [O.name]")
+
+ var/pill_count = 0
+ for(var/datum/action/item_action/hands_free/activate_pill/AP in M.actions)
+ pill_count++
+
+ if(M == user)
+ var/can_use_mirror = FALSE
+ if(isturf(user.loc))
+ var/obj/structure/mirror/mirror = locate(/obj/structure/mirror, user.loc)
+ if(mirror)
+ switch(user.dir)
+ if(NORTH)
+ can_use_mirror = mirror.pixel_y > 0
+ if(SOUTH)
+ can_use_mirror = mirror.pixel_y < 0
+ if(EAST)
+ can_use_mirror = mirror.pixel_x > 0
+ if(WEST)
+ can_use_mirror = mirror.pixel_x < 0
+
+ M.visible_message("[M] directs [src] to [their] mouth.", \
+ "You point [src] into your mouth.")
+ if(!can_use_mirror)
+ to_chat(user, "You can't see anything without a mirror.")
+ return
+ if(organ_count)
+ to_chat(user, "Inside your mouth [organ_count > 1 ? "are" : "is"] [organ_list].")
+ else
+ to_chat(user, "There's nothing inside your mouth.")
+ if(pill_count)
+ to_chat(user, "You have [pill_count] implanted pill[pill_count > 1 ? "s" : ""].")
+
+ else
+ user.visible_message("[user] directs [src] to [M]'s mouth.",\
+ "You direct [src] to [M]'s mouth.")
+ if(organ_count)
+ to_chat(user, "Inside [their] mouth [organ_count > 1 ? "are" : "is"] [organ_list].")
+ else
+ to_chat(user, "[M] doesn't have any organs in [their] mouth.")
+ if(pill_count)
+ to_chat(user, "[M] has [pill_count] pill[pill_count > 1 ? "s" : ""] implanted in [their] teeth.")
+
else
return ..()
@@ -280,7 +353,7 @@
return TRUE
/obj/item/device/flashlight/emp/attack(mob/living/M, mob/living/user)
- if(on && user.zone_selected == "eyes") // call original attack proc only if aiming at the eyes
+ if(on && user.zone_selected in list("eyes", "mouth")) // call original attack when examining organs
..()
return
diff --git a/code/game/objects/items/robot/robot_upgrades.dm b/code/game/objects/items/robot/robot_upgrades.dm
index 2aee5acdd9..29463b5a5c 100644
--- a/code/game/objects/items/robot/robot_upgrades.dm
+++ b/code/game/objects/items/robot/robot_upgrades.dm
@@ -237,6 +237,7 @@
/obj/item/borg/upgrade/selfrepair/proc/check_dropped()
if(loc != cyborg)
toggle_action.Remove(cyborg)
+ QDEL_NULL(toggle_action)
cyborg = null
deactivate()
@@ -399,4 +400,4 @@
return
R.make_shell(src)
- return TRUE
\ No newline at end of file
+ return TRUE
diff --git a/code/game/objects/items/stacks/sheets/mineral.dm b/code/game/objects/items/stacks/sheets/mineral.dm
index 611ef76eb4..f32fc2cea4 100644
--- a/code/game/objects/items/stacks/sheets/mineral.dm
+++ b/code/game/objects/items/stacks/sheets/mineral.dm
@@ -29,6 +29,7 @@ Mineral Sheets
GLOBAL_LIST_INIT(sandstone_recipes, list ( \
new/datum/stack_recipe("pile of dirt", /obj/machinery/hydroponics/soil, 3, time = 10, one_per_turf = 1, on_floor = 1), \
new/datum/stack_recipe("sandstone door", /obj/structure/mineral_door/sandstone, 10, one_per_turf = 1, on_floor = 1), \
+ new/datum/stack_recipe("aesthetic volcanic floor tile", /obj/item/stack/tile/basalt, 2, 2, 4, 20), \
new/datum/stack_recipe("Assistant Statue", /obj/structure/statue/sandstone/assistant, 5, one_per_turf = 1, on_floor = 1), \
new/datum/stack_recipe("Breakdown into sand", /obj/item/weapon/ore/glass, 1, one_per_turf = 0, on_floor = 1), \
/* new/datum/stack_recipe("sandstone wall", ???), \
diff --git a/code/game/objects/items/stacks/sheets/sheet_types.dm b/code/game/objects/items/stacks/sheets/sheet_types.dm
index a007dd4545..4700f81d82 100644
--- a/code/game/objects/items/stacks/sheets/sheet_types.dm
+++ b/code/game/objects/items/stacks/sheets/sheet_types.dm
@@ -328,7 +328,7 @@ GLOBAL_LIST_INIT(brass_recipes, list ( \
/obj/item/stack/tile/brass/Initialize(mapload, new_amount, merge = TRUE)
recipes = GLOB.brass_recipes
- ..()
+ . = ..()
pixel_x = 0
pixel_y = 0
diff --git a/code/game/objects/items/stacks/tiles/tile_types.dm b/code/game/objects/items/stacks/tiles/tile_types.dm
index f2432cee3d..ef123030f5 100644
--- a/code/game/objects/items/stacks/tiles/tile_types.dm
+++ b/code/game/objects/items/stacks/tiles/tile_types.dm
@@ -13,8 +13,8 @@
var/turf_type = null
var/mineralType = null
-/obj/item/stack/tile/New(loc, amount)
- ..()
+/obj/item/stack/tile/Initialize(mapload, amount)
+ . = ..()
pixel_x = rand(-3, 3)
pixel_y = rand(-3, 3) //randomize a little
@@ -88,6 +88,14 @@
turf_type = /turf/open/floor/wood
resistance_flags = FLAMMABLE
+//Basalt
+/obj/item/stack/tile/basalt
+ name = "basalt tile"
+ singular_name = "basalt floor tile"
+ desc = "Artificially made ashy soil themed on a hostile enviroment."
+ icon_state = "tile_basalt"
+ origin_tech = "materials=1"
+ turf_type = /turf/open/floor/grass/fakebasalt
//Carpets
/obj/item/stack/tile/carpet
diff --git a/code/game/objects/items/weapons/explosives.dm b/code/game/objects/items/weapons/explosives.dm
index 756512dff1..2ae93fa774 100644
--- a/code/game/objects/items/weapons/explosives.dm
+++ b/code/game/objects/items/weapons/explosives.dm
@@ -81,7 +81,7 @@
to_chat(user, "You start planting the bomb...")
- if(do_after(user, 50, target = AM))
+ if(do_after(user, 50, target = AM))
if(!user.temporarilyRemoveItemFromInventory(src))
return
src.target = AM
diff --git a/code/game/objects/items/weapons/grenades/plastic.dm b/code/game/objects/items/weapons/grenades/plastic.dm
index aedf0954c2..023635c977 100644
--- a/code/game/objects/items/weapons/grenades/plastic.dm
+++ b/code/game/objects/items/weapons/grenades/plastic.dm
@@ -96,7 +96,7 @@
to_chat(user, "You start planting the [src]. The timer is set to [det_time]...")
- if(do_after(user, 50, target = AM))
+ if(do_after(user, 30, target = AM))
if(!user.temporarilyRemoveItemFromInventory(src))
return
src.target = AM
@@ -165,4 +165,4 @@
icon_state = "plasticx40"
item_state = "plasticx4"
directional = TRUE
- boom_sizes = list(0, 2, 5)
\ No newline at end of file
+ boom_sizes = list(0, 2, 5)
diff --git a/code/game/objects/items/weapons/grenades/spawnergrenade.dm b/code/game/objects/items/weapons/grenades/spawnergrenade.dm
index 2d5c4707a6..86c01d745e 100644
--- a/code/game/objects/items/weapons/grenades/spawnergrenade.dm
+++ b/code/game/objects/items/weapons/grenades/spawnergrenade.dm
@@ -1,5 +1,5 @@
/obj/item/weapon/grenade/spawnergrenade
- desc = "It will unleash unleash an unspecified anomaly into the vicinity."
+ desc = "It will unleash an unspecified anomaly into the vicinity."
name = "delivery grenade"
icon = 'icons/obj/grenade.dmi'
icon_state = "delivery"
diff --git a/code/game/objects/items/weapons/his_grace.dm b/code/game/objects/items/weapons/his_grace.dm
index be269d583d..d8e7dabdf9 100644
--- a/code/game/objects/items/weapons/his_grace.dm
+++ b/code/game/objects/items/weapons/his_grace.dm
@@ -41,7 +41,7 @@
..()
/obj/item/weapon/his_grace/CtrlClick(mob/user) //you can't pull his grace
- attack_hand(user)
+ return
/obj/item/weapon/his_grace/examine(mob/user)
..()
diff --git a/code/game/objects/items/weapons/storage/uplink_kits.dm b/code/game/objects/items/weapons/storage/uplink_kits.dm
index 335545e8c9..9cf806f6b3 100644
--- a/code/game/objects/items/weapons/storage/uplink_kits.dm
+++ b/code/game/objects/items/weapons/storage/uplink_kits.dm
@@ -219,7 +219,8 @@
new /obj/item/weapon/reagent_containers/glass/bottle/polonium(src)
new /obj/item/weapon/reagent_containers/glass/bottle/venom(src)
new /obj/item/weapon/reagent_containers/glass/bottle/neurotoxin2(src)
- new /obj/item/weapon/reagent_containers/glass/bottle/formaldehyde(src)
+ new /obj/item/weapon/reagent_containers/glass/bottle/formaldehyde(src)
+ new /obj/item/weapon/reagent_containers/glass/bottle/spewium(src)
new /obj/item/weapon/reagent_containers/glass/bottle/cyanide(src)
new /obj/item/weapon/reagent_containers/glass/bottle/histamine(src)
new /obj/item/weapon/reagent_containers/glass/bottle/initropidril(src)
diff --git a/code/game/objects/items/weapons/vending_items.dm b/code/game/objects/items/weapons/vending_items.dm
index 74ab7be4b6..c93dcaca3b 100644
--- a/code/game/objects/items/weapons/vending_items.dm
+++ b/code/game/objects/items/weapons/vending_items.dm
@@ -71,3 +71,9 @@
icon_state = "refill_clothes"
charges = list(31, 4, 4)// of 101 standard, 12 contraband, 10 premium(?)
init_charges = list(31, 4, 4)
+
+/obj/item/weapon/vending_refill/medical
+ machine_name = "NanoMed"
+ icon_state = "refill_medical"
+ charges = list(26, 5, 3)// of 76 standard, 13 contraband, 8 premium
+ init_charges = list(26, 5, 3)
\ No newline at end of file
diff --git a/code/game/objects/structures/aliens.dm b/code/game/objects/structures/aliens.dm
index d46136a9ae..6212133b12 100644
--- a/code/game/objects/structures/aliens.dm
+++ b/code/game/objects/structures/aliens.dm
@@ -298,7 +298,7 @@
else
for(var/mob/M in range(1,src))
if(CanHug(M))
- child.Attach(M)
+ child.Leap(M)
break
/obj/structure/alien/egg/obj_break(damage_flag)
diff --git a/code/game/objects/structures/displaycase.dm b/code/game/objects/structures/displaycase.dm
index be1b49074d..3817a16685 100644
--- a/code/game/objects/structures/displaycase.dm
+++ b/code/game/objects/structures/displaycase.dm
@@ -16,27 +16,25 @@
var/obj/item/weapon/electronics/airlock/electronics
var/start_showpiece_type = null //add type for items on display
-/obj/structure/displaycase/New()
- ..()
+/obj/structure/displaycase/Initialize()
+ . = ..()
if(start_showpiece_type)
showpiece = new start_showpiece_type (src)
update_icon()
/obj/structure/displaycase/Destroy()
if(electronics)
- qdel(electronics)
- electronics = null
+ QDEL_NULL(electronics)
if(showpiece)
- qdel(showpiece)
- showpiece = null
+ QDEL_NULL(showpiece)
return ..()
/obj/structure/displaycase/examine(mob/user)
..()
- if(showpiece)
- to_chat(user, "There's [showpiece] inside.")
if(alert)
to_chat(user, "Hooked up with an anti-theft system.")
+ if(showpiece)
+ to_chat(user, "There's [showpiece] inside.")
/obj/structure/displaycase/proc/dump()
@@ -176,8 +174,8 @@
/obj/structure/displaycase/attack_hand(mob/user)
user.changeNext_move(CLICK_CD_MELEE)
if (showpiece && (broken || open))
- dump()
to_chat(user, "You deactivate the hover field built into the case.")
+ dump()
src.add_fingerprint(user)
update_icon()
return
@@ -249,3 +247,96 @@
desc = "A glass lab container for storing interesting creatures."
start_showpiece_type = /obj/item/clothing/mask/facehugger/lamarr
req_access = list(GLOB.access_rd)
+
+
+
+/obj/structure/displaycase/trophy
+ name = "trophy display case"
+ desc = "Store your trophies of accomplishment in here, and they will stay forever."
+ var/trophy_message = ""
+ var/placer_key = ""
+ var/added_roundstart = TRUE
+ alert = TRUE
+ integrity_failure = 0
+
+/obj/structure/displaycase/trophy/Initialize()
+ . = ..()
+ GLOB.trophy_cases += src
+
+/obj/structure/displaycase/trophy/Destroy()
+ GLOB.trophy_cases -= src
+ return ..()
+
+/obj/structure/displaycase/trophy/examine(mob/user)
+ ..()
+ if(trophy_message)
+ to_chat(user, "The plaque reads:")
+ to_chat(user, trophy_message)
+
+/obj/structure/displaycase/trophy/attackby(obj/item/weapon/W, mob/user, params)
+
+ if(!user.Adjacent(src)) //no TK museology
+ return
+
+ if(!added_roundstart)
+ to_chat(user, "You've already put something new in this case.")
+ return
+
+ if(is_type_in_typecache(W, GLOB.blacklisted_cargo_types))
+ to_chat(user, "The case rejects the [W].")
+ return
+
+ for(var/a in W.GetAllContents())
+ if(is_type_in_typecache(a, GLOB.blacklisted_cargo_types))
+ to_chat(user, "The case rejects the [W].")
+ return
+
+ if(user.drop_item())
+
+ if(showpiece)
+ to_chat(user, "You press a button, and [showpiece] descends into the floor of the case.")
+ QDEL_NULL(showpiece)
+
+ to_chat(user, "You insert [W] into the case.")
+ W.forceMove(src)
+ showpiece = W
+ added_roundstart = FALSE
+ update_icon()
+
+ placer_key = user.ckey
+
+ trophy_message = W.desc //default value
+
+ var/chosen_plaque = stripped_input(user, "What would you like the plaque to say? Default value is item's description.", "Trophy Plaque")
+ if(chosen_plaque)
+ if(user.Adjacent(src))
+ trophy_message = chosen_plaque
+ to_chat(user, "You set the plaque's text.")
+ else
+ to_chat(user, "You are too far to set the plaque's text.")
+
+ SSpersistence.SaveTrophy(src)
+
+ else
+ to_chat(user, "\The [W] is stuck to your hand, you can't put it in the [src.name]!")
+
+ return
+
+/obj/structure/displaycase/trophy/dump()
+ if (showpiece)
+ if(added_roundstart)
+ visible_message("The [showpiece] crumbles to dust!")
+ new /obj/effect/decal/cleanable/ash(loc)
+ QDEL_NULL(showpiece)
+ else
+ ..()
+
+/obj/item/showpiece_dummy
+ name = "Cheap replica"
+
+/obj/item/showpiece_dummy/Initialize(mapload, path)
+ . = ..()
+ var/obj/item/I = path
+ name = initial(I.name)
+ icon = initial(I.icon)
+ icon_state = initial(I.icon_state)
diff --git a/code/game/objects/structures/flora.dm b/code/game/objects/structures/flora.dm
index cdd706e5df..c00348a2c6 100644
--- a/code/game/objects/structures/flora.dm
+++ b/code/game/objects/structures/flora.dm
@@ -88,7 +88,7 @@
pixel_y = -20
/obj/structure/flora/tree/jungle/Initialize()
- icon_state = "[icon_state][rand(1, 3)]"
+ icon_state = "[icon_state][rand(1, 6)]"
..()
//grass
diff --git a/code/game/turfs/simulated/chasm.dm b/code/game/turfs/simulated/chasm.dm
index 8890c50129..8b24a4c816 100644
--- a/code/game/turfs/simulated/chasm.dm
+++ b/code/game/turfs/simulated/chasm.dm
@@ -143,14 +143,14 @@
qdel(S.mmi)
qdel(AM)
-
+
if(AM && !QDELETED(AM)) //It's indestructible
visible_message("[src] spits out the [AM]!")
AM.alpha = oldalpha
AM.color = oldcolor
AM.transform = oldtransform
AM.throw_at(get_edge_target_turf(src,pick(GLOB.alldirs)),rand(1, 10),rand(1, 10))
-
+
/turf/open/chasm/straight_down/lava_land_surface/normal_air
initial_gas_mix = "o2=22;n2=82;TEMP=293.15"
@@ -158,3 +158,17 @@
/turf/open/chasm/CanPass(atom/movable/mover, turf/target, height=0)
return 1
+
+
+
+//Jungle
+
+/turf/open/chasm/jungle
+ icon = 'icons/turf/floors/junglechasm.dmi'
+ planetary_atmos = TRUE
+ initial_gas_mix = "o2=14;n2=23;TEMP=300"
+
+/turf/open/chasm/straight_down/jungle
+ icon = 'icons/turf/floors/junglechasm.dmi'
+ planetary_atmos = TRUE
+ initial_gas_mix = "o2=14;n2=23;TEMP=300"
\ No newline at end of file
diff --git a/code/game/turfs/simulated/floor/fancy_floor.dm b/code/game/turfs/simulated/floor/fancy_floor.dm
index eaba3d50eb..cce7756892 100644
--- a/code/game/turfs/simulated/floor/fancy_floor.dm
+++ b/code/game/turfs/simulated/floor/fancy_floor.dm
@@ -1,6 +1,7 @@
/* In this file:
* Wood floor
* Grass floor
+ * Fake Basalt
* Carpet floor
* Fake pits
* Fake space
@@ -67,6 +68,7 @@
broken_states = list("sand")
flags = NONE
var/ore_type = /obj/item/weapon/ore/glass
+ var/turfverb = "uproot"
/turf/open/floor/grass/Initialize()
..()
@@ -76,7 +78,7 @@
if(istype(C, /obj/item/weapon/shovel) && params)
new ore_type(src)
new ore_type(src) //Make some sand if you shovel grass
- user.visible_message("[user] digs up [src].", "You uproot [src].")
+ user.visible_message("[user] digs up [src].", "You [src.turfverb] [src].")
playsound(src, 'sound/effects/shovel_dig.ogg', 50, 1)
make_plating()
if(..())
@@ -93,7 +95,6 @@
initial_gas_mix = "o2=22;n2=82;TEMP=180"
slowdown = 2
-
/turf/open/floor/grass/snow/attackby(obj/item/W, mob/user, params)
if(istype(W, /obj/item/weapon/crowbar))//You need to dig this turf out instead of crowbarring it
return
@@ -113,6 +114,24 @@
icon_state = "basalt[rand(0, 12)]"
set_basalt_light(src)
+
+/turf/open/floor/grass/fakebasalt //Heart is not a real planeteer power
+ name = "aesthetic volcanic flooring"
+ desc = "Safely recreated turf for your hellplanet-scaping"
+ icon = 'icons/turf/floors.dmi'
+ icon_state = "basalt"
+ floor_tile = /obj/item/stack/tile/basalt
+ ore_type = /obj/item/weapon/ore/glass/basalt
+ turfverb = "dig up"
+ slowdown = 0
+
+/turf/open/floor/grass/fakebasalt/Initialize()
+ ..()
+ if(prob(15))
+ icon_state = "basalt[rand(0, 12)]"
+ set_basalt_light(src)
+
+
/turf/open/floor/carpet
name = "carpet"
desc = "Soft velvet carpeting. Feels good between your toes."
diff --git a/code/game/turfs/simulated/floor/plating/dirt.dm b/code/game/turfs/simulated/floor/plating/dirt.dm
index 580aadc85f..0d13b93432 100644
--- a/code/game/turfs/simulated/floor/plating/dirt.dm
+++ b/code/game/turfs/simulated/floor/plating/dirt.dm
@@ -3,19 +3,9 @@
desc = "Upon closer examination, it's still dirt."
icon = 'icons/turf/floors.dmi'
icon_state = "dirt"
- var/smooth_icon = 'icons/turf/floors/dirt.dmi'
- canSmoothWith = list(/turf/closed, /turf/open/floor/plating/dirt)
- smooth = SMOOTH_MORE|SMOOTH_BORDER
- baseturf = /turf/open/chasm/straight_down/lava_land_surface
+ baseturf = /turf/open/chasm/straight_down/jungle
initial_gas_mix = "o2=14;n2=23;TEMP=300"
planetary_atmos = TRUE
-/turf/open/floor/plating/dirt/Initialize()
- pixel_y = -2
- pixel_x = -2
- icon = smooth_icon
- ..()
-
/turf/open/floor/plating/dirt/dark
- icon_state = "darkdirt"
- smooth_icon = 'icons/turf/floors/darkdirt.dmi'
+ icon_state = "greenerdirt"
diff --git a/code/modules/admin/topic.dm.rej b/code/modules/admin/topic.dm.rej
deleted file mode 100644
index 041ae92107..0000000000
--- a/code/modules/admin/topic.dm.rej
+++ /dev/null
@@ -1,10 +0,0 @@
-diff a/code/modules/admin/topic.dm b/code/modules/admin/topic.dm (rejected hunks)
-@@ -8,7 +8,7 @@
- if(href_list["ahelp"])
- if(!check_rights(R_ADMIN))
- return
--
-+
- var/ahelp_ref = href_list["ahelp"]
- var/datum/admin_help/AH = locate(ahelp_ref)
- if(AH)
diff --git a/code/modules/admin/verbs/deadsay.dm b/code/modules/admin/verbs/deadsay.dm
index 37af9e8601..500edfe665 100644
--- a/code/modules/admin/verbs/deadsay.dm
+++ b/code/modules/admin/verbs/deadsay.dm
@@ -19,7 +19,7 @@
if (!msg)
return
- var/nicknames = world.file2list("config/admin_nicknames.txt")
+ var/static/nicknames = world.file2list("config/admin_nicknames.txt")
var/rendered = "DEAD: ADMIN([src.holder.fakekey ? pick(nicknames) : src.key]) says, \"[msg]\""
diff --git a/code/modules/admin/verbs/playsound.dm b/code/modules/admin/verbs/playsound.dm
index f417dfbad3..2397f6c4a5 100644
--- a/code/modules/admin/verbs/playsound.dm
+++ b/code/modules/admin/verbs/playsound.dm
@@ -21,7 +21,7 @@
var/res = alert(usr, "Show the title of this song to the players?",, "No", "Yes", "Cancel")
switch(res)
if("Yes")
- to_chat(world, "An admin played: [S]")
+ to_chat(world, "An admin played: [S]")
if("Cancel")
return
diff --git a/code/modules/admin/verbs/randomverbs.dm b/code/modules/admin/verbs/randomverbs.dm
index 547e8e1d03..f1bf4d6969 100644
--- a/code/modules/admin/verbs/randomverbs.dm
+++ b/code/modules/admin/verbs/randomverbs.dm
@@ -350,7 +350,6 @@ Traitors and the like can also be revived with the previous role mostly intact.
if(G_found.mind && !G_found.mind.active)
G_found.mind.transfer_to(new_character) //be careful when doing stuff like this! I've already checked the mind isn't in use
- new_character.mind.special_verbs = list()
else
new_character.mind_initialize()
if(!new_character.mind.assigned_role)
diff --git a/code/modules/awaymissions/gateway.dm b/code/modules/awaymissions/gateway.dm
index 80d6d84a68..c46399fa29 100644
--- a/code/modules/awaymissions/gateway.dm
+++ b/code/modules/awaymissions/gateway.dm
@@ -227,7 +227,7 @@ GLOBAL_DATUM(the_gateway, /obj/machinery/gateway/centerstation)
if(check_exile_implant(C))
say("Rejecting [AM]: Exile implant detected in contained lifeform.")
return
- if(AM.buckled_mobs.len)
+ if(AM.has_buckled_mobs())
for(var/mob/living/carbon/C in AM.buckled_mobs)
if(check_exile_implant(C))
say("Rejecting [AM]: Exile implant detected in close proximity lifeform.")
diff --git a/code/modules/cargo/exports/materials.dm b/code/modules/cargo/exports/materials.dm
index c2a0734958..8f3292df3a 100644
--- a/code/modules/cargo/exports/materials.dm
+++ b/code/modules/cargo/exports/materials.dm
@@ -50,11 +50,6 @@
material_id = MAT_PLASMA
message = "cm3 of plasma"
-/datum/export/material/plasma/get_cost(obj/O, contr = 0, emag = 0)
- . = ..()
- if(emag) // Syndicate pays you more for the plasma.
- . = round(. * 1.5)
-
// Uranium. Still useful for both power generation and nuclear annihilation.
/datum/export/material/uranium
cost = 400
@@ -98,4 +93,4 @@
message = "cm3 of glass"
material_id = MAT_GLASS
export_types = list(/obj/item/stack/sheet/glass, /obj/item/weapon/ore,
- /obj/item/weapon/shard)
\ No newline at end of file
+ /obj/item/weapon/shard)
diff --git a/code/modules/cargo/packs.dm b/code/modules/cargo/packs.dm
index 7686a7a4bf..895c042e00 100644
--- a/code/modules/cargo/packs.dm
+++ b/code/modules/cargo/packs.dm
@@ -182,14 +182,14 @@
/datum/supply_pack/emergency/syndicate
name = "NULL_ENTRY"
hidden = TRUE
- cost = 14000
+ cost = 20000
contains = list()
crate_name = "emergency crate"
crate_type = /obj/structure/closet/crate/internals
dangerous = TRUE
/datum/supply_pack/emergency/syndicate/fill(obj/structure/closet/crate/C)
- var/crate_value = 50
+ var/crate_value = 30
var/list/uplink_items = get_uplink_items(SSticker.mode)
while(crate_value)
var/category = pick(uplink_items)
@@ -828,6 +828,14 @@
/obj/item/weapon/defibrillator/loaded)
crate_name = "defibrillator crate"
+/datum/supply_pack/medical/vending
+ name = "Medical Vending Crate"
+ cost = 2000
+ contains = list(/obj/item/weapon/vending_refill/medical,
+ /obj/item/weapon/vending_refill/medical,
+ /obj/item/weapon/vending_refill/medical)
+ crate_name = "medical vending crate"
+
//////////////////////////////////////////////////////////////////////////////
//////////////////////////// Science /////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////
diff --git a/code/modules/client/verbs/suicide.dm b/code/modules/client/verbs/suicide.dm
index 6847a7c1f4..1f50a697c2 100644
--- a/code/modules/client/verbs/suicide.dm
+++ b/code/modules/client/verbs/suicide.dm
@@ -13,8 +13,8 @@
return
if(confirm == "Yes")
suiciding = 1
- log_game("[key_name(src)] (job: [job ? "[job]" : "None"]) commited suicide at [get_area(src)].")
- message_admins("[key_name(src)] (job: [job ? "[job]" : "None"]) commited suicide at [get_area(src)].")
+ log_game("[key_name(src)] (job: [job ? "[job]" : "None"]) committed suicide at [get_area(src)].")
+ message_admins("[key_name(src)] (job: [job ? "[job]" : "None"]) committed suicide at [get_area(src)].")
var/obj/item/held_item = get_active_held_item()
if(held_item)
var/damagetype = held_item.suicide_act(src)
diff --git a/code/modules/clothing/spacesuits/flightsuit.dm b/code/modules/clothing/spacesuits/flightsuit.dm
index 275ad542b5..b1c0bb325d 100644
--- a/code/modules/clothing/spacesuits/flightsuit.dm
+++ b/code/modules/clothing/spacesuits/flightsuit.dm
@@ -326,9 +326,6 @@
disable_flight(1)
if(!suit)
disable_flight(1)
- if(!resync)
- addtimer(CALLBACK(src, .proc/resync), 600)
- resync = 1
if(!wearer) //Oh god our user fell off!
disable_flight(1)
if(!pressure && brake)
@@ -340,12 +337,6 @@
stabilizer = FALSE
usermessage("Warning: Sensor data is not being recieved from flight shoes. Stabilizers and airbrake modules OFFLINE!", 2)
-//Resync the suit
-/obj/item/device/flightpack/proc/resync()
- resync = FALSE
- suit.resync()
-
-//How fast should the wearer be?
/obj/item/device/flightpack/proc/update_slowdown()
if(!flight)
suit.slowdown = slowdown_ground
@@ -356,20 +347,11 @@
/obj/item/device/flightpack/process()
if(!suit || (processing_mode == FLIGHTSUIT_PROCESSING_NONE))
return FALSE
- update_slowdown()
- update_icon()
check_conditions()
calculate_momentum_speed()
momentum_drift()
handle_boost()
handle_damage()
- handle_flight()
-
-/obj/item/device/flightpack/proc/handle_flight()
- if(!flight)
- return FALSE
- if(wearer)
- wearer.float(TRUE)
/obj/item/device/flightpack/proc/handle_damage()
if(crash_damage)
@@ -424,7 +406,6 @@
if(boost_charge < boost_maxcharge)
boost_charge = Clamp(boost_charge+boost_chargerate, 0, boost_maxcharge)
-
/obj/item/device/flightpack/proc/cycle_power()
if(powersetting < powersetting_high)
powersetting++
@@ -654,6 +635,8 @@
wearer.movement_type |= FLYING
wearer.pass_flags |= flight_passflags
usermessage("ENGAGING FLIGHT ENGINES.")
+ update_slowdown()
+ wearer.floating = TRUE
wearer.visible_message("[wearer]'s flight engines activate as they lift into the air!")
//I DONT HAVE SOUND EFFECTS YET playsound(
flight = TRUE
@@ -670,6 +653,8 @@
momentum_x = 0
momentum_y = 0
usermessage("DISENGAGING FLIGHT ENGINES.")
+ update_slowdown()
+ wearer.floating = FALSE
wearer.visible_message("[wearer] drops to the ground as their flight engines cut out!")
//NO SOUND YET playsound(
ion_trail.stop()
@@ -678,6 +663,9 @@
flight = FALSE
if(suit.shoes)
suit.shoes.toggle(FALSE)
+ if(isturf(wearer.loc))
+ var/turf/T = wearer.loc
+ T.Entered(src)
else
if(override_safe)
disable_flight(TRUE)
@@ -749,11 +737,13 @@
wearer.visible_message("[wearer.name]'s flightpack engines flare in intensity as they are rocketed forward by the immense thrust!")
boost = TRUE
update_slowdown()
+ update_icon()
/obj/item/device/flightpack/proc/deactivate_booster()
usermessage("Boosters disengaged!")
boost = FALSE
update_slowdown()
+ update_icon()
/obj/item/device/flightpack/proc/enable_airbrake()
if(wearer)
diff --git a/code/modules/detectivework/scanner.dm b/code/modules/detectivework/scanner.dm
index 92437a34c1..562f59290a 100644
--- a/code/modules/detectivework/scanner.dm
+++ b/code/modules/detectivework/scanner.dm
@@ -13,6 +13,8 @@
var/scanning = 0
var/list/log = list()
origin_tech = "engineering=4;biotech=2;programming=5"
+ var/range = 8
+ var/view_check = TRUE
/obj/item/device/detective_scanner/attack_self(mob/user)
if(log.len && !scanning)
@@ -43,7 +45,7 @@
log = list()
scanning = 0
-/obj/item/device/detective_scanner/pre_attackby(atom/A, mob/user, params)
+/obj/item/device/detective_scanner/afterattack(atom/A, mob/user, params)
scan(A, user)
return FALSE
@@ -51,9 +53,7 @@
set waitfor = 0
if(!scanning)
// Can remotely scan objects and mobs.
- if(!in_range(A, user) && !(A in view(world.view, user)))
- return
- if(loc != user)
+ if((get_dist(A, user) > range) || (!(A in view(range, user)) && view_check) || (loc != user))
return
scanning = 1
diff --git a/code/modules/food_and_drinks/food/snacks_pastry.dm b/code/modules/food_and_drinks/food/snacks_pastry.dm
index 76ef327bb6..6081838669 100644
--- a/code/modules/food_and_drinks/food/snacks_pastry.dm
+++ b/code/modules/food_and_drinks/food/snacks_pastry.dm
@@ -13,8 +13,8 @@
filling_color = "#D2691E"
tastes = list("donut" = 1)
-/obj/item/weapon/reagent_containers/food/snacks/donut/New()
- ..()
+/obj/item/weapon/reagent_containers/food/snacks/donut/Initialize()
+ . = ..()
if(prob(30))
icon_state = "donut2"
name = "frosted donut"
@@ -28,8 +28,8 @@
bitesize = 10
tastes = list("donut" = 3, "chaos" = 1)
-/obj/item/weapon/reagent_containers/food/snacks/donut/chaos/New()
- ..()
+/obj/item/weapon/reagent_containers/food/snacks/donut/chaos/Initialize()
+ . = ..()
extra_reagent = pick("nutriment", "capsaicin", "frostoil", "krokodil", "plasma", "cocoa", "slimejelly", "banana", "berryjuice", "omnizine")
reagents.add_reagent("[extra_reagent]", 3)
bonus_reagents = list("[extra_reagent]" = 3, "sugar" = 1)
@@ -48,8 +48,8 @@
extra_reagent = "berryjuice"
tastes = list("jelly" = 1, "donut" = 3)
-/obj/item/weapon/reagent_containers/food/snacks/donut/jelly/New()
- ..()
+/obj/item/weapon/reagent_containers/food/snacks/donut/jelly/Initialize()
+ . = ..()
if(extra_reagent)
reagents.add_reagent("[extra_reagent]", 3)
if(prob(30))
@@ -210,13 +210,13 @@
filling_color = "#F0E68C"
tastes = list("mushroom" = 1, "biscuit" = 1)
-/obj/item/weapon/reagent_containers/food/snacks/plumphelmetbiscuit/New()
+/obj/item/weapon/reagent_containers/food/snacks/plumphelmetbiscuit/Initialize()
var/fey = prob(10)
if(fey)
name = "exceptional plump helmet biscuit"
desc = "Microwave is taken by a fey mood! It has cooked an exceptional plump helmet biscuit!"
bonus_reagents = list("omnizine" = 5, "nutriment" = 1, "vitamin" = 1)
- ..()
+ . = ..()
if(fey)
reagents.add_reagent("omnizine", 5)
diff --git a/code/modules/food_and_drinks/food/snacks_soup.dm b/code/modules/food_and_drinks/food/snacks_soup.dm
index 79df428ebb..e11231fdfc 100644
--- a/code/modules/food_and_drinks/food/snacks_soup.dm
+++ b/code/modules/food_and_drinks/food/snacks_soup.dm
@@ -128,6 +128,13 @@
list_reagents = list("nutriment" = 5, "tomatojuice" = 10, "vitamin" = 3)
tastes = list("tomato" = 1)
+/obj/item/weapon/reagent_containers/food/snacks/soup/tomato/eyeball
+ name = "eyeball soup"
+ desc = "It looks back at you..."
+ icon_state = "eyeballsoup"
+ bonus_reagents = list("nutriment" = 1, "liquidgibs" = 3)
+ tastes = list("tomato" = 1, "squirming" = 1)
+
/obj/item/weapon/reagent_containers/food/snacks/soup/milo
name = "milosoup"
desc = "The universes best soup! Yum!!!"
@@ -196,5 +203,3 @@
icon_state = "redbeetsoup"
bonus_reagents = list("nutriment" = 4, "vitamin" = 6)
tastes = list("beet" = 1)
-
-
diff --git a/code/modules/food_and_drinks/food/snacks_spaghetti.dm b/code/modules/food_and_drinks/food/snacks_spaghetti.dm
index fd17c0ebd5..dc3aa60115 100644
--- a/code/modules/food_and_drinks/food/snacks_spaghetti.dm
+++ b/code/modules/food_and_drinks/food/snacks_spaghetti.dm
@@ -83,5 +83,5 @@
icon = 'icons/obj/food/pizzaspaghetti.dmi'
icon_state = "beefnoodle"
trash = /obj/item/weapon/reagent_containers/glass/bowl
- bonus_reagents = list("nutriment" = 5, "vitamin" = 6)
+ bonus_reagents = list("nutriment" = 5, "vitamin" = 6, "liquidgibs" = 3)
tastes = list("noodle" = 1, "meat" = 1)
diff --git a/code/modules/food_and_drinks/recipes/tablecraft/recipes_soup.dm b/code/modules/food_and_drinks/recipes/tablecraft/recipes_soup.dm
index 050beb8478..8ab865f65d 100644
--- a/code/modules/food_and_drinks/recipes/tablecraft/recipes_soup.dm
+++ b/code/modules/food_and_drinks/recipes/tablecraft/recipes_soup.dm
@@ -91,6 +91,18 @@
result = /obj/item/weapon/reagent_containers/food/snacks/soup/tomato
category = CAT_SOUP
+/datum/crafting_recipe/food/eyeballsoup
+ name = "Eyeball soup"
+ reqs = list(
+ /datum/reagent/water = 10,
+ /obj/item/weapon/reagent_containers/glass/bowl = 1,
+ /obj/item/weapon/reagent_containers/food/snacks/grown/tomato = 2,
+ /obj/item/organ/eyes = 1
+ )
+ result = /obj/item/weapon/reagent_containers/food/snacks/soup/tomato/eyeball
+ category = CAT_SOUP
+
+
/datum/crafting_recipe/food/milosoup
name = "Milo soup"
reqs = list(
diff --git a/code/modules/hydroponics/grown.dm b/code/modules/hydroponics/grown.dm
index 555df764b8..5104ab333a 100644
--- a/code/modules/hydroponics/grown.dm
+++ b/code/modules/hydroponics/grown.dm
@@ -111,6 +111,7 @@
for(var/datum/plant_gene/trait/trait in seed.genes)
trait.on_squash(src, target)
+ reagents.reaction(T)
for(var/A in T)
reagents.reaction(A)
diff --git a/code/modules/mining/machine_redemption.dm b/code/modules/mining/machine_redemption.dm
index d93bcb5028..f3b66d9172 100644
--- a/code/modules/mining/machine_redemption.dm
+++ b/code/modules/mining/machine_redemption.dm
@@ -84,7 +84,7 @@
if(D.make_reagents.len)
return 0
- var/build_amount = 1
+ var/build_amount = 0
for(var/mat_id in D.materials)
var/M = D.materials[mat_id]
@@ -93,7 +93,15 @@
if(!M || !redemption_mat)
return 0
- build_amount = min(build_amount, round(redemption_mat.amount / M))
+ var/smeltable_sheets = round(redemption_mat.amount / M)
+
+ if(!smeltable_sheets)
+ return 0
+
+ if(!build_amount)
+ build_amount = smeltable_sheets
+
+ build_amount = min(build_amount, smeltable_sheets)
return build_amount
@@ -152,6 +160,7 @@
if(exchange_parts(user, W))
return
if(default_pry_open(W))
+ materials.retrieve_all()
return
if(default_unfasten_wrench(user, W))
return
diff --git a/code/modules/mob/living/blood.dm b/code/modules/mob/living/blood.dm
index ca380170f7..ca8b8f2d9d 100644
--- a/code/modules/mob/living/blood.dm
+++ b/code/modules/mob/living/blood.dm
@@ -35,22 +35,21 @@
blood_volume += 0.1 // regenerate blood VERY slowly
//Effects of bloodloss
+ var/word = pick("dizzy","woozy","faint")
switch(blood_volume)
if(BLOOD_VOLUME_OKAY to BLOOD_VOLUME_SAFE)
if(prob(5))
- to_chat(src, "You feel [pick("dizzy","woozy","faint")].")
+ to_chat(src, "You feel [word].")
adjustOxyLoss(round((BLOOD_VOLUME_NORMAL - blood_volume) * 0.01, 1))
if(BLOOD_VOLUME_BAD to BLOOD_VOLUME_OKAY)
adjustOxyLoss(round((BLOOD_VOLUME_NORMAL - blood_volume) * 0.02, 1))
if(prob(5))
blur_eyes(6)
- var/word = pick("dizzy","woozy","faint")
to_chat(src, "You feel very [word].")
if(BLOOD_VOLUME_SURVIVE to BLOOD_VOLUME_BAD)
adjustOxyLoss(5)
if(prob(15))
Paralyse(rand(1,3))
- var/word = pick("dizzy","woozy","faint")
to_chat(src, "You feel extremely [word].")
if(0 to BLOOD_VOLUME_SURVIVE)
death()
@@ -70,7 +69,7 @@
bleed_rate = max(bleed_rate - 0.5, temp_bleed)//if no wounds, other bleed effects (heparin) naturally decreases
- if(bleed_rate && !bleedsuppress)
+ if(bleed_rate && !bleedsuppress && !(status_flags & FAKEDEATH))
bleed(bleed_rate)
//Makes a blood drop, leaking amt units of blood from the mob
diff --git a/code/modules/mob/living/carbon/alien/organs.dm b/code/modules/mob/living/carbon/alien/organs.dm
index 8a9ee012d9..f9bd64153e 100644
--- a/code/modules/mob/living/carbon/alien/organs.dm
+++ b/code/modules/mob/living/carbon/alien/organs.dm
@@ -87,6 +87,8 @@
owner.adjustFireLoss(-heal_amt)
owner.adjustOxyLoss(-heal_amt)
owner.adjustCloneLoss(-heal_amt)
+ else
+ owner.adjustPlasma(plasma_rate * 0.1)
/obj/item/organ/alien/plasmavessel/Insert(mob/living/carbon/M, special = 0)
..()
diff --git a/code/modules/mob/living/carbon/alien/say.dm b/code/modules/mob/living/carbon/alien/say.dm
index 72162387ee..12c131b3cc 100644
--- a/code/modules/mob/living/carbon/alien/say.dm
+++ b/code/modules/mob/living/carbon/alien/say.dm
@@ -1,4 +1,4 @@
-/mob/living/proc/alien_talk(message, shown_name = name)
+/mob/living/proc/alien_talk(message, shown_name = real_name)
log_say("[key_name(src)] : [message]")
message = trim(message)
if(!message) return
diff --git a/code/modules/mob/living/carbon/carbon.dm b/code/modules/mob/living/carbon/carbon.dm
index 87cf246717..06145235a0 100644
--- a/code/modules/mob/living/carbon/carbon.dm
+++ b/code/modules/mob/living/carbon/carbon.dm
@@ -484,7 +484,7 @@
adjustBruteLoss(3)
else
if(T)
- T.add_vomit_floor(src, 0)//toxic barf looks different
+ T.add_vomit_floor(src, toxic)//toxic barf looks different
nutrition -= lost_nutrition
adjustToxLoss(-3)
T = get_step(T, dir)
@@ -492,6 +492,16 @@
break
return 1
+/mob/living/carbon/proc/spew_organ(power = 5)
+ if(!internal_organs.len)
+ return //Guess we're out of organs
+ var/obj/item/organ/guts = pick(internal_organs)
+ var/turf/T = get_turf(src)
+ guts.Remove(src)
+ guts.forceMove(T)
+ var/atom/throw_target = get_edge_target_turf(guts, dir)
+ guts.throw_at(throw_target, power, 4, src)
+
/mob/living/carbon/fully_replace_character_name(oldname,newname)
..()
diff --git a/code/modules/mob/living/carbon/emote.dm b/code/modules/mob/living/carbon/emote.dm
index 30fa676500..48ebd53435 100644
--- a/code/modules/mob/living/carbon/emote.dm
+++ b/code/modules/mob/living/carbon/emote.dm
@@ -68,6 +68,17 @@
if(!isnum(text2num(params)))
return message
+/datum/emote/sound/carbon/snap
+ key = "snap"
+ key_third_person = "snaps"
+ message = "snaps their fingers."
+ muzzle_ignore = TRUE
+ restraint_check = TRUE
+ emote_type = EMOTE_AUDIBLE
+ sound = 'sound/effects/snap01.ogg'
+ mob_type_allowed_typecache = list(/mob/living/carbon/)
+
+
/datum/emote/living/carbon/sign/signal
key = "signal"
key_third_person = "signals"
diff --git a/code/modules/mob/living/carbon/human/death.dm.rej b/code/modules/mob/living/carbon/human/death.dm.rej
deleted file mode 100644
index a4a1fc5a7c..0000000000
--- a/code/modules/mob/living/carbon/human/death.dm.rej
+++ /dev/null
@@ -1,10 +0,0 @@
-diff a/code/modules/mob/living/carbon/human/death.dm b/code/modules/mob/living/carbon/human/death.dm (rejected hunks)
-@@ -32,7 +32,7 @@
-
- dna.species.spec_death(gibbed, src)
-
-- if(SSticker && SSticker.mode)
-+ if(SSticker.HasRoundStarted())
- SSblackbox.ReportDeath(src)
- if(mind && mind.devilinfo)
- INVOKE_ASYNC(mind.devilinfo, /datum/devilinfo.proc/beginResurrectionCheck, src)
diff --git a/code/modules/mob/living/carbon/human/emote.dm b/code/modules/mob/living/carbon/human/emote.dm
index de4eecabff..b778279f42 100644
--- a/code/modules/mob/living/carbon/human/emote.dm
+++ b/code/modules/mob/living/carbon/human/emote.dm
@@ -171,5 +171,8 @@
dna.species.mutant_bodyparts -= "wingsopen"
dna.species.mutant_bodyparts |= "wings"
update_body()
+ if(isturf(loc))
+ var/turf/T = loc
+ T.Entered(src)
//Ayy lmao
diff --git a/code/modules/mob/living/carbon/human/examine.dm b/code/modules/mob/living/carbon/human/examine.dm
index 9081591395..a3bb2fefde 100644
--- a/code/modules/mob/living/carbon/human/examine.dm
+++ b/code/modules/mob/living/carbon/human/examine.dm
@@ -134,7 +134,7 @@
if(stat == DEAD || (status_flags & FAKEDEATH))
appears_dead = 1
if(suiciding)
- msg += "[t_He] appear[p_s()] to have commited suicide... there is no hope of recovery.\n"
+ msg += "[t_He] appear[p_s()] to have committed suicide... there is no hope of recovery.\n"
if(hellbound)
msg += "[t_His] soul seems to have been ripped out of [t_his] body. Revival is impossible.\n"
msg += "[t_He] [t_is] limp and unresponsive; there are no signs of life"
diff --git a/code/modules/mob/living/carbon/human/species.dm b/code/modules/mob/living/carbon/human/species.dm
index a48124e412..2c034dc64f 100644
--- a/code/modules/mob/living/carbon/human/species.dm
+++ b/code/modules/mob/living/carbon/human/species.dm
@@ -119,6 +119,8 @@
var/obj/item/thing = C.get_item_by_slot(slot_id)
if(thing && (!thing.species_exception || !is_type_in_list(src,thing.species_exception)))
C.dropItemToGround(thing)
+ if(C.hud_used)
+ C.hud_used.update_locked_slots()
// this needs to be FIRST because qdel calls update_body which checks if we have DIGITIGRADE legs or not and if not then removes DIGITIGRADE from species_traits
if(("legs" in C.dna.species.mutant_bodyparts) && C.dna.features["legs"] == "Digitigrade Legs")
diff --git a/code/modules/mob/living/carbon/human/species_types/golems.dm b/code/modules/mob/living/carbon/human/species_types/golems.dm
index 0390661c78..4d68188686 100644
--- a/code/modules/mob/living/carbon/human/species_types/golems.dm
+++ b/code/modules/mob/living/carbon/human/species_types/golems.dm
@@ -9,7 +9,7 @@
punchdamagelow = 5
punchdamagehigh = 14
punchstunthreshold = 11 //about 40% chance to stun
- no_equip = list(slot_wear_mask, slot_wear_suit, slot_gloves, slot_shoes, slot_w_uniform)
+ no_equip = list(slot_wear_mask, slot_wear_suit, slot_gloves, slot_shoes, slot_w_uniform, slot_s_store)
nojumpsuit = 1
sexes = 1
damage_overlay_type = ""
diff --git a/code/modules/mob/living/silicon/ai/freelook/eye.dm b/code/modules/mob/living/silicon/ai/freelook/eye.dm
index dce38bd664..56c43211e4 100644
--- a/code/modules/mob/living/silicon/ai/freelook/eye.dm
+++ b/code/modules/mob/living/silicon/ai/freelook/eye.dm
@@ -28,7 +28,7 @@
//Holopad
if(istype(ai.current, /obj/machinery/holopad))
var/obj/machinery/holopad/H = ai.current
- H.move_hologram(ai)
+ H.move_hologram(ai, T)
/mob/camera/aiEye/Move()
return 0
diff --git a/code/modules/mob/living/simple_animal/hostile/jungle_mobs.dm b/code/modules/mob/living/simple_animal/hostile/jungle_mobs.dm
new file mode 100644
index 0000000000..de1bf0b308
--- /dev/null
+++ b/code/modules/mob/living/simple_animal/hostile/jungle_mobs.dm
@@ -0,0 +1,85 @@
+/mob/living/simple_animal/hostile/jungle
+ vision_range = 5
+ atmos_requirements = list("min_oxy" = 0, "max_oxy" = 0, "min_tox" = 0, "max_tox" = 0, "min_co2" = 0, "max_co2" = 0, "min_n2" = 0, "max_n2" = 0)
+ faction = list("jungle")
+ weather_immunities = list("acid")
+ obj_damage = 30
+ environment_smash = 2
+ minbodytemp = 0
+ maxbodytemp = 450
+ response_help = "pokes"
+ response_disarm = "shoves"
+ response_harm = "strikes"
+ status_flags = 0
+ a_intent = INTENT_HARM
+ see_in_dark = 4
+ lighting_alpha = LIGHTING_PLANE_ALPHA_MOSTLY_INVISIBLE
+ mob_size = MOB_SIZE_LARGE
+
+
+
+//Mega arachnid
+
+/mob/living/simple_animal/hostile/jungle/mega_arachnid
+ name = "mega arachnid"
+ desc = "Though physically imposing, it prefers to ambush its prey, and it will only engage with an already crippled opponent."
+ melee_damage_lower = 30
+ melee_damage_upper = 30
+ maxHealth = 300
+ health = 300
+ speed = 1
+ ranged = 1
+ pixel_x = -16
+ move_to_delay = 10
+ aggro_vision_range = 9
+ speak_emote = list("chitters")
+ attack_sound = 'sound/weapons/bladeslice.ogg'
+ ranged_cooldown_time = 60
+ projectiletype = /obj/item/projectile/mega_arachnid
+ projectilesound = 'sound/weapons/pierce.ogg'
+ icon = 'icons/mob/jungle/arachnid.dmi'
+ icon_state = "arachnid"
+ icon_living = "arachnid"
+ icon_dead = "dead_purple"
+ alpha = 50
+
+/mob/living/simple_animal/hostile/jungle/mega_arachnid/Life()
+ ..()
+ if(target && ranged_cooldown > world.time && iscarbon(target))
+ var/mob/living/carbon/C = target
+ if(!C.legcuffed && C.health < 50)
+ retreat_distance = 9
+ minimum_distance = 9
+ alpha = 125
+ return
+ retreat_distance = 0
+ minimum_distance = 0
+ alpha = 255
+
+
+/mob/living/simple_animal/hostile/jungle/mega_arachnid/Aggro()
+ ..()
+ alpha = 255
+
+/mob/living/simple_animal/hostile/jungle/mega_arachnid/LoseAggro()
+ ..()
+ alpha = 50
+
+/obj/item/projectile/mega_arachnid
+ name = "flesh snare"
+ nodamage = 1
+ damage = 0
+ icon_state = "tentacle_end"
+
+/obj/item/projectile/mega_arachnid/on_hit(atom/target, blocked = 0)
+ if(iscarbon(target) && blocked < 100)
+ var/obj/item/weapon/restraints/legcuffs/beartrap/mega_arachnid/B = new /obj/item/weapon/restraints/legcuffs/beartrap/mega_arachnid(get_turf(target))
+ B.Crossed(target)
+ ..()
+
+/obj/item/weapon/restraints/legcuffs/beartrap/mega_arachnid
+ name = "fleshy restraints"
+ desc = "Used by mega arachnids to immobilize their prey."
+ flags = DROPDEL
+ icon_state = "tentacle_end"
+ icon = 'icons/obj/projectiles.dmi'
\ No newline at end of file
diff --git a/code/modules/mob/living/simple_animal/slime/slime.dm b/code/modules/mob/living/simple_animal/slime/slime.dm
index 8971d33b28..f9bcfe1b6f 100644
--- a/code/modules/mob/living/simple_animal/slime/slime.dm
+++ b/code/modules/mob/living/simple_animal/slime/slime.dm
@@ -16,7 +16,7 @@
response_disarm = "shoos"
response_harm = "stomps on"
emote_see = list("jiggles", "bounces in place")
- speak_emote = list("telepathically chirps")
+ speak_emote = list("blorbles")
bubble_icon = "slime"
initial_languages = list(/datum/language/common, /datum/language/slime)
@@ -31,10 +31,10 @@
see_in_dark = 8
- verb_say = "telepathically chirps"
- verb_ask = "telepathically asks"
- verb_exclaim = "telepathically cries"
- verb_yell = "telephatically cries"
+ verb_say = "blorbles"
+ verb_ask = "inquisitively blorbles"
+ verb_exclaim = "loudly blorbles"
+ verb_yell = "loudly blorbles"
// canstun and canweaken don't affect slimes because they ignore stun and weakened variables
// for the sake of cleanliness, though, here they are.
diff --git a/code/modules/mob/mob.dm b/code/modules/mob/mob.dm
index 24b4d228cc..819f7f3db2 100644
--- a/code/modules/mob/mob.dm
+++ b/code/modules/mob/mob.dm
@@ -351,6 +351,8 @@
/mob/proc/spin(spintime, speed)
set waitfor = 0
var/D = dir
+ if((spintime < 1)||(speed < 1)||!spintime||!speed)
+ return
while(spintime >= speed)
sleep(speed)
switch(D)
diff --git a/code/modules/power/generator.dm b/code/modules/power/generator.dm
index dfbf3fe50b..9fe043a4a0 100644
--- a/code/modules/power/generator.dm
+++ b/code/modules/power/generator.dm
@@ -28,11 +28,12 @@
/obj/machinery/power/generator/Initialize(mapload)
- . = ..()
+ . = ..()
var/obj/machinery/atmospherics/components/binary/circulator/circpath = /obj/machinery/atmospherics/components/binary/circulator
cold_circ = locate(circpath) in get_step(src, cold_dir)
hot_circ = locate(circpath) in get_step(src, hot_dir)
connect_to_network()
+ SSair.atmos_machinery += src
if(cold_circ)
switch(cold_dir)
@@ -55,6 +56,9 @@
update_icon()
+/obj/machinery/power/generator/Destroy()
+ SSair.atmos_machinery -= src
+ return ..()
/obj/machinery/power/generator/update_icon()
@@ -63,21 +67,20 @@
else
cut_overlays()
- if(lastgenlev != 0)
- add_overlay("teg-op[lastgenlev]")
+ var/L = min(round(lastgenlev/100000),11)
+ if(L != 0)
+ add_overlay(image('icons/obj/power.dmi', "teg-op[L]"))
- add_overlay("teg-oc[lastcirc]")
+ add_overlay("teg-oc[lastcirc]")
#define GENRATE 800 // generator output coefficient from Q
-/obj/machinery/power/generator/process()
+/obj/machinery/power/generator/process_atmos()
if(!cold_circ || !hot_circ)
return
- lastgen = 0
-
if(powernet)
//to_chat(world, "cold_circ and hot_circ pass")
@@ -104,7 +107,7 @@
var/energy_transfer = delta_temperature*hot_air_heat_capacity*cold_air_heat_capacity/(hot_air_heat_capacity+cold_air_heat_capacity)
var/heat = energy_transfer*(1-efficiency)
- lastgen = energy_transfer*efficiency
+ lastgen += energy_transfer*efficiency
//to_chat(world, "lastgen = [lastgen]; heat = [heat]; delta_temperature = [delta_temperature]; hot_air_heat_capacity = [hot_air_heat_capacity]; cold_air_heat_capacity = [cold_air_heat_capacity];")
@@ -113,7 +116,7 @@
//to_chat(world, "POWER: [lastgen] W generated at [efficiency*100]% efficiency and sinks sizes [cold_air_heat_capacity], [hot_air_heat_capacity]")
- add_avail(lastgen)
+ //add_avail(lastgen) This is done in process now
// update icon overlays only if displayed level has changed
if(hot_air)
@@ -124,15 +127,23 @@
var/datum/gas_mixture/cold_circ_air1 = cold_circ.AIR1
cold_circ_air1.merge(cold_air)
- var/genlev = max(0, min( round(11*lastgen / 100000), 11))
+ update_icon()
+
var/circ = "[cold_circ && cold_circ.last_pressure_delta > 0 ? "1" : "0"][hot_circ && hot_circ.last_pressure_delta > 0 ? "1" : "0"]"
- if((genlev != lastgenlev) || (circ != lastcirc))
- lastgenlev = genlev
+ if(circ != lastcirc)
lastcirc = circ
update_icon()
src.updateDialog()
+/obj/machinery/power/generator/process()
+ //Setting this number higher just makes the change in power output slower, it doesnt actualy reduce power output cause **math**
+ var/power_output = round(lastgen / 10)
+ add_avail(power_output)
+ lastgenlev = power_output
+ lastgen -= power_output
+ ..()
+
/obj/machinery/power/generator/attack_hand(mob/user)
if(..())
user << browse(null, "window=teg")
@@ -151,7 +162,13 @@
t += ""
- t += "Output: [round(lastgen)] W"
+ var/displaygen = lastgenlev
+ if(displaygen < 1000000) //less than a MW
+ displaygen /= 1000
+ t += "Output: [round(displaygen,0.01)] kW"
+ else
+ displaygen /= 1000000
+ t += "Output: [round(displaygen,0.01)] MW"
t += "
"
diff --git a/code/modules/power/singularity/narsie.dm b/code/modules/power/singularity/narsie.dm
index 9deebdfe10..fb2df4deeb 100644
--- a/code/modules/power/singularity/narsie.dm
+++ b/code/modules/power/singularity/narsie.dm
@@ -14,6 +14,7 @@
light_power = 0.7
light_range = 15
light_color = rgb(255, 0, 0)
+ gender = FEMALE
var/clashing = FALSE //If Nar-Sie is fighting Ratvar
/obj/singularity/narsie/large
@@ -26,8 +27,8 @@
grav_pull = 10
consume_range = 12 //How many tiles out do we eat
-/obj/singularity/narsie/large/New()
- ..()
+/obj/singularity/narsie/large/Initialize()
+ . = ..()
send_to_playing_players("NAR-SIE HAS RISEN")
send_to_playing_players(pick('sound/hallucinations/im_here1.ogg', 'sound/hallucinations/im_here2.ogg'))
diff --git a/code/modules/power/singularity/singularity.dm b/code/modules/power/singularity/singularity.dm
index 3b0bc3087b..1a308ed471 100644
--- a/code/modules/power/singularity/singularity.dm
+++ b/code/modules/power/singularity/singularity.dm
@@ -29,12 +29,12 @@
resistance_flags = INDESTRUCTIBLE | LAVA_PROOF | FIRE_PROOF | UNACIDABLE | ACID_PROOF
dangerous_possession = TRUE
-/obj/singularity/New(loc, var/starting_energy = 50, var/temp = 0)
+/obj/singularity/Initialize(mapload, starting_energy = 50)
//CARN: admin-alert for chuckle-fuckery.
admin_investigate_setup()
src.energy = starting_energy
- ..()
+ . = ..()
START_PROCESSING(SSobj, src)
GLOB.poi_list |= src
GLOB.singularities |= src
diff --git a/code/modules/power/supermatter/supermatter.dm b/code/modules/power/supermatter/supermatter.dm
index 4b48d19857..a580b63e55 100644
--- a/code/modules/power/supermatter/supermatter.dm
+++ b/code/modules/power/supermatter/supermatter.dm
@@ -129,6 +129,7 @@
/obj/machinery/power/supermatter_shard/Initialize()
. = ..()
+ SSair.atmos_machinery += src
countdown = new(src)
countdown.start()
GLOB.poi_list |= src
@@ -139,6 +140,7 @@
/obj/machinery/power/supermatter_shard/Destroy()
investigate_log("has been destroyed.", "supermatter")
+ SSair.atmos_machinery -= src
QDEL_NULL(radio)
GLOB.poi_list -= src
QDEL_NULL(countdown)
@@ -181,7 +183,7 @@
E.energy = power
qdel(src)
-/obj/machinery/power/supermatter_shard/process()
+/obj/machinery/power/supermatter_shard/process_atmos()
var/turf/T = loc
if(isnull(T)) // We have a null turf...something is wrong, stop processing this entity.
@@ -296,6 +298,7 @@
if(produces_gas)
env.merge(removed)
+ air_update_turf()
for(var/mob/living/carbon/human/l in view(src, HALLUCINATION_RANGE(power))) // If they can see it without mesons on. Bad on them.
if(!istype(l.glasses, /obj/item/clothing/glasses/meson))
diff --git a/code/modules/power/tesla/energy_ball.dm b/code/modules/power/tesla/energy_ball.dm
index fbb82cb36a..df08899140 100644
--- a/code/modules/power/tesla/energy_ball.dm
+++ b/code/modules/power/tesla/energy_ball.dm
@@ -40,6 +40,11 @@ GLOBAL_LIST_INIT(blacklisted_tesla_types, typecacheof(list(/obj/machinery/atmosp
var/energy_to_raise = 32
var/energy_to_lower = -20
+/obj/singularity/energy_ball/Initialize(mapload, starting_energy = 50, is_miniball = FALSE)
+ . = ..()
+ if(!is_miniball)
+ set_light(10, 7, "#EEEEFF")
+
/obj/singularity/energy_ball/ex_act(severity, target)
return
@@ -54,6 +59,11 @@ GLOBAL_LIST_INIT(blacklisted_tesla_types, typecacheof(list(/obj/machinery/atmosp
. = ..()
+/obj/singularity/energy_ball/admin_investigate_setup()
+ if(istype(loc, /obj/singularity/energy_ball))
+ return
+ ..()
+
/obj/singularity/energy_ball/process()
if(!orbiting)
handle_energy()
@@ -117,7 +127,7 @@ GLOBAL_LIST_INIT(blacklisted_tesla_types, typecacheof(list(/obj/machinery/atmosp
/obj/singularity/energy_ball/proc/new_mini_ball()
if(!loc)
return
- var/obj/singularity/energy_ball/EB = new(loc)
+ var/obj/singularity/energy_ball/EB = new(loc, 0, TRUE)
EB.transform *= pick(0.3, 0.4, 0.5, 0.6, 0.7)
var/icon/I = icon(icon,icon_state,dir)
diff --git a/code/modules/projectiles/ammunition/energy.dm b/code/modules/projectiles/ammunition/energy.dm
index a6440e32ed..b1fd49779f 100644
--- a/code/modules/projectiles/ammunition/energy.dm
+++ b/code/modules/projectiles/ammunition/energy.dm
@@ -191,7 +191,7 @@
fire_sound = 'sound/magic/lightningbolt.ogg'
e_cost = 200
select_name = "stun"
- projectile_type = /obj/item/projectile/energy/tesla_revolver
+ projectile_type = /obj/item/projectile/energy/tesla/revolver
/obj/item/ammo_casing/energy/gravityrepulse
projectile_type = /obj/item/projectile/gravityrepulse
diff --git a/code/modules/projectiles/projectile.dm b/code/modules/projectiles/projectile.dm
index dceed5b438..9835b1df21 100644
--- a/code/modules/projectiles/projectile.dm
+++ b/code/modules/projectiles/projectile.dm
@@ -179,6 +179,8 @@
return
if(setAngle)
Angle = setAngle
+ var/old_pixel_x = pixel_x
+ var/old_pixel_y = pixel_y
if(!legacy) //new projectiles
set waitfor = 0
var/next_run = world.time
@@ -201,29 +203,30 @@
var/Pixel_x=round((sin(Angle)+16*sin(Angle)*2), 1) //round() is a floor operation when only one argument is supplied, we don't want that here
var/Pixel_y=round((cos(Angle)+16*cos(Angle)*2), 1)
- var/pixel_x_offset = pixel_x + Pixel_x
- var/pixel_y_offset = pixel_y + Pixel_y
+ var/pixel_x_offset = old_pixel_x + Pixel_x
+ var/pixel_y_offset = old_pixel_y + Pixel_y
var/new_x = x
var/new_y = y
while(pixel_x_offset > 16)
pixel_x_offset -= 32
- pixel_x -= 32
+ old_pixel_x -= 32
new_x++// x++
while(pixel_x_offset < -16)
pixel_x_offset += 32
- pixel_x += 32
+ old_pixel_x += 32
new_x--
-
while(pixel_y_offset > 16)
pixel_y_offset -= 32
- pixel_y -= 32
+ old_pixel_y -= 32
new_y++
while(pixel_y_offset < -16)
pixel_y_offset += 32
- pixel_y += 32
+ old_pixel_y += 32
new_y--
-
+
+ pixel_x = old_pixel_x
+ pixel_y = old_pixel_y
step_towards(src, locate(new_x, new_y, z))
next_run += max(world.tick_lag, speed)
var/delay = next_run - world.time
@@ -232,7 +235,9 @@
pixel_y = pixel_y_offset
else
animate(src, pixel_x = pixel_x_offset, pixel_y = pixel_y_offset, time = max(1, (delay <= 3 ? delay - 1 : delay)), flags = ANIMATION_END_NOW)
-
+ old_pixel_x = pixel_x_offset
+ old_pixel_y = pixel_y_offset
+
if(original && (original.layer>=2.75) || ismob(original))
if(loc == get_turf(original))
if(!(original in permutated))
diff --git a/code/modules/projectiles/projectile/energy.dm b/code/modules/projectiles/projectile/energy.dm
index c1a67f4c81..974ea935f2 100644
--- a/code/modules/projectiles/projectile/energy.dm
+++ b/code/modules/projectiles/projectile/energy.dm
@@ -159,44 +159,34 @@
/obj/item/projectile/energy/bolt/large
damage = 20
-/obj/item/projectile/energy/tesla_revolver
+/obj/item/projectile/energy/tesla
name = "tesla bolt"
icon_state = "tesla_projectile"
impact_effect_type = /obj/effect/overlay/temp/impact_effect/blue_laser
var/chain
-/obj/item/projectile/energy/tesla_revolver/fire(setAngle)
+/obj/item/projectile/energy/tesla/fire(setAngle)
if(firer)
chain = firer.Beam(src, icon_state = "lightning[rand(1, 12)]", time = INFINITY, maxdistance = INFINITY)
..()
-/obj/item/projectile/energy/tesla_revolver/on_hit(atom/target)
- . = ..()
- if(isliving(target))
- tesla_zap(src, 3, 10000)
- qdel(src)
-
-/obj/item/projectile/energy/tesla_revolver/Destroy()
+/obj/item/projectile/energy/tesla/Destroy()
qdel(chain)
return ..()
+/obj/item/projectile/energy/tesla/revolver
+ name = "energy orb"
-/obj/item/projectile/energy/tesla_cannon
- name = "tesla bolt"
- icon_state = "tesla_projectile"
- impact_effect_type = /obj/effect/overlay/temp/impact_effect/blue_laser
- var/chain
+/obj/item/projectile/energy/tesla/revolver/on_hit(atom/target)
+ . = ..()
+ if(isliving(target))
+ tesla_zap(target, 3, 10000)
+ qdel(src)
-/obj/item/projectile/energy/tesla_cannon/fire(setAngle)
- if(firer)
- chain = firer.Beam(src, icon_state = "lightning[rand(1, 12)]", time = INFINITY, maxdistance = INFINITY)
- ..()
+/obj/item/projectile/energy/tesla/cannon
+ name = "tesla orb"
-/obj/item/projectile/energy/tesla_cannon/on_hit(atom/target)
+/obj/item/projectile/energy/tesla/cannon/on_hit(atom/target)
. = ..()
- tesla_zap(src, 3, 10000, explosive = FALSE, stun_mobs = FALSE)
+ tesla_zap(target, 3, 10000, explosive = FALSE, stun_mobs = FALSE)
qdel(src)
-
-/obj/item/projectile/energy/tesla_cannon/Destroy()
- qdel(chain)
- return ..()
diff --git a/code/modules/reagents/chemistry/machinery/reagentgrinder.dm b/code/modules/reagents/chemistry/machinery/reagentgrinder.dm
index 2dbc0ff1c2..a8ab8fd426 100644
--- a/code/modules/reagents/chemistry/machinery/reagentgrinder.dm
+++ b/code/modules/reagents/chemistry/machinery/reagentgrinder.dm
@@ -38,7 +38,7 @@
/obj/item/weapon/reagent_containers/food/snacks/grown/wheat = list("flour" = -5),
/obj/item/weapon/reagent_containers/food/snacks/grown/oat = list("flour" = -5),
/obj/item/weapon/reagent_containers/food/snacks/grown/rice = list("rice" = -5),
- /obj/item/weapon/reagent_containers/food/snacks/donut/New = list("sprinkles" = -2, "sugar" = 1),
+ /obj/item/weapon/reagent_containers/food/snacks/donut = list("sprinkles" = -2, "sugar" = 1),
/obj/item/weapon/reagent_containers/food/snacks/grown/cherries = list("cherryjelly" = 0),
/obj/item/weapon/reagent_containers/food/snacks/grown/bluecherries = list("bluecherryjelly" = 0),
/obj/item/weapon/reagent_containers/food/snacks/egg = list("eggyolk" = -5),
diff --git a/code/modules/reagents/chemistry/reagents/alcohol_reagents.dm b/code/modules/reagents/chemistry/reagents/alcohol_reagents.dm
index 23836e866d..31ec27fb79 100644
--- a/code/modules/reagents/chemistry/reagents/alcohol_reagents.dm
+++ b/code/modules/reagents/chemistry/reagents/alcohol_reagents.dm
@@ -966,7 +966,7 @@ All effects don't start immediately, but rather get worse over time; the rate is
glass_desc = "Only for the experienced. You think you see sand floating in the glass."
/datum/reagent/consumable/ethanol/bananahonk
- name = "Banana Mama"
+ name = "Banana Honk"
id = "bananahonk"
description = "A drink from Clown Heaven."
nutriment_factor = 1 * REAGENTS_METABOLISM
diff --git a/code/modules/reagents/chemistry/reagents/food_reagents.dm b/code/modules/reagents/chemistry/reagents/food_reagents.dm
index 442772fea8..56a89fe389 100644
--- a/code/modules/reagents/chemistry/reagents/food_reagents.dm
+++ b/code/modules/reagents/chemistry/reagents/food_reagents.dm
@@ -60,7 +60,10 @@
// data for nutriment is one or more (flavour -> ratio)
// where all the ratio values adds up to 1
- var/list/taste_amounts = data.Copy()
+ var/list/taste_amounts = list()
+ if(data)
+ taste_amounts = data.Copy()
+
counterlist_scale(taste_amounts, volume)
var/list/other_taste_amounts = newdata.Copy()
diff --git a/code/modules/reagents/chemistry/reagents/medicine_reagents.dm b/code/modules/reagents/chemistry/reagents/medicine_reagents.dm
index 500147d233..6d38e85ca8 100644
--- a/code/modules/reagents/chemistry/reagents/medicine_reagents.dm
+++ b/code/modules/reagents/chemistry/reagents/medicine_reagents.dm
@@ -347,10 +347,9 @@
/datum/reagent/medicine/mine_salve/reaction_mob(mob/living/M, method=TOUCH, reac_volume, show_message = 1)
if(iscarbon(M) && M.stat != DEAD)
if(method in list(INGEST, VAPOR, INJECT))
- M.Stun(4)
- M.Weaken(4)
+ M.nutrition -= 5
if(show_message)
- to_chat(M, "Your stomach agonizingly cramps!")
+ to_chat(M, "Your stomach feels empty and cramps!")
else
var/mob/living/carbon/C = M
for(var/s in C.surgeries)
@@ -962,8 +961,7 @@
/datum/reagent/medicine/antitoxin/on_mob_life(mob/living/M)
M.adjustToxLoss(-2*REM, 0)
for(var/datum/reagent/toxin/R in M.reagents.reagent_list)
- if(R != src)
- M.reagents.remove_reagent(R.id,1)
+ M.reagents.remove_reagent(R.id,1)
..()
. = 1
diff --git a/code/modules/reagents/chemistry/reagents/other_reagents.dm b/code/modules/reagents/chemistry/reagents/other_reagents.dm
index c25a1d050d..ac259e58c2 100644
--- a/code/modules/reagents/chemistry/reagents/other_reagents.dm
+++ b/code/modules/reagents/chemistry/reagents/other_reagents.dm
@@ -189,7 +189,7 @@
/datum/reagent/water/holywater/on_mob_life(mob/living/M)
if(!data) data = 1
data++
- M.jitteriness = max(M.jitteriness-5,0)
+ M.jitteriness = min(M.jitteriness+4,10)
if(data >= 30) // 12 units, 54 seconds @ metabolism 0.4 units & tick rate 1.8 sec
if(!M.stuttering)
M.stuttering = 1
@@ -212,9 +212,9 @@
SSticker.mode.remove_cultist(M.mind, 1, 1)
else if(is_servant_of_ratvar(M))
remove_servant_of_ratvar(M)
- holder.remove_reagent(id, volume) // maybe this is a little too perfect and a max() cap on the statuses would be better??
M.jitteriness = 0
M.stuttering = 0
+ holder.remove_reagent(id, volume) // maybe this is a little too perfect and a max() cap on the statuses would be better??
return
holder.remove_reagent(id, 0.4) //fixed consumption to prevent balancing going out of whack
@@ -658,7 +658,7 @@
taste_mult = 0 // apparently tasteless.
/datum/reagent/mercury/on_mob_life(mob/living/M)
- if(M.canmove && isspaceturf(M.loc))
+ if(M.canmove && !isspaceturf(M.loc))
step(M, pick(GLOB.cardinal))
if(prob(5))
M.emote(pick("twitch","drool","moan"))
@@ -738,7 +738,7 @@
taste_description = "metal"
/datum/reagent/lithium/on_mob_life(mob/living/M)
- if(M.canmove && isspaceturf(M.loc))
+ if(M.canmove && !isspaceturf(M.loc))
step(M, pick(GLOB.cardinal))
if(prob(5))
M.emote(pick("twitch","drool","moan"))
@@ -1568,6 +1568,13 @@
M.update_transform()
..()
+/datum/reagent/plastic_polymers
+ name = "plastic polymers"
+ id = "plastic_polymers"
+ description = "the petroleum based components of plastic."
+ color = "#f7eded"
+ taste_description = "plastic"
+
/datum/reagent/glitter
name = "generic glitter"
id = "glitter"
diff --git a/code/modules/reagents/chemistry/reagents/toxin_reagents.dm b/code/modules/reagents/chemistry/reagents/toxin_reagents.dm
index 528124f84c..cedec9941b 100644
--- a/code/modules/reagents/chemistry/reagents/toxin_reagents.dm
+++ b/code/modules/reagents/chemistry/reagents/toxin_reagents.dm
@@ -648,6 +648,34 @@
M.losebreath += 5
return ..()
+/datum/reagent/toxin/spewium
+ name = "Spewium"
+ id = "spewium"
+ description = "A powerful emetic, causes uncontrollable vomiting. May result in vomiting organs at high doses."
+ reagent_state = LIQUID
+ color = "#2f6617" //A sickly green color
+ metabolization_rate = REAGENTS_METABOLISM
+ overdose_threshold = 29
+ toxpwr = 0
+ taste_description = "vomit"
+
+/datum/reagent/toxin/spewium/on_mob_life(mob/living/M)
+ .=..()
+ if(current_cycle >=11 && prob(min(50,current_cycle)) && ishuman(M))
+ var/mob/living/carbon/human/H = M
+ H.vomit(lost_nutrition = 10, blood = prob(10), stun = prob(50), distance = rand(0,4), message = TRUE, toxic = prob(30))
+ for(var/datum/reagent/toxin/R in M.reagents.reagent_list)
+ if(R != src)
+ H.reagents.remove_reagent(R.id,1)
+
+/datum/reagent/toxin/spewium/overdose_process(mob/living/M)
+ . = ..()
+ if(current_cycle >=33 && prob(15) && ishuman(M))
+ var/mob/living/carbon/human/H = M
+ H.spew_organ()
+ H.vomit(lost_nutrition = 0, blood = 1, stun = 1, distance = 4)
+ to_chat(H, "You feel something lumpy come up as you vomit.")
+
/datum/reagent/toxin/curare
name = "Curare"
id = "curare"
diff --git a/code/modules/reagents/chemistry/recipes/others.dm b/code/modules/reagents/chemistry/recipes/others.dm
index 19bb28666d..0bc843a605 100644
--- a/code/modules/reagents/chemistry/recipes/others.dm
+++ b/code/modules/reagents/chemistry/recipes/others.dm
@@ -624,3 +624,14 @@
id = "laughter"
results = list("laughter" = 10) // Fuck it. I'm not touching this one.
required_reagents = list("sugar" = 1, "banana" = 1)
+
+/datum/chemical_reaction/plastic_polymers
+ name = "plastic polymers"
+ id = "plastic_polymers"
+ required_reagents = list("oil" = 5, "sodiumchloride" = 2, "ash" = 3)
+ required_temp = 374 //lazily consistent with soap & other crafted objects generically created with heat.
+
+/datum/chemical_reaction/plastic_polymers/on_reaction(datum/reagents/holder, created_volume)
+ var/location = get_turf(holder.my_atom)
+ for(var/i in 1 to 10)
+ new /obj/item/stack/sheet/plastic(location)
diff --git a/code/modules/reagents/reagent_containers/bottle.dm b/code/modules/reagents/reagent_containers/bottle.dm
index a92c52abf4..37074b6d12 100644
--- a/code/modules/reagents/reagent_containers/bottle.dm
+++ b/code/modules/reagents/reagent_containers/bottle.dm
@@ -58,6 +58,12 @@
icon_state = "bottle12"
list_reagents = list("cyanide" = 30)
+/obj/item/weapon/reagent_containers/glass/bottle/spewium
+ name = "spewium bottle"
+ desc = "A small bottle of spewium."
+ icon_state = "bottle12"
+ list_reagents = list("spewium" = 30)
+
/obj/item/weapon/reagent_containers/glass/bottle/morphine
name = "morphine bottle"
desc = "A small bottle of morphine."
diff --git a/code/modules/shuttle/elevator.dm b/code/modules/shuttle/elevator.dm
new file mode 100644
index 0000000000..12f9c24f9a
--- /dev/null
+++ b/code/modules/shuttle/elevator.dm
@@ -0,0 +1,10 @@
+/obj/docking_port/mobile/elevator
+ name = "elevator"
+ id = "elevator"
+ dwidth = 3
+ width = 7
+ height = 7
+ knockdown = FALSE
+
+/obj/docking_port/mobile/elevator/request(obj/docking_port/stationary/S) //No transit, no ignition, just a simple up/down platform
+ dock(S, TRUE)
\ No newline at end of file
diff --git a/code/modules/shuttle/on_move.dm b/code/modules/shuttle/on_move.dm
index 756fad25b3..b5571164ff 100644
--- a/code/modules/shuttle/on_move.dm
+++ b/code/modules/shuttle/on_move.dm
@@ -3,7 +3,7 @@
return
// Called when shuttle attempts to move an atom.
-/atom/movable/proc/onShuttleMove(turf/T1, rotation)
+/atom/movable/proc/onShuttleMove(turf/T1, rotation, knockdown = TRUE)
if(rotation)
shuttleRotate(rotation)
loc = T1
@@ -47,11 +47,11 @@
else
shake_camera(src, 7, 1)
-/mob/living/carbon/onShuttleMove()
+/mob/living/carbon/onShuttleMove(turf/T1, rotation, knockdown = TRUE)
. = ..()
if(!.)
return
- if(!buckled)
+ if(!buckled && knockdown)
Weaken(3)
/obj/effect/abstract/proximity_checker/onShuttleMove()
diff --git a/code/modules/shuttle/shuttle.dm b/code/modules/shuttle/shuttle.dm
index 00ddecb7f8..656ba24da6 100644
--- a/code/modules/shuttle/shuttle.dm
+++ b/code/modules/shuttle/shuttle.dm
@@ -217,6 +217,8 @@
var/launch_status = NOLAUNCH
+ var/knockdown = TRUE //Will it knock down mobs when it docks?
+
// A timid shuttle will not register itself with the shuttle subsystem
// All shuttle templates are timid
var/timid = FALSE
@@ -517,7 +519,7 @@
//move mobile to new location
for(var/atom/movable/AM in T0)
- if(AM.onShuttleMove(T1, rotation))
+ if(AM.onShuttleMove(T1, rotation, knockdown))
moved_atoms += AM
if(rotation)
@@ -578,10 +580,7 @@
if(M.pulledby)
M.pulledby.stop_pulling()
M.stop_pulling()
- M.visible_message("[M] is hit by \
- a hyperspace ripple!",
- "You feel an immense \
- crushing pressure as the space around you ripples.")
+ M.visible_message("[src] slams into [M]!")
if(M.key || M.get_ghost(TRUE))
SSblackbox.add_details("shuttle_gib", "[type]")
else
diff --git a/code/modules/spells/spell_types/mind_transfer.dm b/code/modules/spells/spell_types/mind_transfer.dm
index 7ebafe6e24..052c1f1162 100644
--- a/code/modules/spells/spell_types/mind_transfer.dm
+++ b/code/modules/spells/spell_types/mind_transfer.dm
@@ -62,29 +62,14 @@ Also, you never added distance checking after target is selected. I've went ahea
var/mob/caster = user//The wizard/whomever doing the body transferring.
//MIND TRANSFER BEGIN
- if(caster.mind.special_verbs.len)//If the caster had any special verbs, remove them from the mob verb list.
- for(var/V in caster.mind.special_verbs)//Since the caster is using an object spell system, this is mostly moot.
- caster.verbs -= V//But a safety nontheless.
-
- if(victim.mind.special_verbs.len)//Now remove all of the victim's verbs.
- for(var/V in victim.mind.special_verbs)
- victim.verbs -= V
-
var/mob/dead/observer/ghost = victim.ghostize(0)
caster.mind.transfer_to(victim)
- if(victim.mind.special_verbs.len)//To add all the special verbs for the original caster.
- for(var/V in caster.mind.special_verbs)//Not too important but could come into play.
- caster.verbs += V
-
ghost.mind.transfer_to(caster)
if(ghost.key)
caster.key = ghost.key //have to transfer the key since the mind was not active
qdel(ghost)
- if(caster.mind.special_verbs.len)//If they had any special verbs, we add them here.
- for(var/V in caster.mind.special_verbs)
- caster.verbs += V
//MIND TRANSFER END
//Here we paralyze both mobs and knock them out for a time.
diff --git a/code/modules/surgery/bodyparts/dismemberment.dm b/code/modules/surgery/bodyparts/dismemberment.dm
index de8c2b79ac..60edac1977 100644
--- a/code/modules/surgery/bodyparts/dismemberment.dm
+++ b/code/modules/surgery/bodyparts/dismemberment.dm
@@ -218,6 +218,14 @@
for(var/X in list(owner.glasses, owner.ears, owner.wear_mask, owner.head))
var/obj/item/I = X
owner.dropItemToGround(I, TRUE)
+
+ //Handle dental implants
+ for(var/datum/action/item_action/hands_free/activate_pill/AP in owner.actions)
+ AP.Remove(owner)
+ var/obj/pill = AP.target
+ if(pill)
+ pill.forceMove(src)
+
name = "[owner.real_name]'s head"
..()
@@ -300,6 +308,14 @@
C.real_name = real_name
real_name = ""
name = initial(name)
+
+ //Handle dental implants
+ for(var/obj/item/weapon/reagent_containers/pill/P in src)
+ for(var/datum/action/item_action/hands_free/activate_pill/AP in P.actions)
+ P.forceMove(C)
+ AP.Grant(C)
+ break
+
..()
diff --git a/code/modules/surgery/bodyparts/head.dm b/code/modules/surgery/bodyparts/head.dm
index 909f83e4d7..dd63506086 100644
--- a/code/modules/surgery/bodyparts/head.dm
+++ b/code/modules/surgery/bodyparts/head.dm
@@ -48,7 +48,10 @@
brain = null
update_icon_dropped()
else
- I.loc = T
+ if(istype(I, /obj/item/weapon/reagent_containers/pill))
+ for(var/datum/action/item_action/hands_free/activate_pill/AP in I.actions)
+ qdel(AP)
+ I.forceMove(T)
/obj/item/bodypart/head/update_limb(dropping_limb, mob/living/carbon/source)
var/mob/living/carbon/C
diff --git a/code/modules/surgery/dental_implant.dm b/code/modules/surgery/dental_implant.dm
index eef88e4a5f..c51a49081c 100644
--- a/code/modules/surgery/dental_implant.dm
+++ b/code/modules/surgery/dental_implant.dm
@@ -18,10 +18,10 @@
user.drop_item()
tool.loc = target
- var/datum/action/item_action/hands_free/activate_pill/P = new
+ var/datum/action/item_action/hands_free/activate_pill/P = new(tool)
P.button.name = "Activate [tool.name]"
P.target = tool
- P.Grant(target)
+ P.Grant(target) //The pill never actually goes in an inventory slot, so the owner doesn't inherit actions from it
user.visible_message("[user] wedges \the [tool] into [target]'s [parse_zone(target_zone)]!", "You wedge [tool] into [target]'s [parse_zone(target_zone)].")
return 1
@@ -37,6 +37,5 @@
if(target.reagents.total_volume)
target.reagents.reaction(owner, INGEST)
target.reagents.trans_to(owner, target.reagents.total_volume)
- Remove(owner)
qdel(target)
return 1
\ No newline at end of file
diff --git a/code/modules/surgery/organs/ears.dm b/code/modules/surgery/organs/ears.dm
index c91cb219af..e66346a2c8 100644
--- a/code/modules/surgery/organs/ears.dm
+++ b/code/modules/surgery/organs/ears.dm
@@ -4,6 +4,7 @@
desc = "There are three parts to the ear. Inner, middle and outer. Only one of these parts should be normally visible."
zone = "head"
slot = "ears"
+ gender = PLURAL
// `deaf` measures "ticks" of deafness. While > 0, the person is unable
// to hear anything.
diff --git a/code/modules/surgery/organs/eyes.dm b/code/modules/surgery/organs/eyes.dm
index 672ac924ad..2cb2dd5dc6 100644
--- a/code/modules/surgery/organs/eyes.dm
+++ b/code/modules/surgery/organs/eyes.dm
@@ -4,6 +4,7 @@
desc = "I see you!"
zone = "eyes"
slot = "eye_sight"
+ gender = PLURAL
var/sight_flags = 0
var/see_in_dark = 2
diff --git a/code/modules/surgery/organs/vocal_cords.dm b/code/modules/surgery/organs/vocal_cords.dm
index b310f891fb..50f66fef27 100644
--- a/code/modules/surgery/organs/vocal_cords.dm
+++ b/code/modules/surgery/organs/vocal_cords.dm
@@ -8,6 +8,7 @@
icon_state = "appendix"
zone = "mouth"
slot = "vocal_cords"
+ gender = PLURAL
var/list/spans = null
/obj/item/organ/vocal_cords/proc/can_speak_with() //if there is any limitation to speaking with these cords
diff --git a/code/world.dm b/code/world.dm
index 9023ac47f3..29c40a5742 100644
--- a/code/world.dm
+++ b/code/world.dm
@@ -136,11 +136,7 @@
if(!key_valid)
return "Bad Key"
else
-#define CHAT_PULLR 64 //defined in preferences.dm, but not available here at compilation time
- for(var/client/C in GLOB.clients)
- if(C.prefs && (C.prefs.chat_toggles & CHAT_PULLR))
- to_chat(C, "PR: [input["announce"]]")
-#undef CHAT_PULLR
+ AnnouncePR(input["announce"], json_decode(input["payload"]))
else if("crossmessage" in input)
if(!key_valid)
@@ -176,6 +172,25 @@
else if("server_hop" in input)
show_server_hop_transfer_screen(input["server_hop"])
+#define PR_ANNOUNCEMENTS_PER_ROUND 5 //The number of unique PR announcements allowed per round
+ //This makes sure that a single person can only spam 3 reopens and 3 closes before being ignored
+
+/world/proc/AnnouncePR(announcement, list/payload)
+ var/static/list/PRcounts = list() //PR id -> number of times announced this round
+ var/id = "[payload["pull_request"]["id"]]"
+ if(!PRcounts[id])
+ PRcounts[id] = 1
+ else
+ ++PRcounts[id]
+ if(PRcounts[id] > PR_ANNOUNCEMENTS_PER_ROUND)
+ return
+
+#define CHAT_PULLR 64 //defined in preferences.dm, but not available here at compilation time
+ for(var/client/C in GLOB.clients)
+ if(C.prefs && (C.prefs.chat_toggles & CHAT_PULLR))
+ C << "PR: [announcement]"
+#undef CHAT_PULLR
+
#define WORLD_REBOOT(X) log_world("World rebooted at [time_stamp()]"); ..(X); return;
/world/Reboot(var/reason, var/feedback_c, var/feedback_r, var/time)
if (reason == 1) //special reboot, do none of the normal stuff
@@ -226,7 +241,7 @@
/world/proc/RoundEndAnimation(round_end_sound_sent)
set waitfor = FALSE
var/round_end_sound
- if(!SSticker && SSticker.round_end_sound)
+ if(SSticker.round_end_sound)
round_end_sound = SSticker.round_end_sound
if (!round_end_sound_sent)
for(var/thing in GLOB.clients)
diff --git a/html/changelogs/AutoChangeLog-pr-676.yml b/html/changelogs/AutoChangeLog-pr-676.yml
new file mode 100644
index 0000000000..73c6fac766
--- /dev/null
+++ b/html/changelogs/AutoChangeLog-pr-676.yml
@@ -0,0 +1,5 @@
+author: "Joan"
+delete-after: True
+changes:
+ - rscadd: "Proselytizers can now charge from Sigils of Transmission at a rate of 1000W per second."
+ - rscadd: "Sigils of Transmission can be charged with brass at a rate of 250W per sheet."
diff --git a/html/changelogs/AutoChangeLog-pr-682.yml b/html/changelogs/AutoChangeLog-pr-682.yml
new file mode 100644
index 0000000000..c55c645e6e
--- /dev/null
+++ b/html/changelogs/AutoChangeLog-pr-682.yml
@@ -0,0 +1,4 @@
+author: "Swindly"
+delete-after: True
+changes:
+ - tweak: "Mercury and Lithium make people move when not in space instead of when in space."
diff --git a/html/changelogs/AutoChangeLog-pr-698.yml b/html/changelogs/AutoChangeLog-pr-698.yml
new file mode 100644
index 0000000000..40e55644b5
--- /dev/null
+++ b/html/changelogs/AutoChangeLog-pr-698.yml
@@ -0,0 +1,4 @@
+author: "CitadelStationBot"
+delete-after: True
+changes:
+ - rscadd: "You can now make holocalls! Simply stand on a pad, bring up the menu, and select the holopad you wish to call. Remain still until someone answers. When they do, you'll be able to act just like an AI hologram until the call ends"
diff --git a/html/changelogs/AutoChangeLog-pr-701.yml b/html/changelogs/AutoChangeLog-pr-701.yml
new file mode 100644
index 0000000000..8848bcb450
--- /dev/null
+++ b/html/changelogs/AutoChangeLog-pr-701.yml
@@ -0,0 +1,7 @@
+author: "ninjanomnom"
+delete-after: True
+changes:
+ - tweak: "TEG displays power in kw or MW now"
+ - tweak: "TEG power bar only maxes over 1MW now"
+ - experiment: "Moves TEG to SSair"
+ - experiment: "Moves SM to SSair"
diff --git a/html/changelogs/AutoChangeLog-pr-706.yml b/html/changelogs/AutoChangeLog-pr-706.yml
new file mode 100644
index 0000000000..bef4ff2c24
--- /dev/null
+++ b/html/changelogs/AutoChangeLog-pr-706.yml
@@ -0,0 +1,4 @@
+author: "Kor, Goof and Plizzard"
+delete-after: True
+changes:
+ - rscadd: "Adds persistent trophy cases. They are not on any map yet."
diff --git a/html/changelogs/AutoChangeLog-pr-708.yml b/html/changelogs/AutoChangeLog-pr-708.yml
new file mode 100644
index 0000000000..6cb7c07312
--- /dev/null
+++ b/html/changelogs/AutoChangeLog-pr-708.yml
@@ -0,0 +1,4 @@
+author: "CitadelStationBot"
+delete-after: True
+changes:
+ - bugfix: "Squishy plants will now affect walls and other turfs they get squished on"
diff --git a/html/changelogs/AutoChangeLog-pr-714.yml b/html/changelogs/AutoChangeLog-pr-714.yml
new file mode 100644
index 0000000000..d5e4582f40
--- /dev/null
+++ b/html/changelogs/AutoChangeLog-pr-714.yml
@@ -0,0 +1,4 @@
+author: "XDTM"
+delete-after: True
+changes:
+ - tweak: "Blood Cult's talisman of Horrors now works at range. It will still give no warning to the victim."
diff --git a/html/changelogs/AutoChangeLog-pr-717.yml b/html/changelogs/AutoChangeLog-pr-717.yml
new file mode 100644
index 0000000000..fbb98e0039
--- /dev/null
+++ b/html/changelogs/AutoChangeLog-pr-717.yml
@@ -0,0 +1,5 @@
+author: "coiax"
+delete-after: True
+changes:
+ - rscadd: "When talking on the alien hivemind, a person will be identified by
+their real name, rather than who they are disguised as."
diff --git a/html/changelogs/AutoChangeLog-pr-727.yml b/html/changelogs/AutoChangeLog-pr-727.yml
new file mode 100644
index 0000000000..2eaec0638a
--- /dev/null
+++ b/html/changelogs/AutoChangeLog-pr-727.yml
@@ -0,0 +1,4 @@
+author: "deathride58"
+delete-after: True
+changes:
+ - tweak: "Fixed the slimecore HUD's neck slot sprite."
diff --git a/html/changelogs/AutoChangeLog-pr-733.yml b/html/changelogs/AutoChangeLog-pr-733.yml
new file mode 100644
index 0000000000..ef779f70a1
--- /dev/null
+++ b/html/changelogs/AutoChangeLog-pr-733.yml
@@ -0,0 +1,4 @@
+author: "BeeSting12"
+delete-after: True
+changes:
+ - bugfix: "Omega shuttle now has lighting."
diff --git a/html/changelogs/AutoChangeLog-pr-745.yml b/html/changelogs/AutoChangeLog-pr-745.yml
new file mode 100644
index 0000000000..b9aa3fddd2
--- /dev/null
+++ b/html/changelogs/AutoChangeLog-pr-745.yml
@@ -0,0 +1,4 @@
+author: "CitadelStationBot"
+delete-after: True
+changes:
+ - bugfix: "revenants now properly resurrect from ectoplasm, as opposed to ectoplasm merely spawning a new grief ghost"
diff --git a/html/changelogs/AutoChangeLog-pr-746.yml b/html/changelogs/AutoChangeLog-pr-746.yml
new file mode 100644
index 0000000000..ddeea1d732
--- /dev/null
+++ b/html/changelogs/AutoChangeLog-pr-746.yml
@@ -0,0 +1,4 @@
+author: "CitadelStationBot"
+delete-after: True
+changes:
+ - bugfix: "Turrets can no longer see invisible things, such as unrevealed revenants"
diff --git a/html/changelogs/AutoChangeLog-pr-747.yml b/html/changelogs/AutoChangeLog-pr-747.yml
new file mode 100644
index 0000000000..583f6b5e56
--- /dev/null
+++ b/html/changelogs/AutoChangeLog-pr-747.yml
@@ -0,0 +1,4 @@
+author: "QualityVan"
+delete-after: True
+changes:
+ - rscadd: "Point flashlights at mouths to see what's inside them"
diff --git a/html/changelogs/AutoChangeLog-pr-748.yml b/html/changelogs/AutoChangeLog-pr-748.yml
new file mode 100644
index 0000000000..7ad62adec8
--- /dev/null
+++ b/html/changelogs/AutoChangeLog-pr-748.yml
@@ -0,0 +1,5 @@
+author: "Moonlighting Mac says"
+delete-after: True
+changes:
+ - rscadd: "Courtesy of the art & crafts division, imitation basalt tiles themed on the rough volcanic terrain of lavaland are now available to be made out of sandstone."
+ - experiment: "The manufacturer even managed to replicate the way that it lights up with volcanic energy, it is the perfect accompaniment to other fake (or real) lava-land tiles or a independent piece."
diff --git a/html/changelogs/AutoChangeLog-pr-756.yml b/html/changelogs/AutoChangeLog-pr-756.yml
new file mode 100644
index 0000000000..7ef015b31c
--- /dev/null
+++ b/html/changelogs/AutoChangeLog-pr-756.yml
@@ -0,0 +1,6 @@
+author: "lordpidey"
+delete-after: True
+changes:
+ - rscadd: "There is a new traitor poison, spewium. It will cause uncontrollable vomiting, which gets worse the longer it's in your system. An overdose can cause vomiting of organs."
+ - tweak: "Committing suicide with a gas pump can now shoot out random organs."
+ - bugfix: "Toxic vomit now shows up as intended."
diff --git a/html/changelogs/AutoChangeLog-pr-760.yml b/html/changelogs/AutoChangeLog-pr-760.yml
new file mode 100644
index 0000000000..b0296b2330
--- /dev/null
+++ b/html/changelogs/AutoChangeLog-pr-760.yml
@@ -0,0 +1,4 @@
+author: "bgobandit"
+delete-after: True
+changes:
+ - tweak: "The Syndicate has added basic functionality to their state-of-the-art equipment. Nuke ops can now donate all TCs at once."
diff --git a/html/changelogs/AutoChangeLog-pr-764.yml b/html/changelogs/AutoChangeLog-pr-764.yml
new file mode 100644
index 0000000000..87210fcb7a
--- /dev/null
+++ b/html/changelogs/AutoChangeLog-pr-764.yml
@@ -0,0 +1,4 @@
+author: "QualityVan"
+delete-after: True
+changes:
+ - bugfix: "Dental implants stay with the head they're in"
diff --git a/html/changelogs/AutoChangeLog-pr-771.yml b/html/changelogs/AutoChangeLog-pr-771.yml
new file mode 100644
index 0000000000..031ec64151
--- /dev/null
+++ b/html/changelogs/AutoChangeLog-pr-771.yml
@@ -0,0 +1,4 @@
+author: "BeeSting12"
+delete-after: True
+changes:
+ - bugfix: "Pubbystation no longer has two airlocks stacked on top of each other leading into xenobiology's kill room."
diff --git a/html/changelogs/AutoChangeLog-pr-781.yml b/html/changelogs/AutoChangeLog-pr-781.yml
new file mode 100644
index 0000000000..08a5c148ff
--- /dev/null
+++ b/html/changelogs/AutoChangeLog-pr-781.yml
@@ -0,0 +1,4 @@
+author: "CitadelStationBot"
+delete-after: True
+changes:
+ - tweak: "Teslas now give off light"
diff --git a/html/changelogs/AutoChangeLog-pr-792.yml b/html/changelogs/AutoChangeLog-pr-792.yml
new file mode 100644
index 0000000000..9d2ccfebde
--- /dev/null
+++ b/html/changelogs/AutoChangeLog-pr-792.yml
@@ -0,0 +1,6 @@
+author: "BeeSting12"
+delete-after: True
+changes:
+ - rscadd: "Deltastation's chemistry now has a screwdriver."
+ - bugfix: "Deltastation's morgue no longer has a blue tile."
+ - bugfix: "Deltastation's chemistry smart fridge is no longer blocked by a disposal unit."
diff --git a/html/changelogs/AutoChangeLog-pr-800.yml b/html/changelogs/AutoChangeLog-pr-800.yml
new file mode 100644
index 0000000000..798c98c64b
--- /dev/null
+++ b/html/changelogs/AutoChangeLog-pr-800.yml
@@ -0,0 +1,4 @@
+author: "coiax"
+delete-after: True
+changes:
+ - tweak: "The lavaland Seed Vault ruin can spawn only once."
diff --git a/html/changelogs/AutoChangeLog-pr-801.yml b/html/changelogs/AutoChangeLog-pr-801.yml
new file mode 100644
index 0000000000..756cf33927
--- /dev/null
+++ b/html/changelogs/AutoChangeLog-pr-801.yml
@@ -0,0 +1,6 @@
+author: "CitadelStationBot"
+delete-after: True
+changes:
+ - rscadd: "Internal Affairs Agents now obtain the kill objectives of their targets when they die."
+ - rscadd: "Internal Affairs Agents now have an integrated nanotrasen pinpointer that tracks their target at distances further than ten squares."
+ - rscadd: "Internal Affairs Agents will now lose any restrictions on collateral damage and gain a \"Die a glorious death\" objective upon becoming the last man standing, and revert if any of their targets are cloned."
diff --git a/html/changelogs/AutoChangeLog-pr-805.yml b/html/changelogs/AutoChangeLog-pr-805.yml
new file mode 100644
index 0000000000..be4a17ddf7
--- /dev/null
+++ b/html/changelogs/AutoChangeLog-pr-805.yml
@@ -0,0 +1,5 @@
+author: "CitadelStationBot"
+delete-after: True
+changes:
+ - rscadd: "Reduction to nutrition when consuming Miner's salve."
+ - rscdel: "Stun/weaken that bypasses bugged chemical protection when consuming Miner's salve."
diff --git a/html/changelogs/AutoChangeLog-pr-809.yml b/html/changelogs/AutoChangeLog-pr-809.yml
new file mode 100644
index 0000000000..06fb6139cc
--- /dev/null
+++ b/html/changelogs/AutoChangeLog-pr-809.yml
@@ -0,0 +1,5 @@
+author: "QualityVan"
+delete-after: True
+changes:
+ - rscadd: "Cargo can order restocking units for NanoMed vending machines"
+ - rscadd: "NanoMed vending machines can be build and unbuilt"
diff --git a/html/changelogs/AutoChangeLog-pr-815.yml b/html/changelogs/AutoChangeLog-pr-815.yml
new file mode 100644
index 0000000000..6472c7a13d
--- /dev/null
+++ b/html/changelogs/AutoChangeLog-pr-815.yml
@@ -0,0 +1,4 @@
+author: "Penguaro"
+delete-after: True
+changes:
+ - bugfix: "Adjusted the Examine description of the right-most tiles of the Space Station 13 sign to be consistent with the rest of the tiles."
diff --git a/html/changelogs/AutoChangeLog-pr-824.yml b/html/changelogs/AutoChangeLog-pr-824.yml
new file mode 100644
index 0000000000..625034ab7c
--- /dev/null
+++ b/html/changelogs/AutoChangeLog-pr-824.yml
@@ -0,0 +1,5 @@
+author: "CitadelStationBot"
+delete-after: True
+changes:
+ - rscadd: "Showers and sinks added to gulag and mining station for hygiene and fire safety."
+ - rscadd: "Watertanks added to mining station for convenient fire extinguisher refill."
diff --git a/html/changelogs/AutoChangeLog-pr-825.yml b/html/changelogs/AutoChangeLog-pr-825.yml
new file mode 100644
index 0000000000..ee3a963c30
--- /dev/null
+++ b/html/changelogs/AutoChangeLog-pr-825.yml
@@ -0,0 +1,4 @@
+author: "Robustin"
+delete-after: True
+changes:
+ - tweak: "c4 planting is now 40% faster"
diff --git a/html/changelogs/AutoChangeLog-pr-827.yml b/html/changelogs/AutoChangeLog-pr-827.yml
new file mode 100644
index 0000000000..e16167448d
--- /dev/null
+++ b/html/changelogs/AutoChangeLog-pr-827.yml
@@ -0,0 +1,4 @@
+author: "Jay"
+delete-after: True
+changes:
+ - rscadd: "Adds finger snapping emote. Use say *snap"
diff --git a/html/changelogs/AutoChangeLog-pr-829.yml b/html/changelogs/AutoChangeLog-pr-829.yml
new file mode 100644
index 0000000000..619bc85876
--- /dev/null
+++ b/html/changelogs/AutoChangeLog-pr-829.yml
@@ -0,0 +1,4 @@
+author: "Penguaro"
+delete-after: True
+changes:
+ - bugfix: "Anywhere there was lava below a tile on the station is now space."
diff --git a/html/changelogs/AutoChangeLog-pr-841.yml b/html/changelogs/AutoChangeLog-pr-841.yml
new file mode 100644
index 0000000000..3c27ac83c8
--- /dev/null
+++ b/html/changelogs/AutoChangeLog-pr-841.yml
@@ -0,0 +1,5 @@
+author: "Moonlighting Mac"
+delete-after: True
+changes:
+ - experiment: "Due to budget cuts and oil synthesis replacing expensive processes of digging up haunted primeval ashwalker burial grounds, Nanotransen has taught chemists how to make plastic from chemicals in the hopes that new plastic products can reduce expenditure on metal and glass."
+ - rscadd: "you can now make plastic sheets from chemistry out of heated up crude oil, ash & sodium chloride"
diff --git a/icons/effects/clockwork_effects.dmi b/icons/effects/clockwork_effects.dmi
index 8bbf24a7ef..b2e15da1d0 100644
Binary files a/icons/effects/clockwork_effects.dmi and b/icons/effects/clockwork_effects.dmi differ
diff --git a/icons/mob/jungle/arachnid.dmi b/icons/mob/jungle/arachnid.dmi
new file mode 100644
index 0000000000..a1db8e351f
Binary files /dev/null and b/icons/mob/jungle/arachnid.dmi differ
diff --git a/icons/mob/screen_slimecore.dmi b/icons/mob/screen_slimecore.dmi
index bc33ad6e37..63d67e6fba 100644
Binary files a/icons/mob/screen_slimecore.dmi and b/icons/mob/screen_slimecore.dmi differ
diff --git a/icons/obj/flora/jungletrees.dmi b/icons/obj/flora/jungletrees.dmi
index 461ac0b265..67c7e0f463 100644
Binary files a/icons/obj/flora/jungletrees.dmi and b/icons/obj/flora/jungletrees.dmi differ
diff --git a/icons/obj/food/soupsalad.dmi b/icons/obj/food/soupsalad.dmi
index fe4c07362a..c6df0a2603 100644
Binary files a/icons/obj/food/soupsalad.dmi and b/icons/obj/food/soupsalad.dmi differ
diff --git a/icons/obj/tiles.dmi b/icons/obj/tiles.dmi
index d629cfe24d..5a8afeee51 100644
Binary files a/icons/obj/tiles.dmi and b/icons/obj/tiles.dmi differ
diff --git a/icons/obj/vending_restock.dmi b/icons/obj/vending_restock.dmi
index aa9f2873f0..eac7b8a266 100644
Binary files a/icons/obj/vending_restock.dmi and b/icons/obj/vending_restock.dmi differ
diff --git a/icons/turf/floors.dmi b/icons/turf/floors.dmi
index a1cd8fb2f9..28bc9e28d3 100644
Binary files a/icons/turf/floors.dmi and b/icons/turf/floors.dmi differ
diff --git a/icons/turf/floors/junglechasm.dmi b/icons/turf/floors/junglechasm.dmi
new file mode 100644
index 0000000000..699a3b667c
Binary files /dev/null and b/icons/turf/floors/junglechasm.dmi differ
diff --git a/sound/effects/snap01.ogg b/sound/effects/snap01.ogg
new file mode 100644
index 0000000000..aa7ab9f5bf
Binary files /dev/null and b/sound/effects/snap01.ogg differ
diff --git a/config/admin_nicknames.txt b/strings/admin_nicknames.txt
similarity index 100%
rename from config/admin_nicknames.txt
rename to strings/admin_nicknames.txt
diff --git a/config/sillytips.txt b/strings/sillytips.txt
similarity index 100%
rename from config/sillytips.txt
rename to strings/sillytips.txt
diff --git a/config/tips.txt b/strings/tips.txt
similarity index 100%
rename from config/tips.txt
rename to strings/tips.txt
diff --git a/tgstation.dme b/tgstation.dme
index 1f3ef27802..543fb04f6c 100644
--- a/tgstation.dme
+++ b/tgstation.dme
@@ -244,6 +244,7 @@
#include "code\datums\dog_fashion.dm"
#include "code\datums\emotes.dm"
#include "code\datums\forced_movement.dm"
+#include "code\datums\holocall.dm"
#include "code\datums\hud.dm"
#include "code\datums\map_config.dm"
#include "code\datums\martial.dm"
@@ -1714,6 +1715,7 @@
#include "code\modules\mob\living\simple_animal\hostile\hivebot.dm"
#include "code\modules\mob\living\simple_animal\hostile\hostile.dm"
#include "code\modules\mob\living\simple_animal\hostile\illusion.dm"
+#include "code\modules\mob\living\simple_animal\hostile\jungle_mobs.dm"
#include "code\modules\mob\living\simple_animal\hostile\killertomato.dm"
#include "code\modules\mob\living\simple_animal\hostile\mecha_pilot.dm"
#include "code\modules\mob\living\simple_animal\hostile\mimic.dm"
@@ -2012,6 +2014,7 @@
#include "code\modules\shuttle\arrivals.dm"
#include "code\modules\shuttle\assault_pod.dm"
#include "code\modules\shuttle\computer.dm"
+#include "code\modules\shuttle\elevator.dm"
#include "code\modules\shuttle\emergency.dm"
#include "code\modules\shuttle\ferry.dm"
#include "code\modules\shuttle\manipulator.dm"