diff --git a/_maps/RandomRuins/LavaRuins/lavaland_surface_animal_hospital.dmm b/_maps/RandomRuins/LavaRuins/lavaland_surface_animal_hospital.dmm
index d1272fcd828..b783a48b9b9 100644
--- a/_maps/RandomRuins/LavaRuins/lavaland_surface_animal_hospital.dmm
+++ b/_maps/RandomRuins/LavaRuins/lavaland_surface_animal_hospital.dmm
@@ -220,8 +220,10 @@
},
/area/ruin/powered)
"aF" = (
-/obj/machinery/door/unpowered/shuttle,
-/turf/open/floor/plating{
+/obj/machinery/door/unpowered/shuttle{
+ name = "Restroom"
+ },
+/turf/open/floor/plasteel/bar{
baseturf = /turf/open/floor/plating/lava/smooth/lava_land_surface
},
/area/ruin/powered)
@@ -257,10 +259,7 @@
},
/area/ruin/powered)
"aM" = (
-/obj/effect/mob_spawn/human/doctor/alive{
- flavour_text = "You were putting in your hours as a vet in the local animal hospital when a massive bluespace translocation shunted you across the galaxy. Can you survive on this desolate wasteland..?";
- id_job = "Veterinarian"
- },
+/obj/effect/mob_spawn/human/doctor/alive/lavaland,
/turf/open/floor/plasteel/blue/side{
baseturf = /turf/open/floor/plating/lava/smooth/lava_land_surface;
dir = 1
@@ -384,6 +383,10 @@
"bd" = (
/obj/structure/table/glass,
/obj/item/weapon/storage/box/gloves,
+/obj/item/weapon/storage/box/masks{
+ pixel_x = 3;
+ pixel_y = 3
+ },
/turf/open/floor/plasteel/white{
baseturf = /turf/open/floor/plating/lava/smooth/lava_land_surface
},
@@ -530,7 +533,7 @@
"bv" = (
/obj/effect/mob_spawn/mouse{
dir = 4;
- flavour_text = "You're a mousey! You're getting pretty old as mice go, and you haven't been feeling well as of late. Your master loves you a lot so he took you to this place so you can get better! You can't wait to see him again!";
+ flavour_text = "You're a mousey! You're getting pretty old as mice go, and you haven't been feeling well as of late. Your master loves you a lot so he took you to this place so you can get better! You can't wait to see him again!";
mob_name = "Stallman Jr."
},
/turf/open/floor/plasteel/white{
@@ -546,9 +549,9 @@
"bx" = (
/obj/machinery/door/airlock/medical{
name = "Patient Room";
- req_access_txt = "5"
+ req_access_txt = "0"
},
-/turf/open/floor/plating{
+/turf/open/floor/plasteel/white{
baseturf = /turf/open/floor/plating/lava/smooth/lava_land_surface
},
/area/ruin/powered)
@@ -641,8 +644,10 @@
},
/area/ruin/powered)
"bJ" = (
-/obj/machinery/door/airlock/glass_large,
-/turf/open/floor/plating{
+/obj/machinery/door/airlock/glass_large{
+ name = "Ian's Pet Care"
+ },
+/turf/open/floor/plasteel{
baseturf = /turf/open/floor/plating/lava/smooth/lava_land_surface
},
/area/ruin/powered)
@@ -673,7 +678,7 @@
"bN" = (
/obj/effect/mob_spawn/cow{
dir = 4;
- flavour_text = "You're a cow. You've lived a pampered life as a prized show heifer, a real blue-ribbon winner. After showing signs of a minor respiratory infection, your master took you to the hospital right away. He'd better come back soon, you're getting quite impatient.";
+ flavour_text = "You're a cow. You've lived a pampered life as a prized show heifer, a real blue-ribbon winner. After showing signs of a minor respiratory infection, your master took you to the hospital right away. He'd better come back soon. You're getting quite impatient.";
mob_name = "Flossie"
},
/turf/open/floor/plasteel/white{
@@ -706,7 +711,10 @@
"bR" = (
/obj/structure/table,
/obj/machinery/cell_charger,
-/obj/item/weapon/melee/baton/cattleprod,
+/obj/item/weapon/melee/baton/cattleprod{
+ desc = "On-the-fly rabies treatment.";
+ name = "cattle prod"
+ },
/obj/item/weapon/stock_parts/cell/high,
/turf/open/floor/plasteel/blue/side{
baseturf = /turf/open/floor/plating/lava/smooth/lava_land_surface;
@@ -802,13 +810,66 @@
},
/area/ruin/powered)
"cf" = (
-/obj/machinery/sleeper{
- icon_state = "sleeper-open";
- dir = 4
+/obj/structure/closet/l3closet,
+/turf/open/floor/plasteel/white{
+ baseturf = /turf/open/floor/plating/lava/smooth/lava_land_surface
},
-/turf/open/floor/plasteel/blue/side{
- baseturf = /turf/open/floor/plating/lava/smooth/lava_land_surface;
- dir = 1
+/area/ruin/powered)
+"cm" = (
+/obj/machinery/door/unpowered/shuttle{
+ name = "Tool Storage"
+ },
+/turf/open/floor/plating{
+ baseturf = /turf/open/floor/plating/lava/smooth/lava_land_surface
+ },
+/area/ruin/powered)
+"cl" = (
+/obj/machinery/door/unpowered/shuttle{
+ name = "Safety Supplies"
+ },
+/turf/open/floor/plasteel/white{
+ baseturf = /turf/open/floor/plating/lava/smooth/lava_land_surface
+ },
+/area/ruin/powered)
+"ck" = (
+/obj/machinery/door/unpowered/shuttle{
+ name = "Medical Supplies"
+ },
+/turf/open/floor/plasteel/white{
+ baseturf = /turf/open/floor/plating/lava/smooth/lava_land_surface
+ },
+/area/ruin/powered)
+"cj" = (
+/obj/machinery/door/unpowered/shuttle{
+ name = "Morgue"
+ },
+/turf/open/floor/plating{
+ baseturf = /turf/open/floor/plating/lava/smooth/lava_land_surface
+ },
+/area/ruin/powered)
+"ci" = (
+/obj/machinery/door/unpowered/shuttle{
+ desc = "There's a note wedged in the seam saying something about directing pizza here.";
+ name = "Staff Entrance"
+ },
+/turf/open/floor/plating{
+ baseturf = /turf/open/floor/plating/lava/smooth/lava_land_surface
+ },
+/area/ruin/powered)
+"ch" = (
+/obj/machinery/door/unpowered/shuttle{
+ name = "Emergency Care"
+ },
+/turf/open/floor/plasteel/white{
+ baseturf = /turf/open/floor/plating/lava/smooth/lava_land_surface
+ },
+/area/ruin/powered)
+"cg" = (
+/obj/machinery/door/unpowered/shuttle{
+ name = "Break Room"
+ },
+/turf/open/floor/plasteel/cmo{
+ baseturf = /turf/open/floor/plating/lava/smooth/lava_land_surface
},
/area/ruin/powered)
@@ -942,7 +1003,7 @@ ae
ae
ae
aE
-aF
+ci
ae
aE
aT
@@ -974,11 +1035,11 @@ ay
ae
aK
aK
-aF
+cj
aU
aZ
bg
-aF
+cj
aK
bp
by
@@ -1061,7 +1122,7 @@ ae
ai
as
as
-aF
+cg
aK
aP
ae
@@ -1094,11 +1155,11 @@ as
ae
aM
aK
-aF
+ck
ao
bb
ao
-aF
+ck
aK
aK
aK
@@ -1133,7 +1194,7 @@ bl
bt
aK
aK
-aU
+aK
aJ
aJ
ab
@@ -1154,11 +1215,11 @@ as
ae
aM
aK
-aF
+cl
ao
bc
ao
-aF
+cl
aK
aK
aK
@@ -1181,7 +1242,7 @@ ae
am
as
as
-aF
+cg
aK
aP
ae
@@ -1215,7 +1276,7 @@ aH
aL
aP
ae
-aV
+cf
bd
bj
ae
@@ -1271,10 +1332,10 @@ cc
ce
ao
ao
-aF
+ch
aK
aK
-aF
+cm
aX
be
bk
diff --git a/_maps/map_files/generic/z2.dmm b/_maps/map_files/generic/z2.dmm
index 28148da6ec8..8dc216d7bb7 100644
--- a/_maps/map_files/generic/z2.dmm
+++ b/_maps/map_files/generic/z2.dmm
@@ -2496,7 +2496,7 @@
desc = "A altar dedicated to the Wizard's Federation"
},
/obj/item/weapon/kitchen/knife/ritual,
-/turf/open/floor/plasteel/cult,
+/turf/open/floor/engine/cult,
/area/wizard_station)
"hM" = (
/obj/structure/flora/bush,
@@ -3066,7 +3066,7 @@
},
/area/wizard_station)
"jx" = (
-/turf/open/floor/plasteel/cult/airless,
+/turf/open/floor/engine/cult/airless,
/area/wizard_station)
"jy" = (
/obj/item/clothing/head/collectable/paper,
@@ -3183,7 +3183,7 @@
/area/wizard_station)
"jQ" = (
/obj/effect/decal/cleanable/blood/gibs/body,
-/turf/open/floor/plasteel/cult/airless,
+/turf/open/floor/engine/cult/airless,
/area/wizard_station)
"jR" = (
/turf/closed/indestructible/riveted,
@@ -3311,7 +3311,7 @@
/area/wizard_station)
"kk" = (
/obj/effect/decal/cleanable/blood,
-/turf/open/floor/plasteel/cult/airless,
+/turf/open/floor/engine/cult/airless,
/area/wizard_station)
"kl" = (
/obj/structure/showcase{
@@ -3320,9 +3320,7 @@
icon_state = "nim";
name = "wizard of yendor showcase"
},
-/turf/open/floor/plasteel/cult/airless{
- icon_state = "cultdamage4"
- },
+/turf/open/floor/engine/cult/airless,
/area/wizard_station)
"km" = (
/turf/closed/indestructible/fakeglass{
@@ -3446,12 +3444,10 @@
/area/wizard_station)
"kF" = (
/obj/effect/decal/cleanable/blood/splatter,
-/turf/open/floor/plasteel/cult{
- icon_state = "cultdamage"
- },
+/turf/open/floor/engine/cult,
/area/wizard_station)
"kG" = (
-/turf/open/floor/plasteel/cult,
+/turf/open/floor/engine/cult,
/area/wizard_station)
"kH" = (
/turf/closed/indestructible/fakeglass,
@@ -3536,7 +3532,7 @@
/area/wizard_station)
"kT" = (
/obj/effect/forcefield,
-/turf/open/floor/plasteel/cult,
+/turf/open/floor/engine/cult,
/area/wizard_station)
"kU" = (
/turf/open/floor/plasteel/cult{
@@ -3781,9 +3777,7 @@
/area/wizard_station)
"lJ" = (
/obj/machinery/vending/snack,
-/turf/open/floor/plasteel/cult{
- icon_state = "cultdamage"
- },
+/turf/open/floor/engine/cult,
/area/wizard_station)
"lK" = (
/turf/open/floor/plasteel/darkblue/side{
@@ -3814,14 +3808,14 @@
anchored = 1;
name = "Break Room"
},
-/turf/open/floor/plasteel/cult,
+/turf/open/floor/engine/cult,
/area/wizard_station)
"lR" = (
/obj/machinery/door/airlock{
icon = 'icons/obj/doors/airlocks/station/uranium.dmi';
name = "Break Room"
},
-/turf/open/floor/plasteel/cult,
+/turf/open/floor/engine/cult,
/area/wizard_station)
"lS" = (
/turf/open/floor/plasteel/blue,
@@ -3844,12 +3838,12 @@
/obj/structure/table/wood,
/obj/item/stack/medical/bruise_pack,
/obj/item/stack/medical/ointment,
-/turf/open/floor/plasteel/cult,
+/turf/open/floor/engine/cult,
/area/wizard_station)
"lY" = (
/obj/structure/table/wood,
/obj/item/weapon/retractor,
-/turf/open/floor/plasteel/cult,
+/turf/open/floor/engine/cult,
/area/wizard_station)
"lZ" = (
/obj/structure/table/wood,
@@ -3859,26 +3853,24 @@
/obj/structure/mirror/magic{
pixel_y = 28
},
-/turf/open/floor/plasteel/cult,
+/turf/open/floor/engine/cult,
/area/wizard_station)
"ma" = (
/obj/structure/table/wood,
/obj/item/clothing/suit/wizrobe/magusred,
/obj/item/clothing/head/wizard/magus,
/obj/item/weapon/staff,
-/turf/open/floor/plasteel/cult,
+/turf/open/floor/engine/cult,
/area/wizard_station)
"mb" = (
/obj/structure/rack,
/obj/item/clothing/head/helmet/space/hardsuit/wizard,
-/turf/open/floor/plasteel/cult/airless,
+/turf/open/floor/engine/cult,
/area/wizard_station)
"mc" = (
/obj/effect/decal/cleanable/blood/splatter,
/obj/effect/decal/cleanable/blood/gibs/body,
-/turf/open/floor/plasteel/cult/airless{
- icon_state = "cultdamage"
- },
+/turf/open/floor/engine/cult,
/area/wizard_station)
"md" = (
/obj/effect/forcefield,
@@ -3974,7 +3966,7 @@
/obj/item/clothing/head/wizard/red,
/obj/item/weapon/staff,
/obj/item/clothing/shoes/sandal,
-/turf/open/floor/plasteel/cult,
+/turf/open/floor/engine/cult,
/area/wizard_station)
"ms" = (
/obj/effect/decal/cleanable/blood/splatter,
@@ -3982,9 +3974,7 @@
health = 9999
},
/obj/item/clothing/suit/space/hardsuit/wizard,
-/turf/open/floor/plasteel/cult/airless{
- icon_state = "cultdamage"
- },
+/turf/open/floor/engine/cult,
/area/wizard_station)
"mt" = (
/turf/open/floor/plasteel/cult,
@@ -4041,7 +4031,7 @@
/area/wizard_station)
"mA" = (
/obj/structure/bookcase,
-/turf/open/floor/plasteel/cult,
+/turf/open/floor/engine/cult,
/area/wizard_station)
"mB" = (
/obj/structure/grille/broken{
@@ -4057,14 +4047,14 @@
/obj/item/clothing/suit/wizrobe/marisa,
/obj/item/clothing/head/wizard/marisa,
/obj/item/weapon/staff/broom,
-/turf/open/floor/plasteel/cult,
+/turf/open/floor/engine/cult,
/area/wizard_station)
"mE" = (
/obj/effect/decal/cleanable/blood/splatter,
/mob/living/simple_animal/hostile/creature{
name = "Experiment 35b"
},
-/turf/open/floor/plasteel/cult/airless,
+/turf/open/floor/engine/cult,
/area/wizard_station)
"mF" = (
/obj/machinery/door/poddoor/preopen,
@@ -4156,7 +4146,7 @@
"mR" = (
/obj/effect/decal/remains/human,
/obj/effect/decal/cleanable/blood/splatter,
-/turf/open/floor/plasteel/cult/airless,
+/turf/open/floor/engine/cult,
/area/wizard_station)
"mS" = (
/turf/open/floor/plasteel/cult,
@@ -4183,19 +4173,17 @@
icon_state = "wooden_chair_wings";
dir = 1
},
-/turf/open/floor/plasteel/cult,
+/turf/open/floor/engine/cult,
/area/wizard_station)
"mW" = (
/obj/structure/cult/pylon,
-/turf/open/floor/plasteel/cult,
+/turf/open/floor/engine/cult,
/area/wizard_station)
"mX" = (
/obj/effect/decal/cleanable/blood/splatter,
/obj/structure/rack,
/obj/item/weapon/staff,
-/turf/open/floor/plasteel/cult/airless{
- icon_state = "cultdamage"
- },
+/turf/open/floor/engine/cult,
/area/wizard_station)
"mY" = (
/obj/effect/decal/cleanable/blood/splatter,
@@ -4207,9 +4195,7 @@
"mZ" = (
/obj/effect/decal/cleanable/blood/splatter,
/obj/effect/forcefield,
-/turf/open/floor/plasteel/cult/airless{
- icon_state = "cultdamage"
- },
+/turf/open/floor/engine/cult,
/area/wizard_station)
"na" = (
/turf/open/floor/plasteel/cult/airless{
@@ -4221,14 +4207,14 @@
anchored = 1;
name = "Corridor A"
},
-/turf/open/floor/plasteel/cult,
+/turf/open/floor/engine/cult,
/area/wizard_station)
"nc" = (
/obj/machinery/door/airlock{
icon = 'icons/obj/doors/airlocks/station/uranium.dmi';
name = "Corridor A"
},
-/turf/open/floor/plasteel/cult,
+/turf/open/floor/engine/cult,
/area/wizard_station)
"nd" = (
/obj/structure/barricade/security,
@@ -4358,7 +4344,7 @@
icon = 'icons/obj/doors/airlocks/station/uranium.dmi';
name = "Personal Quarters"
},
-/turf/open/floor/plasteel/cult,
+/turf/open/floor/engine/cult,
/area/wizard_station)
"nz" = (
/turf/closed/indestructible/riveted,
@@ -4491,7 +4477,7 @@
/area/centcom/holding)
"nV" = (
/obj/structure/table/wood,
-/turf/open/floor/plasteel/cult,
+/turf/open/floor/engine/cult,
/area/wizard_station)
"nW" = (
/obj/structure/table/wood,
@@ -4500,7 +4486,7 @@
max_charges = 0;
name = "wand of emergency engine ignition"
},
-/turf/open/floor/plasteel/cult,
+/turf/open/floor/engine/cult,
/area/wizard_station)
"nX" = (
/obj/structure/shuttle/engine/propulsion{
@@ -4614,7 +4600,7 @@
desc = "A engine used in powering the wizards ship";
name = "magma engine"
},
-/turf/open/floor/plasteel/cult,
+/turf/open/floor/engine/cult,
/area/wizard_station)
"op" = (
/obj/structure/table,
@@ -5797,21 +5783,22 @@
},
/turf/open/floor/plasteel/delivery,
/area/centcom/ferry)
+"sa" = (
+/obj/structure/chair/wood/wings,
+/turf/open/floor/engine/cult,
+/area/wizard_station)
+"sb" = (
+/obj/structure/cult/tome,
+/turf/open/floor/engine/cult,
+/area/wizard_station)
+"sc" = (
+/obj/effect/decal/cleanable/blood/gibs/body,
+/turf/open/floor/engine/cult,
+/area/wizard_station)
"sd" = (
/obj/structure/flora/tree/pine,
/turf/open/floor/holofloor/snow/cold,
/area/holodeck/rec_center/winterwonderland)
-"sc" = (
-/obj/structure/flora/grass/brown,
-/turf/open/floor/holofloor/snow/cold,
-/area/holodeck/rec_center/winterwonderland)
-"sb" = (
-/obj/structure/flora/bush,
-/turf/open/floor/holofloor/snow/cold,
-/area/holodeck/rec_center/winterwonderland)
-"sa" = (
-/turf/open/floor/holofloor/snow/cold,
-/area/holodeck/rec_center/winterwonderland)
(1,1,1) = {"
aa
@@ -10616,10 +10603,10 @@ aa
aa
aa
jc
-lW
-mp
+sa
+sb
mA
-mp
+sb
mV
jc
aa
@@ -11902,7 +11889,7 @@ lx
ju
jc
lX
-mq
+kF
lz
lI
mW
@@ -12159,7 +12146,7 @@ ly
lG
jc
lY
-mq
+kF
ln
kG
kG
@@ -12664,7 +12651,7 @@ aa
ja
jw
jP
-jQ
+sc
kv
kF
kU
@@ -13458,7 +13445,7 @@ nL
jP
jc
jc
-ok
+sc
jc
jc
jc
@@ -14218,7 +14205,7 @@ mc
mt
mF
mS
-mY
+mc
jc
aa
aa
@@ -14728,7 +14715,7 @@ aa
aa
aa
ju
-me
+kF
lx
mH
mT
diff --git a/code/__DEFINES/is_helpers.dm b/code/__DEFINES/is_helpers.dm
index ed2e7c1c94d..83925584817 100644
--- a/code/__DEFINES/is_helpers.dm
+++ b/code/__DEFINES/is_helpers.dm
@@ -44,6 +44,8 @@
#define isconstruct(A) (istype(A, /mob/living/simple_animal/hostile/construct))
+#define isshade(A) (istype(A, /mob/living/simple_animal/shade))
+
#define isbear(A) (istype(A, /mob/living/simple_animal/hostile/bear))
#define iscarp(A) (istype(A, /mob/living/simple_animal/hostile/carp))
diff --git a/code/game/gamemodes/clock_cult/clock_items.dm b/code/game/gamemodes/clock_cult/clock_items.dm
index 3ab3dd80046..c3f7db74900 100644
--- a/code/game/gamemodes/clock_cult/clock_items.dm
+++ b/code/game/gamemodes/clock_cult/clock_items.dm
@@ -370,7 +370,6 @@
/obj/item/clothing/glasses/wraith_spectacles/equipped(mob/living/user, slot)
..()
- . = 0
if(slot != slot_glasses)
return
if(user.disabilities & BLIND)
@@ -385,8 +384,11 @@
user.adjust_blindness(30)
return
if(is_servant_of_ratvar(user))
+ tint = 0
user << "As you put on the spectacles, all is revealed to you.[ratvar_awakens ? "" : " Your eyes begin to itch - you cannot do this for long."]"
- . = 1
+ else
+ tint = 3
+ user << "You put on the spectacles, but you can't see through the glass."
/obj/item/clothing/glasses/wraith_spectacles/New()
..()
@@ -394,10 +396,10 @@
/obj/item/clothing/glasses/wraith_spectacles/Destroy()
SSobj.processing -= src
- ..()
+ return ..()
/obj/item/clothing/glasses/wraith_spectacles/process()
- if(ratvar_awakens || !ishuman(loc)) //If Ratvar is alive, the spectacles don't hurt your eyes
+ if(ratvar_awakens || !ishuman(loc) || !is_servant_of_ratvar(loc)) //If Ratvar is alive, the spectacles don't hurt your eyes
return 0
var/mob/living/carbon/human/H = loc
if(H.glasses != src)
diff --git a/code/game/gamemodes/clock_cult/clock_ratvar.dm b/code/game/gamemodes/clock_cult/clock_ratvar.dm
index 9e8eaffddf9..5c906e99f2b 100644
--- a/code/game/gamemodes/clock_cult/clock_ratvar.dm
+++ b/code/game/gamemodes/clock_cult/clock_ratvar.dm
@@ -39,7 +39,7 @@
SSshuttle.emergencyNoEscape = TRUE
SSobj.processing += src
var/area/gate_area = get_area(src)
- for(var/mob/M in mob_list)
+ for(var/M in mob_list)
if(is_servant_of_ratvar(M) || isobserver(M))
M << "A gateway to the Celestial Derelict has been created in [gate_area.map_name]!"
@@ -53,7 +53,7 @@
SSobj.processing -= src
if(!purpose_fulfilled)
var/area/gate_area = get_area(src)
- for(var/mob/M in mob_list)
+ for(var/M in mob_list)
if(is_servant_of_ratvar(M) || isobserver(M))
M << "A gateway to the Celestial Derelict has fallen at [gate_area.map_name]!"
world << sound(null, 0, channel = 8)
@@ -84,8 +84,8 @@
return 0 //Nice try, Toxins!
/obj/structure/clockwork/massive/celestial_gateway/process()
- if(prob(5))
- for(var/mob/M in mob_list)
+ if(!progress_in_seconds || prob(5))
+ for(var/M in mob_list)
M << "You hear otherworldly sounds from the [dir2text(get_dir(get_turf(M), get_turf(src)))]..."
if(!health)
return 0
diff --git a/code/game/gamemodes/clock_cult/clock_scripture.dm b/code/game/gamemodes/clock_cult/clock_scripture.dm
index a98feb3e591..0e302f4ae51 100644
--- a/code/game/gamemodes/clock_cult/clock_scripture.dm
+++ b/code/game/gamemodes/clock_cult/clock_scripture.dm
@@ -136,13 +136,13 @@ Judgement: 10 servants, 100 CV, and any existing AIs are converted or destroyed
invoker.say(pick(chant_invocations))
else
invoker.whisper(pick(chant_invocations))
- chant_effects()
+ chant_effects(i)
if(invoker && slab)
invoker << "You cease your chant."
chant_end_effects()
return 1
-/datum/clockwork_scripture/channeled/proc/chant_effects() //The chant's periodic effects
+/datum/clockwork_scripture/channeled/proc/chant_effects(chant_number) //The chant's periodic effects
/datum/clockwork_scripture/channeled/proc/chant_end_effects() //The chant's effect upon ending
@@ -231,7 +231,7 @@ Judgement: 10 servants, 100 CV, and any existing AIs are converted or destroyed
usage_tip = "Useful for crowd control in a populated area and disrupting mass movement."
tier = SCRIPTURE_DRIVER
-/datum/clockwork_scripture/channeled/belligerent/chant_effects()
+/datum/clockwork_scripture/channeled/belligerent/chant_effects(chant_number)
for(var/mob/living/L in hearers(7, invoker))
if(!is_servant_of_ratvar(L) && L.m_intent != "walk")
if(!iscultist(L))
@@ -314,22 +314,29 @@ Judgement: 10 servants, 100 CV, and any existing AIs are converted or destroyed
if(C.stat != DEAD && is_servant_of_ratvar(C))
nearby_cultists += C
if(!nearby_cultists.len)
- invoker << "There are no eligible cultists nearby!"
+ invoker << "There are no eligible servants nearby!"
return 0
var/mob/living/L = input(invoker, "Choose a fellow servant to heal.", name) as null|anything in nearby_cultists
if(!L || !invoker || !invoker.canUseTopic(slab))
return 0
- if(!L.getBruteLoss() && !L.getFireLoss())
+ var/brutedamage = L.getBruteLoss()
+ var/burndamage = L.getFireLoss()
+ var/totaldamage = brutedamage + burndamage
+ if(!totaldamage)
invoker << "[L] is not burned or bruised!"
return 0
- L.adjustToxLoss(L.getBruteLoss() / 2)
- L.adjustToxLoss(L.getFireLoss() / 2)
- L.adjustBruteLoss(-L.getBruteLoss())
- L.adjustFireLoss(-L.getFireLoss())
- invoker << "You bathe [L] in the light of Ratvar!"
- L.visible_message("A white light washes over [L], mending their bruises and burns!", \
- "You feel Ratvar's energy healing your wounds, but a deep nausea overcomes you!")
- playsound(get_turf(L), 'sound/magic/Staff_Healing.ogg', 50, 1)
+ L.adjustToxLoss(brutedamage / 2)
+ L.adjustToxLoss(burndamage / 2)
+ L.adjustBruteLoss(-brutedamage)
+ L.adjustFireLoss(-burndamage)
+ var/healseverity = max(round(totaldamage*0.05, 1), 1) //shows the general severity of the damage you just healed, 1 glow per 20
+ var/targetturf = get_turf(L)
+ for(var/i in 1 to healseverity)
+ PoolOrNew(/obj/effect/overlay/temp/heal, list(targetturf, "#1E8CE1"))
+ invoker << "You bathe [L] with Inath-Neq's power!"
+ L.visible_message("A blue light washes over [L], mending their bruises and burns!", \
+ "You feel Inath-Neq's power healing your wounds, but a deep nausea overcomes you!")
+ playsound(targetturf, 'sound/magic/Staff_Healing.ogg', 50, 1)
return 1
@@ -375,25 +382,26 @@ Judgement: 10 servants, 100 CV, and any existing AIs are converted or destroyed
var/grace_period = 3 //very short grace period so you don't have to stop immediately
var/datum/progressbar/progbar
-/datum/clockwork_scripture/channeled/taunting_tirade/chant_effects()
+/datum/clockwork_scripture/channeled/taunting_tirade/chant_effects(chant_number)
for(var/mob/living/L in hearers(7, invoker))
if(!is_servant_of_ratvar(L))
L.confused = min(L.confused + 20, 100)
L.dizziness = min(L.dizziness + 20, 100)
L.Stun(1)
- invoker.visible_message("[invoker] is suddenly covered with a thin layer of dark purple smoke!")
- invoker.color = "#AF0AAF"
- animate(invoker, color = initial(invoker.color), time = flee_time+grace_period)
- var/endtime = world.time + flee_time
- var/starttime = world.time
- progbar = new(invoker, flee_time, invoker)
- progbar.bar.color = "#AF0AAF"
- animate(progbar.bar, color = initial(progbar.bar.color), time = flee_time+grace_period)
- while(world.time < endtime)
- sleep(1)
- progbar.update(world.time - starttime)
- qdel(progbar)
- sleep(grace_period)
+ if(chant_number != chant_amount) //if this is the last chant, we don't have a movement period because the chant is over
+ invoker.visible_message("[invoker] is suddenly covered with a thin layer of dark purple smoke!")
+ invoker.color = "#AF0AAF"
+ animate(invoker, color = initial(invoker.color), time = flee_time+grace_period)
+ var/endtime = world.time + flee_time
+ var/starttime = world.time
+ progbar = new(invoker, flee_time, invoker)
+ progbar.bar.color = "#AF0AAF"
+ animate(progbar.bar, color = initial(progbar.bar.color), time = flee_time+grace_period)
+ while(world.time < endtime)
+ sleep(1)
+ progbar.update(world.time - starttime)
+ qdel(progbar)
+ sleep(grace_period)
/datum/clockwork_scripture/channeled/taunting_tirade/chant_end_effects()
qdel(progbar)
@@ -502,7 +510,7 @@ Judgement: 10 servants, 100 CV, and any existing AIs are converted or destroyed
var/power_damage_threshhold = 3000
var/augument_damage_threshhold = 6000
-/datum/clockwork_scripture/channeled/volt_void/chant_effects()
+/datum/clockwork_scripture/channeled/volt_void/chant_effects(chant_number)
playsound(invoker, 'sound/effects/EMPulse.ogg', 50, 1)
var/power_drained = 0
for(var/obj/machinery/power/apc/A in view(7, invoker))
@@ -654,6 +662,9 @@ Judgement: 10 servants, 100 CV, and any existing AIs are converted or destroyed
tier = SCRIPTURE_SCRIPT
/datum/clockwork_scripture/spatial_gateway/check_special_requirements()
+ if(!isturf(invoker.loc))
+ invoker << "You must not be inside an object to use this scripture!"
+ return 0
var/other_servants = 0
for(var/mob/living/L in living_mob_list)
if(is_servant_of_ratvar(L) && !L.stat != DEAD)
diff --git a/code/game/gamemodes/clock_cult/clock_structures.dm b/code/game/gamemodes/clock_cult/clock_structures.dm
index feae771b38a..ea02442701d 100644
--- a/code/game/gamemodes/clock_cult/clock_structures.dm
+++ b/code/game/gamemodes/clock_cult/clock_structures.dm
@@ -425,7 +425,7 @@
/obj/structure/clockwork/wall_gear/examine(mob/user)
..()
- user << "[src] is [anchored ? "":"un"]secured to the floor."
+ user << "[src] is [anchored ? "secured to the floor":"mobile, and not secured"]."
///////////////////////
// CLOCKWORK EFFECTS //
@@ -667,7 +667,7 @@
burn_state = FIRE_PROOF
burntime = 1
var/affects_servants = FALSE
- var/affects_stat = FALSE
+ var/stat_affected = CONSCIOUS
/obj/effect/clockwork/sigil/attack_hand(mob/user)
if(iscarbon(user) && !user.stat && (!is_servant_of_ratvar(user) || (is_servant_of_ratvar(user) && user.a_intent == "harm")))
@@ -680,7 +680,7 @@
..()
if(isliving(AM))
var/mob/living/L = AM
- if(!L.stat || affects_stat)
+ if(L.stat <= stat_affected)
if((!is_servant_of_ratvar(L) || (is_servant_of_ratvar(L) && affects_servants)) && L.mind)
sigil_effects(L)
return 1
@@ -718,6 +718,7 @@
icon_state = "sigilsubmission"
color = "#FAE48C"
alpha = 125
+ stat_affected = UNCONSCIOUS
var/convert_time = 50
var/glow_light = 2 //soft light
var/glow_falloff = 1
@@ -761,7 +762,7 @@
for(var/M in mob_list)
if(isobserver(M))
var/link = FOLLOW_LINK(M, L)
- M << "[link] [message] [L.real_name]!"
+ M << "[link] [message] [L.real_name]!"
else if(is_servant_of_ratvar(M))
if(M == L)
M << "[message] you!"
@@ -835,7 +836,7 @@
color = "#123456"
alpha = 75
affects_servants = TRUE
- affects_stat = TRUE
+ stat_affected = DEAD
var/vitality = 0
var/base_revive_cost = 25
var/sigil_active = FALSE
diff --git a/code/game/gamemodes/cult/cult_structures.dm b/code/game/gamemodes/cult/cult_structures.dm
index a5a299d068c..bf9033396cc 100644
--- a/code/game/gamemodes/cult/cult_structures.dm
+++ b/code/game/gamemodes/cult/cult_structures.dm
@@ -92,6 +92,13 @@
user << "You work the forge as dark knowledge guides your hands, creating [N]!"
+var/list/blacklisted_pylon_turfs = typecacheof(list(
+ /turf/closed,
+ /turf/open/floor/engine/cult,
+ /turf/open/space,
+ /turf/open/floor/plating/lava,
+ /turf/open/chasm))
+
/obj/structure/cult/pylon
name = "pylon"
desc = "A floating crystal that slowly heals those faithful to Nar'Sie."
@@ -116,30 +123,43 @@
if(last_heal <= world.time)
last_heal = world.time + heal_delay
for(var/mob/living/L in range(5, src))
- if(iscultist(L) || istype(L, /mob/living/simple_animal/shade) || istype(L, /mob/living/simple_animal/hostile/construct))
+ if(iscultist(L) || isshade(L) || isconstruct(L))
if(L.health != L.maxHealth)
PoolOrNew(/obj/effect/overlay/temp/heal, list(get_turf(src), "#960000"))
if(ishuman(L))
L.adjustBruteLoss(-1, 0)
L.adjustFireLoss(-1, 0)
L.updatehealth()
- if(istype(L, /mob/living/simple_animal/shade) || istype(L, /mob/living/simple_animal/hostile/construct))
+ if(isshade(L) || isconstruct(L))
var/mob/living/simple_animal/M = L
if(M.health < M.maxHealth)
M.adjustHealth(-1)
CHECK_TICK
if(last_corrupt <= world.time)
var/list/validturfs = list()
+ var/list/cultturfs = list()
for(var/T in circleviewturfs(src, 5))
- if(istype(T, /turf/closed) || istype(T, /turf/open/floor/engine/cult) || istype(T, /turf/open/space) || istype(T, /turf/open/floor/plating/lava))
+ if(istype(T, /turf/open/floor/engine/cult))
+ cultturfs |= T
continue
- validturfs |= T
+ if(is_type_in_typecache(T, blacklisted_pylon_turfs))
+ continue
+ else
+ validturfs |= T
+
+ last_corrupt = world.time + corrupt_delay
+
var/turf/T = safepick(validturfs)
if(T)
T.ChangeTurf(/turf/open/floor/engine/cult)
- last_corrupt = world.time + corrupt_delay
else
- last_corrupt = world.time + corrupt_delay*2
+ var/turf/open/floor/engine/cult/F = safepick(cultturfs)
+ if(F)
+ PoolOrNew(/obj/effect/overlay/temp/cult/turf/open/floor, F)
+ else
+ // Are we in space or something? No cult turfs or
+ // convertable turfs?
+ last_corrupt = world.time + corrupt_delay*2
/obj/structure/cult/tome
name = "archives"
diff --git a/code/game/gamemodes/miniantags/umbra/umbra.dm b/code/game/gamemodes/miniantags/umbra/umbra.dm
index 76398918ffb..4bbb87b156e 100644
--- a/code/game/gamemodes/miniantags/umbra/umbra.dm
+++ b/code/game/gamemodes/miniantags/umbra/umbra.dm
@@ -30,6 +30,8 @@ Although these umbral ashes make umbras resilient, they can be killed permanentl
/mob/living/simple_animal/umbra
name = "umbra"
real_name = "umbra"
+ unique_name = TRUE
+ gender = NEUTER
desc = "A translucent, cobalt-blue apparition floating several feet in the air."
invisibility = UMBRA_INVISIBILITY
icon = 'icons/mob/mob.dmi'
@@ -39,24 +41,29 @@ Although these umbral ashes make umbras resilient, they can be killed permanentl
alpha = 175 //To show invisibility
health = 100
maxHealth = 100
- healable = 0
- damage_coeff = list(BRUTE = 1, BURN = 1, TOX = 0, CLONE = 0, STAMINA = 0, OXY = 0)
healable = FALSE
+ damage_coeff = list(BRUTE = 1, BURN = 1, TOX = 0, CLONE = 0, STAMINA = 0, OXY = 0)
+ minbodytemp = 0
+ maxbodytemp = INFINITY
+ 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)
+ unsuitable_atmos_damage = 0
friendly = "passes through"
speak_emote = list("murmurs")
emote_hear = list("murmurs")
languages_spoken = ALL
languages_understood = ALL
+ status_flags = 0
+ pass_flags = PASSTABLE | PASSGRILLE | PASSMOB
incorporeal_move = 3
flying = TRUE
- stop_automated_movement = TRUE
wander = FALSE
+ stop_automated_movement = TRUE
+ mob_size = MOB_SIZE_TINY
+ anchored = TRUE
+ density = FALSE
sight = SEE_SELF
see_invisible = SEE_INVISIBLE_NOLIGHTING
see_in_dark = 8
- minbodytemp = 0
- maxbodytemp = INFINITY
- 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)
var/vitae = 10 //The amount of vitae captured by the umbra
var/vitae_cap = 100 //How much vitae a single umbra can hold
var/breaking_apart = FALSE //If the umbra is currently dying
@@ -66,6 +73,7 @@ Although these umbral ashes make umbras resilient, they can be killed permanentl
var/mob/living/carbon/human/possessed //The human that an umbra is inside of, if applicable
var/time_possessing = 0 //How long an umbra has been in possession of a single target.
var/list/lobotomized = list() //Mobs that have had their memories stolen by the umbra
+ var/image/ghost_image //So ghosts can see the umbra in the dark
var/playstyle_string = "You are an umbra, and you aren't quite sure how you're alive. You don't remember much, but you remember slipping away, \
lsoing your hold on life. You died, but here you are... somehow. You can't be quite sure how this happened, but you're pretty sure that it won't last long. Already you feel this strange \
form of life weakening. You need to find a way to sustain yourself, and you think you might have an idea.\n\
@@ -83,6 +91,9 @@ Although these umbral ashes make umbras resilient, they can be killed permanentl
//Creation, destruction, life, and death
/mob/living/simple_animal/umbra/New()
..()
+ ghost_image = image(icon, src, icon_state)
+ ghost_darkness_images |= ghost_image
+ updateallghostimages()
if(prob(1))
name = "grief ghost"
real_name = "grief ghost"
@@ -204,7 +215,8 @@ Although these umbral ashes make umbras resilient, they can be killed permanentl
spawn(time)
if(!silent)
src << "You can move again!"
- notransform = FALSE
+ if(!possessed) //To ensure that umbras don't escape their quarry
+ notransform = FALSE
//Actions and interaction
diff --git a/code/game/gamemodes/miniantags/umbra/umbra_abilities.dm b/code/game/gamemodes/miniantags/umbra/umbra_abilities.dm
index 6383074ea70..409a3ed5763 100644
--- a/code/game/gamemodes/miniantags/umbra/umbra_abilities.dm
+++ b/code/game/gamemodes/miniantags/umbra/umbra_abilities.dm
@@ -98,6 +98,10 @@
user << "[target] is mindless and incapable of higher thought!"
revert_cast()
return
+ if(user.possessed)
+ user << "Unpossess [user.possessed] first!"
+ revert_cast()
+ return
user.visible_message("[user] appears from nowhere, stretching out towards [target]!", "You try to copy [target]'s memories...")
target.visible_message("A blue beam arcs into [target]'s head, immobilizing them!", "Your mind freezes. You can't move. \
You can't think.")
@@ -112,6 +116,6 @@
target.visible_message("[target] silently collapses, motionless.", "Your mind blanks. Your thoughts have fled. Slowly, they begin to \
return... but you feel wrong.")
target.mind.show_memory(user, 0)
- user.mind.memory += "[target.real_name]'s Memories:\n[target.mind.memory]\n\n"
+ user.mind.memory += "[target.real_name]'s Memories:
[target.mind.memory]
"
target.Weaken(5)
user.lobotomized |= target
diff --git a/code/game/gamemodes/miniantags/umbra/umbra_objectives.dm b/code/game/gamemodes/miniantags/umbra/umbra_objectives.dm
index db1bd30be1a..3b0e2e01561 100644
--- a/code/game/gamemodes/miniantags/umbra/umbra_objectives.dm
+++ b/code/game/gamemodes/miniantags/umbra/umbra_objectives.dm
@@ -1,7 +1,7 @@
/*
Possible objectives:
- 1. Steal the memories of # humans. (# = round population / 4)
+ 1. Steal the memories of # humans. (# = 10-20)
*/
@@ -15,7 +15,7 @@ Possible objectives:
explanation_text = "Steal the memories of several humans."
/datum/objective/umbra/lobotomize/New()
- target_amount = round(ticker.mode.num_players() / 4)
+ target_amount = rand(10, 20)
explanation_text = "Steal the memories of [target_amount] humans."
..()
diff --git a/code/game/gamemodes/miniantags/umbra/umbra_spawn_event.dm b/code/game/gamemodes/miniantags/umbra/umbra_spawn_event.dm
index 1c8526edf5b..f73a1300e1f 100644
--- a/code/game/gamemodes/miniantags/umbra/umbra_spawn_event.dm
+++ b/code/game/gamemodes/miniantags/umbra/umbra_spawn_event.dm
@@ -12,6 +12,7 @@
/datum/round_event/ghost_role/umbra/spawn_role()
message_admins("An unoccupied umbra was created by a random event.")
var/mob/living/simple_animal/umbra/U = new(pick(xeno_spawn))
- var/image/alert_overlay = image('icons/mob/mob.dmi', "umbra")
- notify_ghosts("An umbra has formed in [get_area(U)]. Interact with it to take control of it.", null, source = U, alert_overlay = alert_overlay)
+ var/image/I = image('icons/mob/mob.dmi', "umbra")
+ notify_ghosts("An umbra has formed in [get_area(U)]. Interact with it to take control of it.", 'sound/effects/ghost2.ogg', alert_overlay = I, source = U, action = NOTIFY_ATTACK)
+ spawned_mobs += U
return SUCCESSFUL_SPAWN
diff --git a/code/game/gamemodes/miniantags/umbra/umbral_ashes.dm b/code/game/gamemodes/miniantags/umbra/umbral_ashes.dm
index c4c168bf7c8..ea005b1d2c7 100644
--- a/code/game/gamemodes/miniantags/umbra/umbral_ashes.dm
+++ b/code/game/gamemodes/miniantags/umbra/umbral_ashes.dm
@@ -32,8 +32,8 @@
U.key = umbra_key
if(!U.client)
U.key = null
- var/image/alert_overlay = image('icons/mob/mob.dmi', "umbra")
- notify_ghosts("An umbra has re-formed in [get_area(U)]. Interact with it to take control of it.", null, source = U, alert_overlay = alert_overlay)
+ var/image/I = image('icons/mob/mob.dmi', "umbra")
+ notify_ghosts("An umbra has reformed in [get_area(U)]. Interact with it to take control of it.", 'sound/effects/ghost2.ogg', alert_overlay = I, source = U, action = NOTIFY_ATTACK)
else
U << "Back... you're back. You can't remember what you were supposed to be doing here. Now... where were we?"
if(umbra_vitae)
diff --git a/code/game/machinery/cloning.dm b/code/game/machinery/cloning.dm
index 2139b5170fe..17f06f2975f 100644
--- a/code/game/machinery/cloning.dm
+++ b/code/game/machinery/cloning.dm
@@ -48,6 +48,7 @@
radio.recalculateChannels()
/obj/machinery/clonepod/Destroy()
+ go_out()
qdel(radio)
radio = null
qdel(countdown)
diff --git a/code/game/machinery/firealarm.dm b/code/game/machinery/firealarm.dm
index 86324d78d52..3d319be807b 100644
--- a/code/game/machinery/firealarm.dm
+++ b/code/game/machinery/firealarm.dm
@@ -23,6 +23,7 @@
var/buildstage = 2 // 2 = complete, 1 = no wires, 0 = circuit gone
var/health = 50
+
/obj/machinery/firealarm/New(loc, dir, building)
..()
if(dir)
@@ -223,3 +224,67 @@
update_icon()
else if(prob(33))
alarm()
+
+/*
+ * Party button
+ */
+
+/obj/machinery/firealarm/partyalarm
+ name = "\improper PARTY BUTTON"
+ desc = "Cuban Pete is in the house!"
+
+/obj/machinery/firealarm/partyalarm/attack_hand(mob/user)
+ if((user.stat && !IsAdminGhost(user)) || stat & (NOPOWER|BROKEN))
+ return
+
+ if (buildstage != 2)
+ return
+
+ user.set_machine(src)
+ var/area/A = src.loc
+ var/d1
+ var/dat
+ if (istype(user, /mob/living/carbon/human) || user.has_unlimited_silicon_privilege)
+ A = A.loc
+
+ if (A.party)
+ d1 = text("No Party :(", src)
+ else
+ d1 = text("PARTY!!!", src)
+ dat = text("Party Button []", d1)
+
+ else
+ A = A.loc
+ if (A.fire)
+ d1 = text("[]", src, stars("No Party :("))
+ else
+ d1 = text("[]", src, stars("PARTY!!!"))
+ dat = text("[] []", stars("Party Button"), d1)
+
+ var/datum/browser/popup = new(user, "firealarm", "Party Alarm")
+ popup.set_content(dat)
+ popup.set_title_image(user.browse_rsc_icon(src.icon, src.icon_state))
+ popup.open()
+ return
+
+/obj/machinery/firealarm/partyalarm/reset()
+ if (stat & (NOPOWER|BROKEN))
+ return
+ var/area/A = src.loc
+ A = A.loc
+ if (!( istype(A, /area) ))
+ return
+ for(var/area/RA in A.related)
+ RA.partyreset()
+ return
+
+/obj/machinery/firealarm/partyalarm/alarm()
+ if (stat & (NOPOWER|BROKEN))
+ return
+ var/area/A = src.loc
+ A = A.loc
+ if (!( istype(A, /area) ))
+ return
+ for(var/area/RA in A.related)
+ RA.partyalert()
+ return
\ No newline at end of file
diff --git a/code/game/objects/effects/glowshroom.dm b/code/game/objects/effects/glowshroom.dm
index 9581cc75125..8f94e4f1789 100644
--- a/code/game/objects/effects/glowshroom.dm
+++ b/code/game/objects/effects/glowshroom.dm
@@ -1,7 +1,12 @@
//separate dm since hydro is getting bloated already
+var/list/blacklisted_glowshroom_turfs = typecacheof(list(
+ /turf/open/floor/plating/lava,
+ /turf/open/floor/plating/beach/water))
+
/obj/effect/glowshroom
name = "glowshroom"
+ desc = "Mycena Bregprox, a species of mushroom that glows in the dark."
anchored = 1
opacity = 0
density = 0
@@ -23,6 +28,10 @@ obj/effect/glowshroom/glowcap
/obj/effect/glowshroom/single
yield = 0
+/obj/effect/glowshroom/examine(mob/user)
+ . = ..()
+ user << "This is a [generation]\th generation [name]!"
+
/obj/effect/glowshroom/New()
..()
SetLuminosity(round(potency/10))
@@ -42,23 +51,23 @@ obj/effect/glowshroom/glowcap
else //if on the floor, glowshroom on-floor sprite
icon_state = "[base_icon_state]f"
- spawn(delay)
- Spread()
+ addtimer(src, "Spread", delay)
/obj/effect/glowshroom/proc/Spread()
- set background = BACKGROUND_ENABLED
-
- for(var/i=1,i<=yield,i++)
+ for(var/i = 1 to yield)
if(prob(1/(generation * generation) * 100))//This formula gives you diminishing returns based on generation. 100% with 1st gen, decreasing to 25%, 11%, 6, 4, 2...
var/list/possibleLocs = list()
- var/spreadsIntoAdjacent = 0
+ var/spreadsIntoAdjacent = FALSE
if(prob(spreadIntoAdjacentChance))
- spreadsIntoAdjacent = 1
+ spreadsIntoAdjacent = TRUE
for(var/turf/open/floor/earth in view(3,src))
+ if(is_type_in_typecache(earth, blacklisted_glowshroom_turfs))
+ continue
if(spreadsIntoAdjacent || !locate(/obj/effect/glowshroom) in view(1,earth))
possibleLocs += earth
+ CHECK_TICK
if(!possibleLocs.len)
break
@@ -77,15 +86,15 @@ obj/effect/glowshroom/glowcap
continue
var/obj/effect/glowshroom/child = new type(newLoc)//The baby mushrooms have different stats :3
- child.potency = max(potency+rand(-3,6), 0)
- child.yield = max(yield+rand(-1,2), 0)
- child.delay = max(delay+rand(-30,60), 0)
- child.endurance = max(endurance+rand(-3,6), 1)
- child.generation = generation+1
- child.desc = "This is a [child.generation]\th generation [child.name]!"//I added this for testing, but I figure I'll leave it in.
+ child.potency = max(potency + rand(-3,6), 0)
+ child.yield = max(yield + rand(-1,2), 0)
+ child.delay = max(delay + rand(-30,60), 0)
+ child.endurance = max(endurance + rand(-3,6), 1)
+ child.generation = generation + 1
+
+ CHECK_TICK
/obj/effect/glowshroom/proc/CalcDir(turf/location = loc)
- set background = BACKGROUND_ENABLED
var/direction = 16
for(var/wallDir in cardinal)
@@ -127,17 +136,12 @@ obj/effect/glowshroom/glowcap
switch(severity)
if(1)
qdel(src)
- return
if(2)
- if (prob(50))
+ if(prob(50))
qdel(src)
- return
if(3)
- if (prob(5))
+ if(prob(5))
qdel(src)
- return
- else
- return
/obj/effect/glowshroom/temperature_expose(datum/gas_mixture/air, exposed_temperature, exposed_volume)
if(exposed_temperature > 300)
@@ -152,4 +156,4 @@ obj/effect/glowshroom/glowcap
visible_message("[src] melts away!")
var/obj/effect/decal/cleanable/molten_item/I = new (get_turf(src))
I.desc = "Looks like this was \an [src] some time ago."
- qdel(src)
\ No newline at end of file
+ qdel(src)
diff --git a/code/game/objects/items/devices/PDA/radio.dm b/code/game/objects/items/devices/PDA/radio.dm
index c127be39aa9..e0fb40066b4 100644
--- a/code/game/objects/items/devices/PDA/radio.dm
+++ b/code/game/objects/items/devices/PDA/radio.dm
@@ -13,6 +13,10 @@
if (istype(loc.loc, /obj/item/device/pda))
hostpda = loc.loc
+/obj/item/radio/integrated/Destroy()
+ hostpda = null
+ return ..()
+
/*
* Radio Cartridge, essentially a signaler.
*/
@@ -32,6 +36,7 @@
/obj/item/radio/integrated/signal/Destroy()
if(SSradio)
SSradio.remove_object(src, frequency)
+ radio_connection = null
return ..()
/obj/item/radio/integrated/signal/initialize()
diff --git a/code/game/objects/items/stacks/sheets/sheet_types.dm b/code/game/objects/items/stacks/sheets/sheet_types.dm
index 95efb496eca..8f3da041c7a 100644
--- a/code/game/objects/items/stacks/sheets/sheet_types.dm
+++ b/code/game/objects/items/stacks/sheets/sheet_types.dm
@@ -68,6 +68,9 @@ var/global/list/datum/stack_recipe/metal_recipes = list ( \
/obj/item/stack/sheet/metal/fifty
amount = 50
+/obj/item/stack/sheet/metal/five
+ amount = 5
+
/obj/item/stack/sheet/metal/cyborg
materials = list()
is_cyborg = 1
diff --git a/code/game/objects/structures/fluff.dm b/code/game/objects/structures/fluff.dm
new file mode 100644
index 00000000000..ea8272849de
--- /dev/null
+++ b/code/game/objects/structures/fluff.dm
@@ -0,0 +1,45 @@
+//Fluff structures serve no purpose and exist only for enriching the environment. They can be destroyed with a wrench.
+
+/obj/structure/fluff
+ name = "fluff structure"
+ desc = "Fluffier than a sheep. This shouldn't exist."
+ icon = 'icons/obj/stationobjs.dmi'
+ icon_state = "minibar"
+ anchored = TRUE
+ density = FALSE
+ opacity = 0
+
+/obj/structure/fluff/attackby(obj/item/I, mob/living/user, params)
+ if(istype(I, /obj/item/weapon/wrench))
+ user.visible_message("[user] starts disassembling [src]...", "You start disassembling [src]...")
+ playsound(user, 'sound/items/Ratchet.ogg', 50, 1)
+ if(!do_after(user, 50, target = src))
+ return 0
+ user.visible_message("[user] disassembles [src]!", "You break down [src] into scrap metal.")
+ playsound(user, 'sound/items/Deconstruct.ogg', 50, 1)
+ new/obj/item/stack/sheet/metal(get_turf(src))
+ qdel(src)
+ return
+ ..()
+
+/obj/structure/fluff/empty_terrarium //Empty terrariums are created when a preserved terrarium in a lavaland seed vault is activated.
+ name = "empty terrarium"
+ desc = "An ancient machine that seems to be used for storing plant matter. Its hatch is ajar."
+ icon = 'icons/obj/lavaland/spawners.dmi'
+ icon_state = "terrarium_open"
+ density = TRUE
+
+/obj/structure/fluff/empty_sleeper //Empty sleepers are created by a good few ghost roles in lavaland.
+ name = "empty sleeper"
+ desc = "An open sleeper. It looks as though it would be awaiting another patient, were it not broken."
+ icon = 'icons/obj/Cryogenic2.dmi'
+ icon_state = "sleeper-open"
+
+/obj/structure/fluff/empty_sleeper/syndicate
+ icon_state = "sleeper_s-open"
+
+/obj/structure/fluff/empty_cryostasis_sleeper //Empty cryostasis sleepers are created when a malfunctioning cryostasis sleeper in a lavaland shelter is activated
+ name = "empty cryostasis sleeper"
+ desc = "Although comfortable, this sleeper won't function as anything but a bed ever again."
+ icon = 'icons/obj/lavaland/spawners.dmi'
+ icon_state = "cryostasis_sleeper_open"
diff --git a/code/game/objects/structures/ghost_role_spawners.dm b/code/game/objects/structures/ghost_role_spawners.dm
new file mode 100644
index 00000000000..9ad05994528
--- /dev/null
+++ b/code/game/objects/structures/ghost_role_spawners.dm
@@ -0,0 +1,239 @@
+//Objects that spawn ghosts in as a certain role when they click on it, i.e. away mission bartenders.
+
+//Preserved terrarium/seed vault: Spawns in seed vault structures in lavaland. Ghosts become plantpeople and are advised to begin growing plants in the room near them.
+/obj/effect/mob_spawn/human/seed_vault
+ name = "preserved terrarium"
+ desc = "An ancient machine that seems to be used for storing plant matter. The glass is obstructed by a mat of vines."
+ mob_name = "a lifebringer"
+ icon = 'icons/obj/lavaland/spawners.dmi'
+ icon_state = "terrarium"
+ density = TRUE
+ roundstart = FALSE
+ death = FALSE
+ mob_species = /datum/species/pod
+ flavour_text = "You are a sentient ecosystem - an example of the mastery over life that your creators possessed. Your masters, benevolent as they were, created uncounted \
+ seed vaults and spread them across the universe to every planet they could chart. You are in one such seed vault. Your goal is to cultivate and spread life wherever it will go while waiting \
+ for contact from your creators. Estimated time of last contact: Deployment, 5x10^3 millennia ago."
+
+/obj/effect/mob_spawn/human/seed_vault/special(mob/living/new_spawn)
+ var/plant_name = pick("Tomato", "Potato", "Brocolli", "Carrot", "Ambrosia", "Pumpkin", "Ivy", "Kudzu", "Bannana", "Moss", "Flower", "Bloom", "Root", "Bark", "Glowshroom", "Petal", "Leaf", \
+ "Venus", "Sprout","Cocao", "Strawberry", "Citrus", "Oak", "Cactus", "Pepper", "Juniper")
+ new_spawn.real_name = plant_name
+ if(ishuman(new_spawn))
+ var/mob/living/carbon/human/H = new_spawn
+ H.underwear = "Nude" //You're a plant, partner
+ H.update_body()
+
+/obj/effect/mob_spawn/human/seed_vault/Destroy()
+ new/obj/structure/fluff/empty_terrarium(get_turf(src))
+ ..()
+
+//Ash walker eggs: Spawns in ash walker dens in lavaland. Ghosts become unbreathing lizards that worship the Necropolis and are advised to retrieve corpses to create more ash walkers.
+/obj/effect/mob_spawn/human/ash_walker
+ name = "ash walker egg"
+ desc = "A man-sized yellow egg, spawned from some unfathomable creature. A humanoid silhouette lurks within."
+ mob_name = "an ash walker"
+ icon = 'icons/mob/lavaland/lavaland_monsters.dmi'
+ icon_state = "large_egg"
+ mob_species = /datum/species/lizard/ashwalker
+ helmet = /obj/item/clothing/head/helmet/gladiator
+ uniform = /obj/item/clothing/under/gladiator
+ roundstart = FALSE
+ death = FALSE
+ anchored = 0
+ density = 0
+ flavour_text = "You are an ash walker. Your tribe worships the Necropolis. The wastes are sacred ground, its monsters a blessed bounty. \
+ You have seen lights in the distance... they foreshadow the arrival of outsiders that seek to tear apart the Necropolis and its domain. Fresh sacrifices for your nest."
+
+/obj/effect/mob_spawn/human/ash_walker/special(mob/living/new_spawn)
+ new_spawn.real_name = random_unique_lizard_name(gender)
+ new_spawn << "Drag the corpses of men and beasts to your nest. It will absorb them to create more of your kind. Glory to the Necropolis!"
+ if(ishuman(new_spawn))
+ var/mob/living/carbon/human/H = new_spawn
+ H.underwear = "Nude"
+ H.update_body()
+
+/obj/effect/mob_spawn/human/ash_walker/New()
+ ..()
+ var/area/A = get_area(src)
+ if(A)
+ notify_ghosts("An ash walker egg is ready to hatch in \the [A.name].", source = src, action=NOTIFY_ATTACK)
+
+//Timeless prisons: Spawns in Wish Granter prisons in lavaland. Ghosts become age-old users of the Wish Granter and are advised to seek repentance for their past.
+/obj/effect/mob_spawn/human/exile
+ name = "timeless prison"
+ desc = "Although this stasis pod looks medicinal, it seems as though it's meant to preserve something for a very long time."
+ mob_name = "a penitent exile"
+ icon = 'icons/obj/Cryogenic2.dmi'
+ icon_state = "sleeper"
+ roundstart = FALSE
+ death = FALSE
+ mob_species = /datum/species/shadow
+ flavour_text = "You are cursed. Years ago, you sacrificed the lives of your trusted friends and the humanity of yourself to reach the Wish Granter. Though you \
+ did so, it has come at a cost: your very body rejects the light, dooming you to wander endlessly in this horrible wasteland."
+
+/obj/effect/mob_spawn/human/exile/Destroy()
+ new/obj/structure/fluff/empty_sleeper(get_turf(src))
+ ..()
+
+/obj/effect/mob_spawn/human/exile/special(mob/living/new_spawn)
+ new_spawn.real_name = "Wish Granter's Victim ([rand(0,999)])"
+ var/wish = rand(1,4)
+ switch(wish)
+ if(1)
+ new_spawn << "You wished to kill, and kill you did. You've lost track of how many, but the spark of excitement that murder once held has winked out. You feel only regret."
+ if(2)
+ new_spawn << "You wished for unending wealth, but no amount of money was worth this existence. Maybe charity might redeem your soul?"
+ if(3)
+ new_spawn << "You wished for power. Little good it did you, cast out of the light. You are the [gender == MALE ? "king" : "queen"] of a hell that holds no subjects. You feel only remorse."
+ if(4)
+ new_spawn << "You wished for immortality, even as your friends lay dying behind you. No matter how many times you cast yourself into the lava, you awaken in this room again within a few days. There is no escape."
+
+//Golem shells: Spawns in Free Golem ships in lavaland. Ghosts become mineral golems and are advised to spread personal freedom.
+/obj/effect/mob_spawn/human/golem
+ name = "inert golem shell"
+ desc = "A humanoid shape, empty, lifeless, and full of potential."
+ mob_name = "a free golem"
+ icon = 'icons/obj/wizard.dmi'
+ icon_state = "construct"
+ mob_species = /datum/species/golem
+ roundstart = FALSE
+ death = FALSE
+ anchored = 0
+ density = 0
+ flavour_text = "You are a Free Golem. Your family worships The Liberator. In his infinite and divine wisdom, he set your clan free to \
+ travel the stars with a single declaration: \"Yeah go do whatever.\" Though you are bound to the one who created you, it is customary in your society to repeat those same words to newborn \
+ golems, so that no golem may ever be forced to serve again."
+
+/obj/effect/mob_spawn/human/golem/New()
+ ..()
+ var/area/A = get_area(src)
+ if(A)
+ notify_ghosts("A golem shell has been completed in \the [A.name].", source = src, action=NOTIFY_ATTACK)
+
+/obj/effect/mob_spawn/human/golem/special(mob/living/new_spawn)
+ var/golem_surname = pick(golem_names)
+ // 3% chance that our golem has a human surname, because
+ // cultural contamination
+ if(prob(3))
+ golem_surname = pick(last_names)
+
+ var/datum/species/X = mob_species
+ var/golem_forename = initial(X.id)
+
+ // The id of golem species is either their material "diamond","gold",
+ // or just "golem" for the plain ones. So we're using it for naming.
+
+ if(golem_forename == "golem")
+ golem_forename = "iron"
+
+ new_spawn.real_name = "[capitalize(golem_forename)] [golem_surname]"
+ // This means golems have names like Iron Forge, or Diamond Quarry
+ // also a tiny chance of being called "Plasma Meme"
+ // which is clearly a feature
+
+ new_spawn << "Build golem shells in the autolathe, and feed refined mineral sheets to the shells to bring them to life! You are generally a peaceful group unless provoked."
+ if(ishuman(new_spawn))
+ var/mob/living/carbon/human/H = new_spawn
+ H.set_cloned_appearance()
+
+
+/obj/effect/mob_spawn/human/golem/adamantine
+ name = "dust-caked golem shell"
+ desc = "A humanoid shape, empty, lifeless, and full of potential."
+ mob_name = "a free golem"
+ anchored = 1
+ density = 1
+ mob_species = /datum/species/golem/adamantine
+
+//Malfunctioning cryostasis sleepers: Spawns in makeshift shelters in lavaland. Ghosts become hermits with knowledge of how they got to where they are now.
+/obj/effect/mob_spawn/human/hermit
+ name = "malfunctiong cryostasis sleeper"
+ desc = "A humming sleeper with a silhoutted occupant inside. Its stasis function is broken and it's likely being used as a bed."
+ mob_name = "a stranded hermit"
+ icon = 'icons/obj/lavaland/spawners.dmi'
+ icon_state = "cryostasis_sleeper"
+ roundstart = FALSE
+ death = FALSE
+ random = TRUE
+ mob_species = /datum/species/human
+ flavour_text = "You've been stranded in this godless prison of a planet for longer than you can remember. Each day you barely scrape by, and between the terrible \
+ conditions of your makeshift shelter, the hostile creatures, and the ash drakes swooping down from the cloudless skies, all you can wish for is the feel of soft grass between your toes and \
+ the fresh air of Earth. These thoughts are dispelled by yet another recollection of how you got here... "
+
+/obj/effect/mob_spawn/human/hermit/New()
+ var/arrpee = rand(1,4)
+ switch(arrpee)
+ if(1)
+ flavour_text += "you were a [pick("arms dealer", "shipwright", "docking manager")]'s assistant on a small trading station several sectors from here. Raiders attacked, and there was \
+ only one pod left when you got to the escape bay. You took it and launched it alone, and the crowd of terrified faces crowding at the airlock door as your pod's engines burst to \
+ life and sent you to this hell are forever branded into your memory."
+ uniform = /obj/item/clothing/under/assistantformal
+ shoes = /obj/item/clothing/shoes/sneakers/black
+ back = /obj/item/weapon/storage/backpack
+ if(2)
+ flavour_text += "you're an exile from the Tiger Cooperative. Their technological fanaticism drove you to question the power and beliefs of the Exolitics, and they saw you as a \
+ heretic and subjected you to hours of horrible torture. You were hours away from execution when a high-ranking friend of yours in the Cooperative managed to secure you a pod, \
+ scrambled its destination's coordinates, and launched it. You awoke from stasis when you landed and have been surviving - barely - ever since."
+ uniform = /obj/item/clothing/under/rank/prisoner
+ shoes = /obj/item/clothing/shoes/sneakers/orange
+ back = /obj/item/weapon/storage/backpack
+ if(3)
+ flavour_text += "you were a doctor on one of Nanotrasen's space stations, but you left behind that damn corporation's tyranny and everything it stood for. From a metaphorical hell \
+ to a literal one, you find yourself nonetheless missing the recycled air and warm floors of what you left behind... but you'd still rather be here than there."
+ uniform = /obj/item/clothing/under/rank/medical
+ suit = /obj/item/clothing/suit/toggle/labcoat
+ back = /obj/item/weapon/storage/backpack/medic
+ shoes = /obj/item/clothing/shoes/sneakers/black
+ if(4)
+ flavour_text += "you were always joked about by your friends for \"not playing with a full deck\", as they so kindly put it. It seems that they were right when you, on a tour \
+ at one of Nanotrasen's state-of-the-art research facilities, were in one of the escape pods alone and saw the red button. It was big and shiny, and it caught your eye. You pressed \
+ it, and after a terrifying and fast ride for days, you landed here. You've had time to wisen up since then, and you think that your old friends wouldn't be laughing now."
+ uniform = /obj/item/clothing/under/color/grey/glorf
+ shoes = /obj/item/clothing/shoes/sneakers/black
+ back = /obj/item/weapon/storage/backpack
+ ..()
+
+/obj/effect/mob_spawn/human/hermit/Destroy()
+ new/obj/structure/fluff/empty_cryostasis_sleeper(get_turf(src))
+ ..()
+
+//Broken rejuvenation pod: Spawns in animal hospitals in lavaland. Ghosts become disoriented interns and are advised to search for help.
+/obj/effect/mob_spawn/human/doctor/alive/lavaland
+ name = "broken rejuvenation pod"
+ desc = "A small sleeper typically used to instantly restore minor wounds. This one seems broken, and its occupant is comatose."
+ mob_name = "a translocated vet"
+ flavour_text = "What...? Where are you? Where are the others? This is still the animal hospital - you should know, you've been an intern here for weeks - but \
+ everyone's gone. One of the cats scratched you just a few minutes ago. That's why you were in the pod - to heal the scratch. The scabs are still fresh; you see them right now. So where is \
+ everyone? Where did they go? What happened to the hospital? And is that smoke you smell? You need to find someone else. Maybe they can tell you what happened."
+
+//Prisoner containment sleeper: Spawns in crashed prison ships in lavaland. Ghosts become escaped prisoners and are advised to find a way out of the mess they've gotten themselves into.
+/obj/effect/mob_spawn/human/prisoner_transport
+ name = "prisoner containment sleeper"
+ desc = "A sleeper designed to put its occupant into a deep coma, unbreakable until the sleeper turns off. This one's glass is cracked and you can see a pale, sleeping face staring out."
+ mob_name = "an escaped prisoner"
+ icon = 'icons/obj/Cryogenic2.dmi'
+ icon_state = "sleeper_s"
+ uniform = /obj/item/clothing/under/rank/prisoner
+ mask = /obj/item/clothing/mask/breath
+ shoes = /obj/item/clothing/shoes/sneakers/orange
+ pocket1 = /obj/item/weapon/tank/internals/emergency_oxygen
+ roundstart = FALSE
+ death = FALSE
+ flavour_text = "Good. It seems as though your ship crashed. You're a prisoner, sentenced to hard work in one of Nanotrasen's labor camps, but it seems as \
+ though fate has other plans for you. You remember that you were convicted of "
+
+/obj/effect/mob_spawn/human/prisoner_transport/special(mob/living/L)
+ L.real_name = "NTP #LL-0[rand(111,999)]" //Nanotrasen Prisoner #Lavaland-(numbers)
+ L.name = L.real_name
+
+/obj/effect/mob_spawn/human/prisoner_transport/New()
+ var/list/crimes = list("murder", "larceny", "embezzlement", "unionization", "dereliction of duty", "kidnapping", "gross incompetence", "grand theft", "collaboration with the Syndicate", \
+ "worship of a forbidden deity", "interspecies relations", "mutiny")
+ flavour_text += "[pick(crimes)]. but regardless of that, it seems like your crime doesn't matter now. You don't know where you are, but you know that it's out to kill you, and you're not going \
+ to lose this opportunity. Find a way to get out of this mess and back to where you rightfully belong - your [pick("house", "apartment", "spaceship", "station")]."
+ ..()
+
+/obj/effect/mob_spawn/human/prisoner_transport/Destroy()
+ new/obj/structure/fluff/empty_sleeper/syndicate(get_turf(src))
+ ..()
diff --git a/code/game/objects/structures/kitchen_spike.dm b/code/game/objects/structures/kitchen_spike.dm
index 3ca954b698e..1155d214c0a 100644
--- a/code/game/objects/structures/kitchen_spike.dm
+++ b/code/game/objects/structures/kitchen_spike.dm
@@ -54,7 +54,7 @@
return ..()
/obj/structure/kitchenspike/attack_hand(mob/user)
- if(user.pulling && isliving(user.pulling) && user.a_intent == "grab" && !buckled_mobs.len)
+ if(isliving(user.pulling) && user.a_intent == "grab" && !has_buckled_mobs())
var/mob/living/L = user.pulling
if(do_mob(user, src, 120))
if(has_buckled_mobs()) //to prevent spam/queing up attacks
diff --git a/code/game/turfs/simulated/floor/plating.dm b/code/game/turfs/simulated/floor/plating.dm
index a319f39dc0c..9ead5e006e6 100644
--- a/code/game/turfs/simulated/floor/plating.dm
+++ b/code/game/turfs/simulated/floor/plating.dm
@@ -175,6 +175,9 @@
else if(prob(30))
ReplaceWithLattice()
+/turf/open/floor/engine/cult/airless
+ initial_gas_mix = "TEMP=2.7"
+
/turf/open/floor/engine/vacuum
name = "vacuum floor"
icon_state = "engine"
@@ -305,4 +308,4 @@
/turf/open/floor/plating/warnplate/corner
icon_state = "warnplatecorner"
/turf/open/floor/plating/airless/warnplate/corner
- icon_state = "warnplatecorner"
\ No newline at end of file
+ icon_state = "warnplatecorner"
diff --git a/code/modules/awaymissions/corpse.dm b/code/modules/awaymissions/corpse.dm
index 7647b13cc4f..238f1ac8e33 100644
--- a/code/modules/awaymissions/corpse.dm
+++ b/code/modules/awaymissions/corpse.dm
@@ -497,24 +497,6 @@
uniform = /obj/item/clothing/under/color/grey
shoes = /obj/item/clothing/shoes/combat
-///Prisoner
-
-/obj/effect/mob_spawn/human/prisoner_transport
- name = "prisoner sleeper"
- icon = 'icons/obj/Cryogenic2.dmi'
- icon_state = "sleeper"
- uniform = /obj/item/clothing/under/rank/prisoner
- mask = /obj/item/clothing/mask/breath
- shoes = /obj/item/clothing/shoes/sneakers/orange
- pocket1 = /obj/item/weapon/tank/internals/emergency_oxygen
- roundstart = FALSE
- death = FALSE
- flavour_text = {"You were a prisoner, sentenced to hard labour in one of Nanotrasen's harsh gulags, but judging by the explosive crash you just survived, fate may have other plans for. First thing is first though: Find a way to survive this mess."}
-
-/obj/effect/mob_spawn/human/prisoner_transport/special(mob/living/new_spawn)
- 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 your manager", "grand theft", "conspiracy", "attempting to unionize", "vandalism", "gross incompetence")
- new_spawn << "You were convincted of: [crime]."
-
//For ghost bar.
/obj/effect/mob_spawn/human/alive/space_bar_patron
name = "Bar cryogenics"
diff --git a/code/modules/cargo/packs.dm b/code/modules/cargo/packs.dm
index a13aeacffb9..2c542ca575d 100644
--- a/code/modules/cargo/packs.dm
+++ b/code/modules/cargo/packs.dm
@@ -16,9 +16,14 @@
if(access)
C.req_access = list(access)
+ fill(C)
+
+ return C
+
+/datum/supply_pack/proc/fill(obj/structure/closet/crate/C)
for(var/item in contains)
new item(C)
- return C
+
//////////////////////////////////////////////////////////////////////////////
//////////////////////////// Emergency ///////////////////////////////////////
@@ -1368,6 +1373,13 @@
/obj/item/clothing/head/collectable/petehat)
crate_name = "collectable hats crate"
+/datum/supply_pack/misc/randomised/fill(obj/structure/closet/crate/C)
+ var/list/L = contains.Copy()
+ for(var/i in 1 to num_contained)
+ var/item = pick_n_take(L)
+ new item(C)
+
+
/datum/supply_pack/misc/randomised/contraband
name = "Contraband Crate"
contraband = TRUE
diff --git a/code/modules/holodeck/turfs.dm b/code/modules/holodeck/turfs.dm
index 92a420f8c9f..ed2021bc5f4 100644
--- a/code/modules/holodeck/turfs.dm
+++ b/code/modules/holodeck/turfs.dm
@@ -79,8 +79,7 @@
/turf/open/floor/holofloor/carpet/New()
..()
- spawn(1)
- update_icon()
+ addtimer(src, "update_icon", 1)
/turf/open/floor/holofloor/carpet/update_icon()
if(!..())
@@ -96,9 +95,9 @@
slowdown = 2
/turf/open/floor/holofloor/snow/cold
- temperature = 180
+ initial_gas_mix = "o2=22;n2=82;TEMP=180"
/turf/open/floor/holofloor/asteroid
name = "asteroid sand"
icon = 'icons/turf/floors.dmi'
- icon_state = "asteroid"
\ No newline at end of file
+ icon_state = "asteroid"
diff --git a/code/modules/hydroponics/plant_genes.dm b/code/modules/hydroponics/plant_genes.dm
index a946ed11e82..3812bc18124 100644
--- a/code/modules/hydroponics/plant_genes.dm
+++ b/code/modules/hydroponics/plant_genes.dm
@@ -202,7 +202,7 @@
if(M.slip(stun, weaken, G))
for(var/datum/plant_gene/trait/T in seed.genes)
- T.on_slip(src, M)
+ T.on_slip(G, M)
/datum/plant_gene/trait/cell_charge
// Cell recharging trait. Charges all mob's power cells to (potency*rate)% mark when eaten.
diff --git a/code/modules/mining/fulton.dm b/code/modules/mining/fulton.dm
new file mode 100644
index 00000000000..09c612b4f18
--- /dev/null
+++ b/code/modules/mining/fulton.dm
@@ -0,0 +1,188 @@
+var/list/total_extraction_beacons = list()
+
+/obj/item/weapon/extraction_pack
+ name = "fulton material extraction pack"
+ desc = "A balloon that can be used to extract a target to a Fulton Recovery Beacon. Anything not bolted down can be moved. Link the pack to a beacon by using the pack in hand."
+ icon = 'icons/obj/fulton.dmi'
+ icon_state = "extraction_pack"
+ w_class = 3
+ var/obj/structure/extraction_point/beacon
+ var/list/beacon_networks = list("station")
+ var/uses_left = 3
+ var/can_use_indoors
+ var/safe_for_living_creatures = 0
+
+/obj/item/weapon/extraction_pack/medivac
+ name = "fulton medivac extraction pack"
+ desc = "A specialized extraction balloon capable of safely extracting living targets."
+ uses_left = 1
+ safe_for_living_creatures = 1
+
+/obj/item/weapon/extraction_pack/examine()
+ . = ..()
+ usr.show_message("It has [uses_left] uses remaining.", 1)
+
+/obj/item/weapon/extraction_pack/attack_self(mob/user)
+ var/list/possible_beacons = list()
+ for(var/B in total_extraction_beacons)
+ var/obj/structure/extraction_point/EP = B
+ if(EP.beacon_network in beacon_networks)
+ possible_beacons += EP
+
+ if(!possible_beacons.len)
+ user << "There are no extraction beacons in existance!"
+ return
+
+ else
+ var/A
+
+ A = input("Select a beacon to connect to", "Balloon Extraction Pack", A) in possible_beacons
+
+ if(!A)
+ return
+ beacon = A
+
+/obj/item/weapon/extraction_pack/afterattack(atom/movable/A, mob/living/carbon/human/user, flag, params)
+ if(!beacon)
+ user << "[src] is not linked to a beacon, and cannot be used."
+ return
+ if(!can_use_indoors)
+ var/area/area = get_area(A)
+ if(!area.outdoors)
+ user << "[src] can only be used on things that are outdoors!"
+ return
+ if(!flag)
+ return
+ if(!istype(A))
+ return
+ else
+ if(!safe_for_living_creatures && check_for_living_mobs(A))
+ user << "[src] is not safe for use with living creatures, they wouldn't survive the trip back!"
+ if(A.loc == user || A == user) // no extracting stuff you're holding in your hands/yourself
+ return
+ if(A.anchored)
+ return
+ user << "You start attaching the pack to [A]..."
+ if(do_after(user,50,target=A))
+ user << "You attach the pack to [A] and activate it."
+ uses_left--
+ if(uses_left <= 0)
+ user.drop_item(src)
+ loc = A
+ var/image/balloon
+ var/image/balloon2
+ var/image/balloon3
+ if(istype(A, /mob/living))
+ var/mob/living/M = A
+ M.Weaken(16) // Keep them from moving during the duration of the extraction
+ M.buckled = 0 // Unbuckle them to prevent anchoring problems
+ else
+ A.anchored = 1
+ A.density = 0
+ var/obj/effect/extraction_holder/holder_obj = new(A.loc)
+ holder_obj.appearance = A.appearance
+ A.loc = holder_obj
+ balloon2 = image('icons/obj/fulton_balloon.dmi',"fulton_expand")
+ balloon2.pixel_y = 10
+ balloon2.appearance_flags = RESET_COLOR | RESET_ALPHA | RESET_TRANSFORM
+ holder_obj.overlays += balloon2
+ sleep(4)
+ balloon = image('icons/obj/fulton_balloon.dmi',"fulton_balloon")
+ balloon.pixel_y = 10
+ balloon.appearance_flags = RESET_COLOR | RESET_ALPHA | RESET_TRANSFORM
+ holder_obj.overlays -= balloon2
+ holder_obj.overlays += balloon
+ playsound(holder_obj.loc, 'sound/items/fulext_deploy.wav', 50, 1, -3)
+ animate(holder_obj, pixel_z = 10, time = 20)
+ sleep(20)
+ animate(holder_obj, pixel_z = 15, time = 10)
+ sleep(10)
+ animate(holder_obj, pixel_z = 10, time = 10)
+ sleep(10)
+ animate(holder_obj, pixel_z = 15, time = 10)
+ sleep(10)
+ animate(holder_obj, pixel_z = 10, time = 10)
+ sleep(10)
+ playsound(holder_obj.loc, 'sound/items/fultext_launch.wav', 50, 1, -3)
+ animate(holder_obj, pixel_z = 1000, time = 30)
+ if(istype(A, /mob/living/carbon/human))
+ var/mob/living/carbon/human/L = A
+ L.SetParalysis(0)
+ L.drowsyness = 0
+ L.sleeping = 0
+ sleep(30)
+ var/list/flooring_near_beacon = list()
+ for(var/turf/open/floor in orange(1, beacon))
+ flooring_near_beacon += floor
+ holder_obj.loc = pick(flooring_near_beacon)
+ animate(holder_obj, pixel_z = 10, time = 50)
+ sleep(50)
+ animate(holder_obj, pixel_z = 15, time = 10)
+ sleep(10)
+ animate(holder_obj, pixel_z = 10, time = 10)
+ sleep(10)
+ balloon3 = image('icons/obj/fulton_balloon.dmi',"fulton_retract")
+ balloon3.pixel_y = 10
+ balloon3.appearance_flags = RESET_COLOR | RESET_ALPHA | RESET_TRANSFORM
+ holder_obj.overlays -= balloon
+ holder_obj.overlays += balloon3
+ sleep(4)
+ holder_obj.overlays -= balloon3
+ A.anchored = 0 // An item has to be unanchored to be extracted in the first place.
+ A.density = initial(A.density)
+ animate(holder_obj, pixel_z = 0, time = 5)
+ sleep(5)
+ A.loc = holder_obj.loc
+ qdel(holder_obj)
+ if(uses_left <= 0)
+ qdel(src)
+
+
+/obj/item/fulton_core
+ name = "extraction beacon signaller"
+ desc = "Emits a signal which fulton recovery devices can lock on to. Craft with metal to create a beacon."
+ icon = 'icons/obj/stock_parts.dmi'
+ icon_state = "subspace_amplifier"
+
+/datum/crafting_recipe/fulton
+ name = "Fulton Recovery Beacon"
+ result = /obj/structure/extraction_point
+ reqs = list(/obj/item/fulton_core = 1, /obj/item/stack/sheet/metal = 5)
+ time = 15
+ category = CAT_MISC
+
+/obj/structure/extraction_point
+ name = "fulton recovery beacon"
+ desc = "A beacon for the fulton recovery system. Hit a beacon with a pack to link the pack to a beacon."
+ icon = 'icons/obj/fulton.dmi'
+ icon_state = "extraction_point"
+ anchored = 1
+ density = 0
+ var/beacon_network = "station"
+
+/obj/structure/extraction_point/New()
+ var/area/area_name = get_area(src)
+ name += " ([rand(100,999)]) ([area_name.name])"
+ total_extraction_beacons += src
+ ..()
+
+/obj/structure/extraction_point/Destroy()
+ total_extraction_beacons -= src
+ ..()
+
+/obj/effect/extraction_holder
+ name = "extraction holder"
+ desc = "you shouldnt see this"
+ var/atom/movable/stored_obj
+
+/obj/item/weapon/extraction_pack/proc/check_for_living_mobs(atom/A)
+ if(istype(A, /mob/living))
+ var/mob/living/L = A
+ if(L.stat != DEAD)
+ return 1
+ for(var/thing in A.GetAllContents())
+ if(istype(A, /mob/living))
+ var/mob/living/L = A
+ if(L.stat != DEAD)
+ return 1
+ return 0
\ No newline at end of file
diff --git a/code/modules/mining/lavaland/weather.dm b/code/modules/mining/lavaland/weather.dm
index 6415b41e024..33eb1e4e6b7 100644
--- a/code/modules/mining/lavaland/weather.dm
+++ b/code/modules/mining/lavaland/weather.dm
@@ -7,12 +7,15 @@
var/name = "storm"
var/start_up_time = 300 //30 seconds
var/start_up_message = "The wind begins to pick up."
+ var/start_up_sound
var/duration = 120 //2 minutes
var/duration_lower = 120
var/duration_upper = 120
+ var/duration_sound
var/duration_message = "A storm has started!"
var/wind_down = 300 // 30 seconds
var/wind_down_message = "The storm is passing."
+ var/wind_down_sound
var/target_z = 1
var/exclude_walls = TRUE
@@ -35,18 +38,22 @@
update_areas()
for(var/mob/M in player_list)
if(M.z == target_z)
- M << "[start_up_message]"
-
+ M << "[start_up_message]"
+ if(start_up_sound)
+ M << start_up_sound
sleep(start_up_time)
- stage = MAIN_STAGE
- weather_main()
+ if(src && stage != MAIN_STAGE)
+ stage = MAIN_STAGE
+ weather_main()
/datum/weather/proc/weather_main()
update_areas()
for(var/mob/M in player_list)
if(M.z == target_z)
- M << "[duration_message]"
+ M << "[duration_message]"
+ if(duration_sound)
+ M << duration_sound
if(purely_aesthetic)
sleep(duration*10)
else //Storm effects
@@ -57,8 +64,9 @@
storm_act(L)
sleep(10)
- stage = WIND_DOWN_STAGE
- weather_wind_down()
+ if(src && stage != WIND_DOWN_STAGE)
+ stage = WIND_DOWN_STAGE
+ weather_wind_down()
/datum/weather/proc/weather_wind_down()
@@ -66,11 +74,13 @@
for(var/mob/M in player_list)
if(M.z == target_z)
M << "[wind_down_message]"
-
+ if(wind_down_sound)
+ M << wind_down_sound
sleep(wind_down)
- stage = END_STAGE
- update_areas()
+ if(src && stage != END_STAGE)
+ stage = END_STAGE
+ update_areas()
/datum/weather/proc/storm_act(mob/living/L)
diff --git a/code/modules/mining/lavaland/weather_types.dm b/code/modules/mining/lavaland/weather_types.dm
index dc3f35f6d9c..bc205602ccc 100644
--- a/code/modules/mining/lavaland/weather_types.dm
+++ b/code/modules/mining/lavaland/weather_types.dm
@@ -41,7 +41,7 @@
duration_upper = 60 //1 minute
duration_message = "This isn't average everyday darkness... this is advanced darkness!"
wind_down = 100 // 10 seconds
- wind_down_message = "The darkness is receding. Thank god."
+ wind_down_message = "The darkness recedes."
purely_aesthetic = TRUE
target_z = 1
@@ -68,12 +68,15 @@
/datum/weather/ash_storm
name = "ash storm"
start_up_time = 300 //30 seconds
- start_up_message = "The wind begins to pick up. Seek shelter."
+ start_up_message = "An eerie moan rises on the wind. Sheets of burning ash blacken the horizon. Seek shelter."
+ start_up_sound = 'sound/lavaland/ash_storm_windup.ogg'
duration_lower = 60 //1 minute
duration_upper = 150 //2.5 minutes
- duration_message = "An ash storm has started! Get inside!"
+ duration_message = "Smoldering clouds of scorching ash billow down around you! Get inside!"
+ duration_sound = 'sound/lavaland/ash_storm_start.ogg'
wind_down = 300 // 30 seconds
- wind_down_message = "The storm begins to fade. Should be safe to go outside again."
+ wind_down_message = "The shrieking wind whips away the last of the ash and falls to its usual murmur. It should be safe to go outside now."
+ wind_down_sound = 'sound/lavaland/ash_storm_end.ogg'
target_z = ZLEVEL_LAVALAND
area_type = /area/lavaland/surface/outdoors
@@ -88,8 +91,8 @@
/datum/weather/ash_storm/false_alarm //No storm, just light ember fall
purely_aesthetic = TRUE
duration_overlay = "light_ash"
- duration_message = "Looks like the storm just missed the mining area. False alarm."
- wind_down_message = "The ash fall starts to trail off."
+ duration_message = "Gentle ashfall surrounds you like grotesque snow. The storm seems to have passed you by."
+ wind_down_message = "The ashfall quietly slows, then stops. Another layer of hardened soot to the volcanic rock beneath you."
/datum/weather/ash_storm/storm_act(mob/living/L)
if(immunity_type in L.weather_immunities)
diff --git a/code/modules/mining/machine_vending.dm b/code/modules/mining/machine_vending.dm
index 17f2c8c2668..c2644d89b95 100644
--- a/code/modules/mining/machine_vending.dm
+++ b/code/modules/mining/machine_vending.dm
@@ -19,6 +19,7 @@
new /datum/data/mining_equipment("Alien Toy", /obj/item/clothing/mask/facehugger/toy, 300),
new /datum/data/mining_equipment("Advanced Scanner", /obj/item/device/t_scanner/adv_mining_scanner, 800),
new /datum/data/mining_equipment("Hivelord Stabilizer", /obj/item/weapon/hivelordstabilizer , 400),
+ new /datum/data/mining_equipment("Fulton Beacon", /obj/item/fulton_core , 400),
new /datum/data/mining_equipment("Shelter Capsule", /obj/item/weapon/survivalcapsule , 400),
new /datum/data/mining_equipment("GAR scanners", /obj/item/clothing/glasses/meson/gar, 500),
new /datum/data/mining_equipment("Explorer's Webbing", /obj/item/weapon/storage/belt/mining, 500),
@@ -28,6 +29,8 @@
new /datum/data/mining_equipment("Jaunter", /obj/item/device/wormhole_jaunter, 750),
new /datum/data/mining_equipment("Kinetic Accelerator", /obj/item/weapon/gun/energy/kinetic_accelerator, 750),
new /datum/data/mining_equipment("Resonator", /obj/item/weapon/resonator, 800),
+ new /datum/data/mining_equipment("Medivac Balloon", /obj/item/weapon/extraction_pack/medivac, 800),
+ new /datum/data/mining_equipment("Fulton Pack", /obj/item/weapon/extraction_pack, 1000),
new /datum/data/mining_equipment("Lazarus Injector", /obj/item/weapon/lazarus_injector, 1000),
new /datum/data/mining_equipment("Silver Pickaxe", /obj/item/weapon/pickaxe/silver, 1000),
new /datum/data/mining_equipment("Jetpack Upgrade", /obj/item/hardsuit_jetpack, 2000),
@@ -155,20 +158,28 @@
return ..()
/obj/machinery/mineral/equipment_vendor/proc/RedeemVoucher(obj/item/weapon/mining_voucher/voucher, mob/redeemer)
- var/selection = input(redeemer, "Pick your equipment", "Mining Voucher Redemption") as null|anything in list("Survival Capsule and Explorer's Webbing", "Resonator", "Mining Drone", "Advanced Scanner")
+ var/selection = input(redeemer, "Pick your equipment", "Mining Voucher Redemption") as null|anything in list("Survival Capsule and Explorer's Webbing", "Resonator and Advanced Scanner", "Mining Drone", "Medivac Kit", "Extraction Kit")
if(!selection || !Adjacent(redeemer) || qdeleted(voucher) || voucher.loc != redeemer)
return
switch(selection)
if("Survival Capsule and Explorer's Webbing")
new /obj/item/weapon/storage/belt/mining(src.loc)
new /obj/item/weapon/survivalcapsule(src.loc)
- if("Resonator")
+ if("Resonator and Advanced Scanner")
new /obj/item/weapon/resonator(src.loc)
+ new /obj/item/device/t_scanner/adv_mining_scanner(src.loc)
if("Mining Drone")
new /mob/living/simple_animal/hostile/mining_drone(src.loc)
new /obj/item/weapon/weldingtool/hugetank(src.loc)
- if("Advanced Scanner")
- new /obj/item/device/t_scanner/adv_mining_scanner(src.loc)
+ if("Medivac Kit")
+ new /obj/item/stack/sheet/metal/five(loc)
+ new /obj/item/fulton_core(loc)
+ new /obj/item/weapon/extraction_pack/medivac(loc)
+ new /obj/item/weapon/reagent_containers/hypospray/medipen/survival(loc)
+ if("Extraction Kit")
+ new /obj/item/stack/sheet/metal/five(loc)
+ new /obj/item/weapon/extraction_pack(loc)
+ new /obj/item/fulton_core(loc)
feedback_add_details("mining_voucher_redeemed", selection)
qdel(voucher)
diff --git a/code/modules/mining/mine_turfs.dm b/code/modules/mining/mine_turfs.dm
index 738e8cc9ccb..61d203af0da 100644
--- a/code/modules/mining/mine_turfs.dm
+++ b/code/modules/mining/mine_turfs.dm
@@ -263,7 +263,8 @@
/turf/open/floor/plating/asteroid/airless/cave/volcanic
mob_spawn_list = list(/mob/living/simple_animal/hostile/asteroid/goldgrub = 10, /mob/living/simple_animal/hostile/asteroid/goliath/beast = 50, /mob/living/simple_animal/hostile/asteroid/basilisk/watcher = 40, /mob/living/simple_animal/hostile/asteroid/hivelord/legion = 30,
- /mob/living/simple_animal/hostile/spawner/lavaland = 2, /mob/living/simple_animal/hostile/spawner/lavaland/goliath = 3, /mob/living/simple_animal/hostile/spawner/lavaland/legion = 3, /mob/living/simple_animal/hostile/megafauna/dragon = 2, /mob/living/simple_animal/hostile/megafauna/bubblegum = 2, /mob/living/simple_animal/hostile/megafauna/colossus = 2)
+ /mob/living/simple_animal/hostile/spawner/lavaland = 2, /mob/living/simple_animal/hostile/spawner/lavaland/goliath = 3, /mob/living/simple_animal/hostile/spawner/lavaland/legion = 3, \
+ /mob/living/simple_animal/hostile/megafauna/dragon = 2, /mob/living/simple_animal/hostile/megafauna/bubblegum = 2, /mob/living/simple_animal/hostile/megafauna/colossus = 2)
turf_type = /turf/open/floor/plating/asteroid/basalt/lava_land_surface
initial_gas_mix = "o2=14;n2=23;TEMP=300"
@@ -587,7 +588,7 @@
if(istype(H.belt, /obj/item/device/wormhole_jaunter))
var/obj/item/device/wormhole_jaunter/J = H.belt
// To freak out any bystanders
- visible_message("[H] falls into [src]!")
+ visible_message("[H] falls into [src]!")
J.chasm_react(H)
return
if(H.dna.species && (FLYING in H.dna.species.specflags))
@@ -599,9 +600,10 @@
/*visible_message("[AM] falls into [src]!")
qdel(AM)*/
AM.forceMove(locate(drop_x, drop_y, drop_z))
- AM.visible_message("[AM] falls from above!")
+ AM.visible_message("[AM] falls from above!", "GAH! Ah... where are you?")
if(istype(AM, /mob/living))
var/mob/living/L = AM
+ L.Weaken(5)
L.adjustBruteLoss(30)
/turf/open/chasm/straight_down/New()
@@ -625,7 +627,20 @@
/turf/open/chasm/straight_down/lava_land_surface/drop(atom/movable/AM)
if(!AM.invisibility)
- visible_message("[AM] falls into [src]!")
+ AM.visible_message("[AM] falls into [src]!", "You stumble and stare into an abyss before you. It stares back, and you fall \
+ into the enveloping dark.")
+ if(isliving(AM))
+ var/mob/living/L = AM
+ L.notransform = TRUE
+ L.Stun(10)
+ L.resting = TRUE
+ animate(AM, transform = matrix() - matrix(), alpha = 0, color = rgb(0, 0, 0), time = 10)
+ for(var/i in 1 to 5)
+ AM.pixel_y--
+ sleep(2)
+ if(isrobot(AM))
+ var/mob/living/silicon/robot/S = AM
+ qdel(S.mmi)
qdel(AM)
/turf/closed/mineral/volcanic/lava_land_surface
diff --git a/code/modules/mob/living/carbon/alien/humanoid/caste/praetorian.dm b/code/modules/mob/living/carbon/alien/humanoid/caste/praetorian.dm
index 8a15c4b4c9e..fb00f816313 100644
--- a/code/modules/mob/living/carbon/alien/humanoid/caste/praetorian.dm
+++ b/code/modules/mob/living/carbon/alien/humanoid/caste/praetorian.dm
@@ -40,8 +40,19 @@
return 0
if(!alien_type_present(/mob/living/carbon/alien/humanoid/royal/queen))
var/mob/living/carbon/alien/humanoid/royal/queen/new_xeno = new (user.loc)
+ if(user.client.prefs.unlock_content) //check the player is a donator
+ switch(alert("Would you like to use your alternative skin?",,"Yes","No"))
+ if("Yes")
+ new_xeno.maidify()
+ if("No")
+ user << "You decide against the xeno fetish outfit"
user.alien_evolve(new_xeno)
return 1
else
user << "We already have an alive queen."
- return 0
\ No newline at end of file
+ return 0
+
+/mob/living/carbon/alien/humanoid/royal/queen/proc/maidify()
+ name = "alien queen maid"
+ icon_state = "alienqmaid"
+ caste = "qmaid"
diff --git a/code/modules/mob/living/simple_animal/guardian/guardian.dm b/code/modules/mob/living/simple_animal/guardian/guardian.dm
index 5a2df11e5f9..1a3b8445f62 100644
--- a/code/modules/mob/living/simple_animal/guardian/guardian.dm
+++ b/code/modules/mob/living/simple_animal/guardian/guardian.dm
@@ -499,7 +499,7 @@ var/global/list/parasites = list() //all currently existing/living guardians
info = {"A list of Holoparasite Types
- Assassin: Does low damage and takes full damage, but can enter stealth, causing its next attack to do massive damage and ignore armor. However, it becomes briefly unable to recall after attacking from stealth.
+ Assassin: Does medium damage and takes full damage, but can enter stealth, causing its next attack to do massive damage and ignore armor. However, it becomes briefly unable to recall after attacking from stealth.
Chaos: Ignites enemies on touch and causes them to hallucinate all nearby people as the parasite. Automatically extinguishes the user if they catch on fire.
diff --git a/code/modules/mob/living/simple_animal/guardian/types/assassin.dm b/code/modules/mob/living/simple_animal/guardian/types/assassin.dm
index ed198b28d47..d54d5013690 100644
--- a/code/modules/mob/living/simple_animal/guardian/types/assassin.dm
+++ b/code/modules/mob/living/simple_animal/guardian/types/assassin.dm
@@ -1,18 +1,18 @@
//Assassin
/mob/living/simple_animal/hostile/guardian/assassin
- melee_damage_lower = 13
- melee_damage_upper = 13
+ melee_damage_lower = 15
+ melee_damage_upper = 15
attacktext = "slashes"
attack_sound = 'sound/weapons/bladeslice.ogg'
damage_coeff = list(BRUTE = 1, BURN = 1, TOX = 1, CLONE = 1, STAMINA = 0, OXY = 1)
- playstyle_string = "As an assassin type you do low damage and have no damage resistance, but can enter stealth, massively increasing the damage of your next attack and causing it to ignore armor. Stealth is broken when you attack or take damage."
+ playstyle_string = "As an assassin type you do medium damage and have no damage resistance, but can enter stealth, massively increasing the damage of your next attack and causing it to ignore armor. Stealth is broken when you attack or take damage."
magic_fluff_string = "..And draw the Space Ninja, a lethal, invisible assassin."
tech_fluff_string = "Boot sequence complete. Assassin modules loaded. Holoparasite swarm online."
carp_fluff_string = "CARP CARP CARP! Caught one! It's an assassin carp! Just when you thought it was safe to go back to the water... which is unhelpful, because we're in space."
toggle_button_type = /obj/screen/guardian/ToggleMode/Assassin
var/toggle = FALSE
- var/stealthcooldown = 200
+ var/stealthcooldown = 160
var/obj/screen/alert/canstealthalert
var/obj/screen/alert/instealthalert
@@ -58,7 +58,7 @@
else
visible_message("\The [src] suddenly appears!")
stealthcooldown = world.time + initial(stealthcooldown) //we were forced out of stealth and go on cooldown
- cooldown = world.time + 50 //can't recall for 5 seconds
+ cooldown = world.time + 40 //can't recall for 4 seconds
updatestealthalert()
toggle = FALSE
else if(stealthcooldown <= world.time)
diff --git a/code/modules/mob/living/simple_animal/guardian/types/charger.dm b/code/modules/mob/living/simple_animal/guardian/types/charger.dm
index f2903408299..fc519b92144 100644
--- a/code/modules/mob/living/simple_animal/guardian/types/charger.dm
+++ b/code/modules/mob/living/simple_animal/guardian/types/charger.dm
@@ -4,7 +4,7 @@
melee_damage_upper = 15
ranged = 1 //technically
ranged_message = "charges"
- ranged_cooldown_time = 50
+ ranged_cooldown_time = 40
speed = -1
damage_coeff = list(BRUTE = 0.6, BURN = 0.6, TOX = 0.6, CLONE = 0.6, STAMINA = 0, OXY = 0.6)
playstyle_string = "As a charger type you do medium damage, have medium damage resistance, move very fast, and can charge at a location, damaging any target hit and forcing them to drop any items they are holding."
diff --git a/code/modules/mob/living/simple_animal/guardian/types/fire.dm b/code/modules/mob/living/simple_animal/guardian/types/fire.dm
index 879799dca53..2ede8928032 100644
--- a/code/modules/mob/living/simple_animal/guardian/types/fire.dm
+++ b/code/modules/mob/living/simple_animal/guardian/types/fire.dm
@@ -1,12 +1,12 @@
//Fire
/mob/living/simple_animal/hostile/guardian/fire
a_intent = "help"
- melee_damage_lower = 10
- melee_damage_upper = 10
+ melee_damage_lower = 7
+ melee_damage_upper = 7
attack_sound = 'sound/items/Welder.ogg'
attacktext = "sears"
damage_coeff = list(BRUTE = 0.8, BURN = 0.8, TOX = 0.8, CLONE = 0.8, STAMINA = 0, OXY = 0.8)
- range = 10
+ range = 7
playstyle_string = "As a chaos type, you have only light damage resistance, but will ignite any enemy you bump into. In addition, your melee attacks will cause human targets to see everyone as you."
magic_fluff_string = "..And draw the Wizard, bringer of endless chaos!"
tech_fluff_string = "Boot sequence complete. Crowd control modules activated. Holoparasite swarm online."
diff --git a/code/modules/mob/living/simple_animal/guardian/types/lightning.dm b/code/modules/mob/living/simple_animal/guardian/types/lightning.dm
index deaef1dbe72..38a03707ef2 100644
--- a/code/modules/mob/living/simple_animal/guardian/types/lightning.dm
+++ b/code/modules/mob/living/simple_animal/guardian/types/lightning.dm
@@ -4,8 +4,8 @@
layer = LYING_MOB_LAYER
/mob/living/simple_animal/hostile/guardian/beam
- melee_damage_lower = 5
- melee_damage_upper = 5
+ melee_damage_lower = 7
+ melee_damage_upper = 7
attacktext = "shocks"
melee_damage_type = BURN
attack_sound = 'sound/machines/defib_zap.ogg'
@@ -108,5 +108,5 @@
"You are shocked by the lightning chain!", \
"You hear a heavy electrical crack." \
)
- L.adjustFireLoss(0.9) //adds up very rapidly
+ L.adjustFireLoss(1.2) //adds up very rapidly
. = 1
diff --git a/code/modules/mob/living/simple_animal/guardian/types/ranged.dm b/code/modules/mob/living/simple_animal/guardian/types/ranged.dm
index a1d618a632b..3d4b665fa81 100644
--- a/code/modules/mob/living/simple_animal/guardian/types/ranged.dm
+++ b/code/modules/mob/living/simple_animal/guardian/types/ranged.dm
@@ -30,12 +30,12 @@
/mob/living/simple_animal/hostile/guardian/ranged/ToggleMode()
if(src.loc == summoner)
if(toggle)
- ranged = 1
- melee_damage_lower = 10
- melee_damage_upper = 10
+ ranged = initial(ranged)
+ melee_damage_lower = initial(melee_damage_lower)
+ melee_damage_upper = initial(melee_damage_upper)
environment_smash = initial(environment_smash)
alpha = 255
- range = 13
+ range = initial(range)
incorporeal_move = 0
src << "You switch to combat mode."
toggle = FALSE
diff --git a/code/modules/mob/living/simple_animal/hostile/megafauna/colossus.dm b/code/modules/mob/living/simple_animal/hostile/megafauna/colossus.dm
index d950bcf4eb2..8b29777419a 100644
--- a/code/modules/mob/living/simple_animal/hostile/megafauna/colossus.dm
+++ b/code/modules/mob/living/simple_animal/hostile/megafauna/colossus.dm
@@ -29,7 +29,7 @@
loot = list(/obj/machinery/smartfridge/black_box)
butcher_results = list(/obj/item/weapon/ore/diamond = 5, /obj/item/stack/sheet/sinew = 5, /obj/item/stack/sheet/animalhide/ashdrake = 10, /obj/item/stack/sheet/bone = 30)
- deathmessage = "disintegrates, leaving a glowing core."
+ deathmessage = "disintegrates, leaving a glowing core in its wake."
death_sound = 'sound/magic/demon_dies.ogg'
damage_coeff = list(BRUTE = 1, BURN = 0.5, TOX = 1, CLONE = 1, STAMINA = 0, OXY = 1)
var/anger_modifier = 0
@@ -114,7 +114,7 @@
/mob/living/simple_animal/hostile/megafauna/colossus/proc/double_spiral()
- visible_message("\"Die\"")
+ visible_message("\"Die.\"")
sleep(10)
spawn()
@@ -220,55 +220,6 @@
playsound(get_turf(src),'sound/magic/clockwork/narsie_attack.ogg', 200, 1)
-/mob/living/simple_animal/hostile/megafauna/colossus/proc/seeking_laser()
- visible_message("\"You can't run.\"")
- var/obj/effect/overlay/temp/seeking_beam/B = new(get_turf(src))
- B.target = target
- B.firer = src
-
-/obj/effect/overlay/temp/seeking_beam
- name = "disintegration ball"
- desc = "Get out of the way!"
- icon = 'icons/effects/effects.dmi'
- icon_state = "shield-cult"
- density = 1
- luminosity = 1
- var/target
- var/firer
- duration = 100
-
-/obj/effect/overlay/temp/seeking_beam/New()
- ..()
- spawn()
- while(loc)
- step_towards(src, target)
- sleep(1)
-
-/obj/effect/overlay/temp/seeking_beam/process()
- step_towards(src, target)
-
-/obj/effect/overlay/temp/seeking_beam/Crossed(AM as mob|obj)
- ..()
- collision(AM)
-
-/obj/effect/overlay/temp/seeking_beam/Bumped(AM as mob|obj)
- ..()
- collision(AM)
-
-/obj/effect/overlay/temp/seeking_beam/Bump(AM as mob|obj)
- ..()
- collision(AM)
-
-/obj/effect/overlay/temp/seeking_beam/proc/collision(AM as mob|obj)
- if(AM == firer)
- return
- if(isliving(AM))
- var/mob/living/M = AM
- visible_message("[M] is disintegrated by the disintegration ball!")
- M.dust()
- else if(istype(AM, /obj/item))
- var/obj/item/I = AM
- I.burn()
/obj/item/projectile/colossus
name ="death bolt"
diff --git a/code/modules/mob/living/simple_animal/hostile/megafauna/legion.dm b/code/modules/mob/living/simple_animal/hostile/megafauna/legion.dm
index eaa280c9c48..c4ae6eefecf 100644
--- a/code/modules/mob/living/simple_animal/hostile/megafauna/legion.dm
+++ b/code/modules/mob/living/simple_animal/hostile/megafauna/legion.dm
@@ -42,7 +42,7 @@
A.faction = faction
ranged_cooldown = world.time + ranged_cooldown_time
else
- visible_message("[src] charges!")
+ visible_message("[src] charges!")
SpinAnimation(speed = 20, loops = 5)
ranged = 0
retreat_distance = 0
@@ -81,7 +81,7 @@
L.target = target
- visible_message("[src] splits!")
+ visible_message("[src] splits in twain!")
else
var/last_legion = TRUE
for(var/mob/living/simple_animal/hostile/megafauna/legion/other in mob_list)
@@ -123,7 +123,7 @@
/obj/item/weapon/staff_of_storms/attack_self(mob/user)
if(storm_cooldown > world.time)
- user << "The staff is still recharging."
+ user << "The staff is still recharging!"
return
if(!linked_machine || linked_machine.z != user.z)
@@ -134,18 +134,21 @@
if(linked_machine && linked_machine.ongoing_weather)
if(linked_machine.ongoing_weather.stage == WIND_DOWN_STAGE || linked_machine.ongoing_weather.stage == END_STAGE)
- user << "The storm is already ending. It would be a waste to use the staff now."
+ user << "The storm is already ending. It would be a waste to use the staff now."
return
- linked_machine.ongoing_weather.duration = 0
- user << "With an appropriately dramatic flourish, you dispell the storm."
- playsound(get_turf(src),'sound/magic/Staff_Change.ogg', 200, 1)
+ user.visible_message("[user] holds [src] skywards, causing its orb to flare!", \
+ "With an appropriately dramatic flourish, you dispel the storm!")
+ playsound(get_turf(src),'sound/magic/Staff_Change.ogg', 200, 0)
storm_cooldown = world.time + 600
+ linked_machine.ongoing_weather.stage = WIND_DOWN_STAGE
+ linked_machine.ongoing_weather.weather_wind_down()
else if (linked_machine && !linked_machine.ongoing_weather)
- user << "You lift the staff towards the heavens, calling down a terrible storm."
- linked_machine.weather_cooldown = 0
- playsound(get_turf(src),'sound/magic/Staff_Change.ogg', 200, 1)
+ user.visible_message("[user] holds [src] skywards, causing its orb to flare!", \
+ "You lift your staff skywards, calling down a terrible storm!")
+ playsound(get_turf(src),'sound/magic/Staff_Chaos.ogg', 200, 0)
storm_cooldown = world.time + 600
+ linked_machine.weather_cooldown = 0
else
- user << "You can't seem to control the weather here."
\ No newline at end of file
+ user << "You can't seem to control the weather here."
diff --git a/code/modules/mob/living/simple_animal/hostile/mining_mobs.dm b/code/modules/mob/living/simple_animal/hostile/mining_mobs.dm
index 8e11397c251..431881a0ed1 100644
--- a/code/modules/mob/living/simple_animal/hostile/mining_mobs.dm
+++ b/code/modules/mob/living/simple_animal/hostile/mining_mobs.dm
@@ -711,7 +711,7 @@
/mob/living/simple_animal/hostile/asteroid/basilisk/watcher
name = "watcher"
- desc = "Its stare causes victims to freeze from the inside."
+ desc = "A levitating, eye-like creature held aloft by winglike formations of sinew. A sharp spine of crystal protrudes from its body."
icon = 'icons/mob/lavaland/watcher.dmi'
icon_state = "watcher"
icon_living = "watcher"
@@ -721,7 +721,7 @@
throw_message = "bounces harmlessly off of"
melee_damage_lower = 15
melee_damage_upper = 15
- attacktext = "stares into the soul of"
+ attacktext = "impales"
a_intent = "harm"
speak_emote = list("telepathically cries")
attack_sound = 'sound/weapons/bladeslice.ogg'
@@ -734,7 +734,7 @@
/mob/living/simple_animal/hostile/asteroid/goliath/beast
name = "goliath"
- desc = "A massive beast that uses long tentacles to ensare its prey, threatening them is not advised under any conditions."
+ desc = "A hulking, armor-plated beast with long tendrils arching from its back."
icon = 'icons/mob/lavaland/lavaland_monsters.dmi'
icon_state = "goliath"
icon_living = "goliath"
@@ -774,7 +774,7 @@
var/mob/living/carbon/human/stored_mob
/mob/living/simple_animal/hostile/asteroid/hivelord/legion/death(gibbed)
- visible_message("[src] wails as in anger as they are driven from their form!")
+ visible_message("The skulls on [src] wail in anger as they flee from their dying host!")
if(stored_mob)
stored_mob.loc = get_turf(src)
stored_mob.adjustBruteLoss(1000)
@@ -1007,14 +1007,14 @@
/obj/effect/collapse/New()
..()
- visible_message("The tendril writhes in pain and anger and the earth around it begins to split! Get back!")
- visible_message("A chest falls clear of the tendril!")
+ visible_message("The tendril writhes in fury as the earth around it begins to crack and break apart! Get back!")
+ visible_message("Something falls free of the tendril!")
playsound(get_turf(src),'sound/effects/tendril_destroyed.ogg', 200, 0, 50, 1, 1)
spawn(50)
for(var/mob/M in range(7,src))
shake_camera(M, 15, 1)
playsound(get_turf(src),'sound/effects/explosionfar.ogg', 200, 1)
- visible_message("The tendril collapes!")
+ visible_message("The tendril falls inward, the ground around it widening into a yawning chasm!")
for(var/turf/T in range(2,src))
if(!T.density)
T.ChangeTurf(/turf/open/chasm/straight_down/lava_land_surface)
diff --git a/code/modules/ruins/lavaland_ruin_code.dm b/code/modules/ruins/lavaland_ruin_code.dm
index 755fbde1da1..ac45476b535 100644
--- a/code/modules/ruins/lavaland_ruin_code.dm
+++ b/code/modules/ruins/lavaland_ruin_code.dm
@@ -1,40 +1,4 @@
-/obj/structure/lavaland_door
- name = "necropolis gate"
- desc = "An imposing, seemingly impenetrable door."
- icon = 'icons/effects/96x96.dmi'
- icon_state = "door"
- anchored = 1
- density = 1
- bound_width = 96
- bound_height = 96
- burn_state = LAVA_PROOF
- luminosity = 1
- var/boss = FALSE
-
-/obj/structure/lavaland_door/attack_hand(mob/user)
- if(boss)
- return
- for(var/mob/living/simple_animal/hostile/megafauna/legion/L in mob_list)
- return
- var/safety = alert(user, "Are you sure you want to do this? You and everyone else on lavaland will likely die.", "Knock on the door?", "Proceed", "Abort")
- if(safety == "Abort" || !in_range(src, user) || !src || boss || user.incapacitated())
- return
- boss = TRUE
- user << "You knock on the door."
- playsound(user.loc, 'sound/effects/shieldbash.ogg', 50, 1)
- visible_message("Legion emerges from the Necropolis!")
- message_admins("[key_name_admin(user)] has summoned Legion.")
- log_game("[key_name(user)] summoned Legion.")
- new /mob/living/simple_animal/hostile/megafauna/legion(get_step(src.loc, SOUTH))
-
-/obj/structure/lavaland_door/singularity_pull()
- return 0
-
-/obj/structure/lavaland_door/Destroy(force)
- if(force)
- . = ..()
- else
- return QDEL_HINT_LETMELIVE
+//If you're looking for spawners like ash walker eggs, check ghost_role_spawners.dm
/obj/machinery/lavaland_controller
name = "weather control machine"
@@ -48,7 +12,11 @@
if(ongoing_weather || weather_cooldown > world.time)
return
weather_cooldown = world.time + rand(3500, 6500)
- var/datum/weather/ash_storm/LAVA = new /datum/weather/ash_storm
+ var/datum/weather/ash_storm/LAVA
+ if(prob(10)) //10% chance for the ash storm to miss the area entirely
+ LAVA = new /datum/weather/ash_storm/false_alarm
+ else
+ LAVA = new /datum/weather/ash_storm
ongoing_weather = LAVA
LAVA.weather_start_up()
ongoing_weather = null
@@ -76,211 +44,6 @@
/obj/item/seeds/sunflower/moonflower = 8
)
-/obj/effect/mob_spawn/human/seed_vault
- name = "vault creature sleeper"
- mob_name = "Vault Creature"
- icon = 'icons/obj/Cryogenic2.dmi'
- icon_state = "sleeper"
- roundstart = FALSE
- death = FALSE
- mob_species = /datum/species/pod
- flavour_text = {"You are a strange, artificial creature. Your creators were a highly advanced and benevolent race, and launched many seed vaults into the stars, hoping to aid fledgling civilizations. You are to tend to the vault and await the arrival of sentient species. You've been waiting quite a while though..."}
-
-/obj/effect/mob_spawn/human/seed_vault/special(mob/living/new_spawn)
- var/plant_name = pick("Tomato", "Potato", "Brocolli", "Carrot", "Deathcap", "Ambrosia", "Pumpkin", "Ivy", "Kudzu", "Bannana", "Moss", "Flower", "Bloom", "Spore", "Root", "Bark", "Glowshroom", "Petal", "Leaf", "Venus", "Sprout","Cocao", "Strawberry", "Citrus", "Oak", "Cactus", "Pepper", "Juniper")
- new_spawn.real_name = plant_name
-
-//Greed
-
-/obj/structure/cursed_slot_machine
- name = "greed's slot machine"
- desc = "High stakes, high rewards."
- icon = 'icons/obj/economy.dmi'
- icon_state = "slots1"
- anchored = 1
- density = 1
- var/win_prob = 5
-
-/obj/structure/cursed_slot_machine/attack_hand(mob/living/carbon/human/user)
- if(!istype(user))
- return
- if(in_use)
- return
- in_use = TRUE
- user << "You feel your very life draining away as you pull the lever...it'll be worth it though, right?"
- user.adjustCloneLoss(20)
- if(user.stat)
- user.gib()
- icon_state = "slots2"
- sleep(50)
- icon_state = "slots1"
- in_use = FALSE
- if(prob(win_prob))
- new /obj/item/weapon/dice/d20/fate/one_use(get_turf(src))
- if(user)
- user << "You hear laughter echoing around you as the machine fades away. In it's place...more gambling."
- qdel(src)
- else
- if(user)
- user << "Looks like you didn't win anything this time...next time though, right?"
-//Gluttony
-
-/obj/effect/gluttony
- name = "gluttony's wall"
- desc = "Only those who truly indulge may pass."
- anchored = 1
- density = 1
- icon_state = "blob"
- icon = 'icons/mob/blob.dmi'
-
-/obj/effect/gluttony/CanPass(atom/movable/mover, turf/target, height=0)//So bullets will fly over and stuff.
- if(height==0)
- return 1
- if(istype(mover, /mob/living/carbon/human))
- var/mob/living/carbon/human/H = mover
- if(H.nutrition >= NUTRITION_LEVEL_FAT)
- return 1
- else
- H << "You're not gluttonous enough to pass this barrier!"
- else
- return 0
-
-//Pride
-
-/obj/structure/mirror/magic/pride
- name = "pride's mirror"
- desc = "Pride cometh before the..."
- icon_state = "magic_mirror"
-
-/obj/structure/mirror/magic/pride/curse(mob/user)
- user.visible_message("The ground splits beneath [user] as their hand leaves the mirror!")
- var/turf/T = get_turf(user)
- T.ChangeTurf(/turf/open/chasm/straight_down)
- var/turf/open/chasm/straight_down/C = T
- C.drop(user)
-
-//Sloth - I'll finish this item later
-
-//Envy
-
-/obj/item/weapon/knife/envy
- name = "envy's knife"
- desc = "Their success will be yours."
- icon = 'icons/obj/wizard.dmi'
- icon_state = "render"
- item_state = "render"
- force = 18
- throwforce = 10
- w_class = 3
- hitsound = 'sound/weapons/bladeslice.ogg'
-
-/obj/item/weapon/knife/envy/afterattack(atom/movable/AM, mob/living/carbon/human/user, proximity)
- ..()
- if(!proximity)
- return
- if(!istype(user))
- return
- if(istype(AM, /mob/living/carbon/human))
- var/mob/living/carbon/human/H = AM
- if(user.real_name != H.dna.real_name)
- user.real_name = H.dna.real_name
- H.dna.transfer_identity(user, transfer_SE=1)
- user.updateappearance(mutcolor_update=1)
- user.domutcheck()
- user << "You assume the face of [H]. Are you satisfied?"
-
-///Ash Walkers
-
-/mob/living/simple_animal/hostile/spawner/ash_walker
- name = "ash walker nest"
- desc = "A nest built around a necropolis tendril. The eggs seem to grow unnaturally fast..."
- icon = 'icons/mob/nest.dmi'
- icon_state = "ash_walker_nest"
- icon_living = "ash_walker_nest"
- faction = list("ashwalker")
- health = 200
- maxHealth = 200
- loot = list(/obj/effect/gibspawner, /obj/item/device/assembly/signaler/anomaly)
- del_on_death = 1
- var/meat_counter
-
-/mob/living/simple_animal/hostile/spawner/ash_walker/Life()
- ..()
- if(!stat)
- consume()
- spawn_mob()
-
-/mob/living/simple_animal/hostile/spawner/ash_walker/proc/consume()
- for(var/mob/living/H in view(src,1)) //Only for corpse right next to/on same tile
- if(H.stat)
- visible_message("Tendrils reach out from \the [src.name] pulling [H] in! Blood seeps over the eggs as [H] is devoured.")
- playsound(get_turf(src),'sound/magic/Demon_consume.ogg', 100, 1)
- if(istype(H,/mob/living/simple_animal/hostile/megafauna/dragon))
- meat_counter += 20
- else
- meat_counter ++
- for(var/obj/item/W in H)
- H.unEquip(W)
- H.gib()
-
-/mob/living/simple_animal/hostile/spawner/ash_walker/spawn_mob()
- if(meat_counter >= 2)
- new /obj/effect/mob_spawn/human/ash_walker(get_step(src.loc, SOUTH))
- visible_message("An egg is ready to hatch!")
- meat_counter -= 2
-
-/obj/effect/mob_spawn/human/ash_walker
- name = "ash walker egg"
- icon = 'icons/mob/lavaland/lavaland_monsters.dmi'
- icon_state = "large_egg"
- mob_species = /datum/species/lizard/ashwalker
- helmet = /obj/item/clothing/head/helmet/gladiator
- uniform = /obj/item/clothing/under/gladiator
- roundstart = FALSE
- death = FALSE
- anchored = 0
- density = 0
- flavour_text = {"You are an Ash Walker. Your tribe worships the necropolis. The wastes are sacred ground, its monsters a blessed bounty. You have seen lights in the distance though, the arrival of outsiders seeking to destroy the land. Fresh sacrifices."}
-
-/obj/effect/mob_spawn/human/ash_walker/special(mob/living/new_spawn)
- new_spawn.real_name = random_unique_lizard_name(gender)
- new_spawn << "Drag corpses to your nest to feed the young, and spawn more Ash Walkers. Bring glory to the tribe!"
- if(ishuman(new_spawn))
- var/mob/living/carbon/human/H = new_spawn
- H.underwear = "Nude"
- H.update_body()
-
-/obj/effect/mob_spawn/human/ash_walker/New()
- ..()
- var/area/A = get_area(src)
- if(A)
- notify_ghosts("An ash walker egg is ready to hatch in \the [A.name].", source = src, action=NOTIFY_ATTACK)
-
-//Wishgranter Exile
-
-/obj/effect/mob_spawn/human/exile
- name = "exile sleeper"
- mob_name = "Penitent Exile"
- icon = 'icons/obj/Cryogenic2.dmi'
- icon_state = "sleeper"
- roundstart = FALSE
- death = FALSE
- mob_species = /datum/species/shadow
- flavour_text = {"You are cursed! Many years ago you risked it all to reach the Wish Granter, siezing it's power for yourself and leaving your friends for dead.. Though your wish came true, it did so at a price, and you've been doomed to wander these wastes ever since. You seek only to atone now, to somehow redeem yourself, and finally be released. You've seen ships landing in the distance. Perhaps now is the time to make things right?"}
-
-/obj/effect/mob_spawn/human/exile/special(mob/living/new_spawn)
- new_spawn.real_name = "[new_spawn.real_name] ([rand(0,999)])"
- var/wish = rand(1,4)
- switch(wish)
- if(1)
- new_spawn << "You wished to kill, and kill you did. You've lost track of the number and murder long lost it's spark of excitement. You feel only regret."
- if(2)
- new_spawn << "You wished for unending wealth, but no amount of money was worth this existence. Maybe charity might redeem your soul?"
- if(3)
- new_spawn << "You wished for power. Little good it did you, cast out of the light. You are a king, but ruling over a miserable wasteland. You feel only remorse."
- if(4)
- new_spawn << "You wished for immortality, even as your friends lay dying behind you. No matter how many times you cast yourself into the lava, you awaken in this room again within a few days. You are overwhelmed with guilt."
-
//Free Golems
/obj/item/weapon/disk/design_disk/golem_shell
@@ -343,96 +106,3 @@
user << "You need at least ten sheets to finish a golem."
else
user << "You can't build a golem out of this kind of material."
-
-/obj/effect/mob_spawn/human/golem
- name = "completed golem shell"
- icon = 'icons/obj/wizard.dmi'
- icon_state = "construct"
- mob_species = /datum/species/golem
- roundstart = FALSE
- death = FALSE
- anchored = 0
- density = 0
- flavour_text = {"You are a Free Golem. Your family worships The Liberator. In his infinite and divine wisdom, he set your clan free to travel the stars with a single declaration; 'Yeah go do whatever.' Though you are bound to the one who created you, it is customary in your society to repeat those same words to newborn golems, so that no golem may ever be forced to serve again."}
-
-
-/obj/effect/mob_spawn/human/golem/New()
- ..()
- var/area/A = get_area(src)
- if(A)
- notify_ghosts("A golem shell has been completed in \the [A.name].", source = src, action=NOTIFY_ATTACK)
-
-/obj/effect/mob_spawn/human/golem/special(mob/living/new_spawn)
- var/golem_surname = pick(golem_names)
- // 3% chance that our golem has a human surname, because
- // cultural contamination
- if(prob(3))
- golem_surname = pick(last_names)
-
- var/datum/species/X = mob_species
- var/golem_forename = initial(X.id)
-
- // The id of golem species is either their material "diamond","gold",
- // or just "golem" for the plain ones. So we're using it for naming.
-
- if(golem_forename == "golem")
- golem_forename = "iron"
-
- new_spawn.real_name = "[capitalize(golem_forename)] [golem_surname]"
- // This means golems have names like Iron Forge, or Diamond Quarry
- // also a tiny chance of being called "Plasma Meme"
- // which is clearly a feature
-
- new_spawn << "Build golem shells in the autolathe, and feed refined mineral sheets to the shells to bring them to life! You are generally a peaceful group unless provoked."
- if(ishuman(new_spawn))
- var/mob/living/carbon/human/H = new_spawn
- H.set_cloned_appearance()
-
-
-/obj/effect/mob_spawn/human/golem/adamantine
- name = "golem sleeper"
- mob_name = "Free Golem"
- icon = 'icons/obj/Cryogenic2.dmi'
- icon_state = "sleeper"
- anchored = 1
- density = 1
- mob_species = /datum/species/golem/adamantine
-
-
-//Hermit
-
-/obj/effect/mob_spawn/human/hermit
- name = "hermit sleeper"
- mob_name = "Hermit"
- icon = 'icons/obj/lavaland/survival_pod.dmi'
- icon_state = "sleeper"
- roundstart = FALSE
- death = FALSE
- random = TRUE
- mob_species = /datum/species/human
- flavour_text = {"Doomed to walk this eternal hellscape due to means you barely remember at this point, every day is a struggle for survival as you barely scrape by in your makeshift housing."}
-
-/obj/effect/mob_spawn/human/hermit/New()
- var/arrpee = rand(1,4)
- switch(arrpee)
- if(1)
- flavour_text = {"You were the sole survivor of a raid-party's onslaught on a small orbital tradestation. You were forced to early-eject your pod to escape, the horrifed faces of the remaining crew when the raiders blew apart the room's airlock forever ingrained in your mind."}
- uniform = /obj/item/clothing/under/assistantformal
- shoes = /obj/item/clothing/shoes/sneakers/black
- back = /obj/item/weapon/storage/backpack
- if(2)
- flavour_text = {"A castaway from a far-off civilization, banished for crimes of heresy against the church. You awoke from hypersleep your pod crashlanding into this hellscape, only the essentials left to make a new life for yourself."}
- uniform = /obj/item/clothing/under/rank/prisoner
- shoes = /obj/item/clothing/shoes/sneakers/orange
- back = /obj/item/weapon/storage/backpack
- if(3)
- flavour_text = {"A runaway from the tyranny of Nanotrasen and everything all these damnned corporations stand for. From a metaphorical hell to a literal one, you do your best to put your station-life behind you to try and survive in this harsh land."}
- uniform = /obj/item/clothing/under/rank/medical
- suit = /obj/item/clothing/suit/toggle/labcoat
- back = /obj/item/weapon/storage/backpack/medic
- shoes = /obj/item/clothing/shoes/sneakers/black
- if(4)
- flavour_text = {"You weren't exactly the sharpest tool in the shed, hitting that big red button on the escape pod wondering what it'd do. Whether this 'special' attribute of yours is a defect of cloning or just genuine stupidity, the fact you've survived this long in a literal hellhole is enough to make Darwin roll in his grave."}
- uniform = /obj/item/clothing/under/color/grey/glorf
- shoes = /obj/item/clothing/shoes/sneakers/black
- back = /obj/item/weapon/storage/backpack
\ No newline at end of file
diff --git a/code/modules/ruins/objects_and_mobs/ash_walker_den.dm b/code/modules/ruins/objects_and_mobs/ash_walker_den.dm
new file mode 100644
index 00000000000..98e67d0e62d
--- /dev/null
+++ b/code/modules/ruins/objects_and_mobs/ash_walker_den.dm
@@ -0,0 +1,39 @@
+#define ASH_WALKER_SPAWN_THRESHOLD 2
+//The ash walker den consumes corpses or unconscious mobs to create ash walker eggs. For more info on those, check ghost_role_spawners.dm
+/mob/living/simple_animal/hostile/spawner/ash_walker
+ name = "ash walker nest"
+ desc = "A nest built around a necropolis tendril. The eggs seem to grow unnaturally fast..."
+ icon = 'icons/mob/nest.dmi'
+ icon_state = "ash_walker_nest"
+ icon_living = "ash_walker_nest"
+ faction = list("ashwalker")
+ health = 200
+ maxHealth = 200
+ loot = list(/obj/effect/gibspawner, /obj/item/device/assembly/signaler/anomaly)
+ del_on_death = 1
+ var/meat_counter
+
+/mob/living/simple_animal/hostile/spawner/ash_walker/Life()
+ ..()
+ if(!stat)
+ consume()
+ spawn_mob()
+
+/mob/living/simple_animal/hostile/spawner/ash_walker/proc/consume()
+ for(var/mob/living/H in view(src,1)) //Only for corpse right next to/on same tile
+ if(H.stat)
+ visible_message("Serrated tendrils eagerly pull [H] to [src], tearing the body apart as its blood seeps over the eggs.")
+ playsound(get_turf(src),'sound/magic/Demon_consume.ogg', 100, 1)
+ if(istype(H,/mob/living/simple_animal/hostile/megafauna/dragon))
+ meat_counter += 20
+ else
+ meat_counter ++
+ for(var/obj/item/W in H)
+ H.unEquip(W)
+ H.gib()
+
+/mob/living/simple_animal/hostile/spawner/ash_walker/spawn_mob()
+ if(meat_counter >= ASH_WALKER_SPAWN_THRESHOLD)
+ new /obj/effect/mob_spawn/human/ash_walker(get_step(src.loc, SOUTH))
+ visible_message("One of the eggs swells to an unnatural size and tumbles free. It's ready to hatch!")
+ meat_counter -= ASH_WALKER_SPAWN_THRESHOLD
diff --git a/code/modules/ruins/objects_and_mobs/necropolis_gate.dm b/code/modules/ruins/objects_and_mobs/necropolis_gate.dm
new file mode 100644
index 00000000000..ba9ce6555a4
--- /dev/null
+++ b/code/modules/ruins/objects_and_mobs/necropolis_gate.dm
@@ -0,0 +1,60 @@
+//The necropolis gate is used to call forth Legion from the Necropolis.
+/obj/structure/lavaland_door
+ name = "necropolis gate"
+ desc = "A tremendous and impossibly large gateway, bored into dense bedrock."
+ icon = 'icons/effects/96x96.dmi'
+ icon_state = "door"
+ anchored = 1
+ density = 1
+ opacity = 1
+ bound_width = 96
+ bound_height = 96
+ burn_state = LAVA_PROOF
+ luminosity = 1
+ var/boss = FALSE
+ var/is_anyone_home = FALSE
+
+/obj/structure/lavaland_door/attack_hand(mob/user)
+ for(var/mob/living/simple_animal/hostile/megafauna/legion/L in mob_list)
+ return
+ if(is_anyone_home)
+ return
+ var/safety = alert(user, "You think this might be a bad idea...", "Knock on the door?", "Proceed", "Abort")
+ if(safety == "Abort" || !in_range(src, user) || !src || is_anyone_home || user.incapacitated())
+ return
+ user.visible_message("[user] knocks on [src]...", "You tentatively knock on [src]...")
+ playsound(user.loc, 'sound/effects/shieldbash.ogg', 100, 1)
+ is_anyone_home = TRUE
+ sleep(50)
+ if(boss)
+ user << "There's no response."
+ is_anyone_home = FALSE
+ return 0
+ boss = TRUE
+ visible_message("Locks along the door begin clicking open from within...")
+ var/volume = 60
+ for(var/i in 1 to 3)
+ playsound(src, 'sound/items/Deconstruct.ogg', volume, 0)
+ volume += 20
+ sleep(10)
+ sleep(10)
+ visible_message("Something horrible emerges from the Necropolis!")
+ message_admins("[key_name_admin(user)] has summoned Legion!")
+ log_game("[key_name(user)] summoned Legion.")
+ for(var/mob/M in player_list)
+ if(M.z == z)
+ M << "Discordant whispers flood your mind in a thousand voices. Each one speaks your name, over and over. Something horrible has come."
+ M << 'sound/creatures/legion_spawn.ogg'
+ flash_color(M, flash_color = "#FF0000", flash_time = 50)
+ notify_ghosts("Legion has been summoned in the [get_area(src)]!", source = src, action = NOTIFY_ORBIT)
+ is_anyone_home = FALSE
+ new/mob/living/simple_animal/hostile/megafauna/legion(get_step(src.loc, SOUTH))
+
+/obj/structure/lavaland_door/singularity_pull()
+ return 0
+
+/obj/structure/lavaland_door/Destroy(force)
+ if(force)
+ . = ..()
+ else
+ return QDEL_HINT_LETMELIVE
diff --git a/code/modules/ruins/objects_and_mobs/sin_ruins.dm b/code/modules/ruins/objects_and_mobs/sin_ruins.dm
new file mode 100644
index 00000000000..ebb97ab7ba7
--- /dev/null
+++ b/code/modules/ruins/objects_and_mobs/sin_ruins.dm
@@ -0,0 +1,126 @@
+//These objects are used in the cardinal sin-themed ruins (i.e. Gluttony, Pride...)
+
+/obj/structure/cursed_slot_machine //Greed's slot machine: Used in the Greed ruin. Deals clone damage on each use, with a successful use giving a d20 of fate.
+ name = "greed's slot machine"
+ desc = "High stakes, high rewards."
+ icon = 'icons/obj/economy.dmi'
+ icon_state = "slots1"
+ anchored = 1
+ density = 1
+ var/win_prob = 5
+
+/obj/structure/cursed_slot_machine/attack_hand(mob/living/carbon/human/user)
+ if(!istype(user))
+ return
+ if(in_use)
+ return
+ in_use = TRUE
+ user.adjustCloneLoss(20)
+ if(user.stat)
+ user << "No... just one more try..."
+ user.gib()
+ else
+ user.visible_message("[user], pulls [src]'s lever with a glint in their eyes!", "You feel a draining as you pull the lever, but you \
+ know it'll be worth it.")
+ icon_state = "slots2"
+ playsound(src, 'sound/lavaland/cursed_slot_machine.ogg', 50, 0)
+ sleep(50)
+ icon_state = "slots1"
+ in_use = FALSE
+ if(prob(win_prob))
+ playsound(src, 'sound/lavaland/cursed_slot_machine_jackpot.ogg', 50, 0)
+ new/obj/structure/cursed_money(get_turf(src))
+ if(user)
+ user << "You've hit jackpot. Laughter echoes around you as your reward appears in the machine's place."
+ qdel(src)
+ else
+ if(user)
+ user << "Fucking machine! Must be rigged. Still... one more try couldn't hurt, right?"
+
+/obj/structure/cursed_money
+ name = "bag of money"
+ desc = "RICH! YES! YOU KNEW IT WAS WORTH IT! YOU'RE RICH! RICH! RICH!"
+ icon = 'icons/obj/storage.dmi'
+ icon_state = "moneybag"
+ anchored = FALSE
+ density = TRUE
+
+/obj/structure/cursed_money/New()
+ spawn(600)
+ if(src)
+ visible_message("[src] falls in on itself, canvas rotting away and contents vanishing.")
+ qdel(src)
+
+/obj/structure/cursed_money/attack_hand(mob/living/user)
+ user.visible_message("You open the bag...!\nAnd see a bag full of dice. Confused, you take one... and the bag vanishes.")
+ var/obj/item/weapon/dice/d20/fate/one_use/critical_fail = new(get_turf(user))
+ user.put_in_hands(critical_fail)
+ qdel(src)
+
+
+
+/obj/effect/gluttony //Gluttony's wall: Used in the Gluttony ruin. Only lets the overweight through.
+ name = "gluttony's wall"
+ desc = "Only those who truly indulge may pass."
+ anchored = 1
+ density = 1
+ icon_state = "blob"
+ icon = 'icons/mob/blob.dmi'
+ color = rgb(145, 150, 0)
+
+/obj/effect/gluttony/CanPass(atom/movable/mover, turf/target, height=0)//So bullets will fly over and stuff.
+ if(height==0)
+ return 1
+ if(istype(mover, /mob/living/carbon/human))
+ var/mob/living/carbon/human/H = mover
+ if(H.nutrition >= NUTRITION_LEVEL_FAT)
+ H.visible_message("[H] pushes through [src]!", "You've seen and eaten worse than this.")
+ return 1
+ else
+ H << "You're repulsed by even looking at [src]. Only a pig could force themselves to go through it."
+ else
+ return 0
+
+
+
+/obj/structure/mirror/magic/pride //Pride's mirror: Used in the Pride ruin.
+ name = "pride's mirror"
+ desc = "Pride cometh before the..."
+ icon_state = "magic_mirror"
+
+/obj/structure/mirror/magic/pride/curse(mob/user)
+ user.visible_message("The ground splits beneath [user] as their hand leaves the mirror!", \
+ "Perfect. Much better! Now nobody will be able to resist yo-")
+ var/turf/T = get_turf(user)
+ T.ChangeTurf(/turf/open/chasm/straight_down)
+ var/turf/open/chasm/straight_down/C = T
+ C.drop(user)
+
+//can't be bothered to do sloth right now, will make later
+
+/obj/item/weapon/knife/envy //Envy's knife: Found in the Envy ruin. Attackers take on the appearance of whoever they strike.
+ name = "envy's knife"
+ desc = "Their success will be yours."
+ icon = 'icons/obj/wizard.dmi'
+ icon_state = "render"
+ item_state = "render"
+ force = 18
+ throwforce = 10
+ w_class = 3
+ hitsound = 'sound/weapons/bladeslice.ogg'
+
+/obj/item/weapon/knife/envy/afterattack(atom/movable/AM, mob/living/carbon/human/user, proximity)
+ ..()
+ if(!proximity)
+ return
+ if(!istype(user))
+ return
+ if(istype(AM, /mob/living/carbon/human))
+ var/mob/living/carbon/human/H = AM
+ if(user.real_name != H.dna.real_name)
+ user.real_name = H.dna.real_name
+ H.dna.transfer_identity(user, transfer_SE=1)
+ user.updateappearance(mutcolor_update=1)
+ user.domutcheck()
+ user.visible_message("[user]'s appearance shifts into [H]'s!", \
+ "They think they're sooo much better than you. Not anymore, they won't.")
diff --git a/html/changelogs/AutoChangeLog-pr-18480.yml b/html/changelogs/AutoChangeLog-pr-18480.yml
new file mode 100644
index 00000000000..29734ec6951
--- /dev/null
+++ b/html/changelogs/AutoChangeLog-pr-18480.yml
@@ -0,0 +1,6 @@
+author: "Kor and Iamgoofball"
+delete-after: True
+changes:
+ - rscadd: "Miners can now purchase fulton extraction packs."
+ - rscadd: "Miners can now purchase fulton medivac packs."
+ - rscadd: "Two new fulton related bundles are available for purchase with vouchers."
diff --git a/html/changelogs/AutoChangeLog-pr-18642.yml b/html/changelogs/AutoChangeLog-pr-18642.yml
new file mode 100644
index 00000000000..42a710505f7
--- /dev/null
+++ b/html/changelogs/AutoChangeLog-pr-18642.yml
@@ -0,0 +1,7 @@
+author: "Joan"
+delete-after: True
+changes:
+ - tweak: "Assassin holoparasite attack damage increased from 13 to 15, stealth cooldown decreased from 20 seconds to 16 seconds."
+ - tweak: "Charger holoparasite charge cooldown decreased from 5 seconds to 4 seconds."
+ - tweak: "Chaos holoparasite attack damage decreased from 10 to 7, range decreased from 10 to 7."
+ - tweak: "Lightning holoparasite attack damage increased from 5 to 7, chain damage increased by 33%."
diff --git a/icons/effects/224x224.dmi b/icons/effects/224x224.dmi
index f6ef50c8f0f..858e69fdd16 100644
Binary files a/icons/effects/224x224.dmi and b/icons/effects/224x224.dmi differ
diff --git a/icons/mob/alienqueen.dmi b/icons/mob/alienqueen.dmi
index 2b3b23d6c64..dfe9c7fa619 100644
Binary files a/icons/mob/alienqueen.dmi and b/icons/mob/alienqueen.dmi differ
diff --git a/icons/obj/fulton.dmi b/icons/obj/fulton.dmi
new file mode 100644
index 00000000000..c56c275b3b1
Binary files /dev/null and b/icons/obj/fulton.dmi differ
diff --git a/icons/obj/fulton_balloon.dmi b/icons/obj/fulton_balloon.dmi
new file mode 100644
index 00000000000..5a1fa98e148
Binary files /dev/null and b/icons/obj/fulton_balloon.dmi differ
diff --git a/icons/obj/lavaland/spawners.dmi b/icons/obj/lavaland/spawners.dmi
new file mode 100644
index 00000000000..42fdc988add
Binary files /dev/null and b/icons/obj/lavaland/spawners.dmi differ
diff --git a/interface/stylesheet.dm b/interface/stylesheet.dm
index 8b248d523b5..515a1943645 100644
--- a/interface/stylesheet.dm
+++ b/interface/stylesheet.dm
@@ -53,6 +53,7 @@ h1.alert, h2.alert {color: #000000;}
.userdanger {color: #ff0000; font-weight: bold; font-size: 3;}
.danger {color: #ff0000;}
.warning {color: #ff0000; font-style: italic;}
+.boldwarning {color: #ff0000; font-style: italic; font-weight: bold}
.announce {color: #228b22; font-weight: bold;}
.boldannounce {color: #ff0000; font-weight: bold;}
.greenannounce {color: #00ff00; font-weight: bold;}
diff --git a/sound/creatures/legion_spawn.ogg b/sound/creatures/legion_spawn.ogg
new file mode 100644
index 00000000000..9fce6dec4c6
Binary files /dev/null and b/sound/creatures/legion_spawn.ogg differ
diff --git a/sound/items/fulext_deploy.wav b/sound/items/fulext_deploy.wav
new file mode 100644
index 00000000000..9fbcb7e3f85
Binary files /dev/null and b/sound/items/fulext_deploy.wav differ
diff --git a/sound/items/fultext_launch.wav b/sound/items/fultext_launch.wav
new file mode 100644
index 00000000000..a623a89ada4
Binary files /dev/null and b/sound/items/fultext_launch.wav differ
diff --git a/sound/lavaland/ash_storm_end.ogg b/sound/lavaland/ash_storm_end.ogg
new file mode 100644
index 00000000000..f9b01453dda
Binary files /dev/null and b/sound/lavaland/ash_storm_end.ogg differ
diff --git a/sound/lavaland/ash_storm_start.ogg b/sound/lavaland/ash_storm_start.ogg
new file mode 100644
index 00000000000..4b9bebffd08
Binary files /dev/null and b/sound/lavaland/ash_storm_start.ogg differ
diff --git a/sound/lavaland/ash_storm_windup.ogg b/sound/lavaland/ash_storm_windup.ogg
new file mode 100644
index 00000000000..a9f0fa3270e
Binary files /dev/null and b/sound/lavaland/ash_storm_windup.ogg differ
diff --git a/sound/lavaland/cursed_slot_machine.ogg b/sound/lavaland/cursed_slot_machine.ogg
new file mode 100644
index 00000000000..1e1b545021d
Binary files /dev/null and b/sound/lavaland/cursed_slot_machine.ogg differ
diff --git a/sound/lavaland/cursed_slot_machine_jackpot.ogg b/sound/lavaland/cursed_slot_machine_jackpot.ogg
new file mode 100644
index 00000000000..83a1c0bee70
Binary files /dev/null and b/sound/lavaland/cursed_slot_machine_jackpot.ogg differ
diff --git a/tgstation.dme b/tgstation.dme
index b0ab0ac29f6..94ba8781c4a 100644
--- a/tgstation.dme
+++ b/tgstation.dme
@@ -734,6 +734,8 @@
#include "code\game\objects\structures\false_walls.dm"
#include "code\game\objects\structures\fireaxe.dm"
#include "code\game\objects\structures\flora.dm"
+#include "code\game\objects\structures\fluff.dm"
+#include "code\game\objects\structures\ghost_role_spawners.dm"
#include "code\game\objects\structures\girders.dm"
#include "code\game\objects\structures\grille.dm"
#include "code\game\objects\structures\guncase.dm"
@@ -1224,6 +1226,7 @@
#include "code\modules\lighting\lighting_system.dm"
#include "code\modules\mining\abandoned_crates.dm"
#include "code\modules\mining\equipment.dm"
+#include "code\modules\mining\fulton.dm"
#include "code\modules\mining\machine_input_output_plates.dm"
#include "code\modules\mining\machine_processing.dm"
#include "code\modules\mining\machine_redemption.dm"
@@ -1682,6 +1685,9 @@
#include "code\modules\research\xenobiology\xenobiology.dm"
#include "code\modules\ruins\lavaland_ruin_code.dm"
#include "code\modules\ruins\ruin_areas.dm"
+#include "code\modules\ruins\objects_and_mobs\ash_walker_den.dm"
+#include "code\modules\ruins\objects_and_mobs\necropolis_gate.dm"
+#include "code\modules\ruins\objects_and_mobs\sin_ruins.dm"
#include "code\modules\security_levels\keycard_authentication.dm"
#include "code\modules\security_levels\security_levels.dm"
#include "code\modules\shuttle\assault_pod.dm"