diff --git a/code/game/objects/effects/landmarks.dm b/code/game/objects/effects/landmarks.dm
index 851a041aab..11dd5a0c39 100644
--- a/code/game/objects/effects/landmarks.dm
+++ b/code/game/objects/effects/landmarks.dm
@@ -513,3 +513,9 @@ INITIALIZE_IMMEDIATE(/obj/effect/landmark/start/new_player)
/obj/effect/landmark/stationroom/lavaland/station
templates = list("Public Mining Base" = 3)
icon = 'icons/rooms/Lavaland/Mining.dmi'
+
+// handled in portals.dm, id connected to one-way portal
+/obj/effect/landmark/portal_exit
+ name = "portal exit"
+ icon_state = "portal_exit"
+ var/id
diff --git a/code/game/objects/effects/portals.dm b/code/game/objects/effects/portals.dm
index 553b3245a1..504b931685 100644
--- a/code/game/objects/effects/portals.dm
+++ b/code/game/objects/effects/portals.dm
@@ -29,6 +29,7 @@
var/allow_anchored = FALSE
var/innate_accuracy_penalty = 0
var/last_effect = 0
+ var/force_teleport = FALSE
/obj/effect/portal/anom
name = "wormhole"
@@ -162,7 +163,7 @@
no_effect = TRUE
else
last_effect = world.time
- if(do_teleport(M, real_target, innate_accuracy_penalty, no_effects = no_effect, channel = teleport_channel))
+ if(do_teleport(M, real_target, innate_accuracy_penalty, no_effects = no_effect, channel = teleport_channel, forced = force_teleport))
if(istype(M, /obj/item/projectile))
var/obj/item/projectile/P = M
P.ignore_source_check = TRUE
diff --git a/code/game/objects/items/puzzle_pieces.dm b/code/game/objects/items/puzzle_pieces.dm
index 4b92921d08..96256ccaa5 100644
--- a/code/game/objects/items/puzzle_pieces.dm
+++ b/code/game/objects/items/puzzle_pieces.dm
@@ -120,11 +120,6 @@
var/reward = /obj/item/reagent_containers/food/snacks/cookie
var/claimed = FALSE
-/obj/item/pressure_plate/hologrid/Initialize()
- . = ..()
-
- AddElement(/datum/element/undertile, tile_overlay = tile_overlay) //we remove use_anchor here, so it ALWAYS stays anchored
-
/obj/item/pressure_plate/hologrid/examine(mob/user)
. = ..()
if(claimed)
@@ -145,3 +140,8 @@
trigger()
sleep(15)
qdel(AM)
+
+// snowflake code until undertile elements
+/obj/item/pressure_plate/hologrid/hide()
+ . = ..()
+ anchored = TRUE
diff --git a/code/game/turfs/simulated/floor/plating/asteroid.dm b/code/game/turfs/simulated/floor/plating/asteroid.dm
index 456fd72a1f..838157f64d 100644
--- a/code/game/turfs/simulated/floor/plating/asteroid.dm
+++ b/code/game/turfs/simulated/floor/plating/asteroid.dm
@@ -151,6 +151,8 @@
var/list/flora_spawn_list
/// Terrain that can spawn in the tunnel, weighted list.
var/list/terrain_spawn_list
+ /// Turf type to choose when spawning in tunnel at 1% chance, weighted list
+ var/list/choose_turf_type
/// if the tunnel should keep being created
var/sanity = 1
/// Cave direction to move
@@ -164,6 +166,7 @@
/// The non-cave creating type
var/data_having_type = /turf/open/floor/plating/asteroid/airless/cave/has_data
/// Option tunnel width, wegihted list
+ var/list/pick_tunnel_width
turf_type = /turf/open/floor/plating/asteroid/airless
/turf/open/floor/plating/asteroid/airless/cave/has_data //subtype for producing a tunnel with given data
@@ -323,10 +326,7 @@
/// Spawns the floor of the tunnel and any type of structure or mob it can have
/turf/open/floor/plating/asteroid/airless/cave/proc/SpawnFloor(turf/T)
- if(!T)
- sanity = 0
- return
- if(isarea(T.loc))
+ var/area/A = T.loc
if(!A.tunnel_allowed)
sanity = 0
return
diff --git a/code/modules/assembly/signaler.dm b/code/modules/assembly/signaler.dm
index cee0a9054c..c5e2cbb422 100644
--- a/code/modules/assembly/signaler.dm
+++ b/code/modules/assembly/signaler.dm
@@ -90,7 +90,7 @@
. = TRUE
update_icon()
-
+
/obj/item/assembly/signaler/attackby(obj/item/W, mob/user, params)
if(issignaler(W))
var/obj/item/assembly/signaler/signaler2 = W
@@ -162,7 +162,6 @@
return
return ..(signal)
-
// Embedded signaller used in anomalies.
/obj/item/assembly/signaler/anomaly
name = "anomaly core"
@@ -179,12 +178,53 @@
return FALSE
if(signal.data["code"] != code)
return FALSE
+ if(suicider)
+ manual_suicide(suicider)
for(var/obj/effect/anomaly/A in get_turf(src))
A.anomalyNeutralize()
return TRUE
-/obj/item/assembly/signaler/anomaly/attack_self()
- return
+/obj/item/assembly/signaler/anomaly/manual_suicide(mob/living/carbon/user)
+ user.visible_message("[user]'s [src] is reacting to the radio signal, warping [user.p_their()] body!")
+ user.set_suicide(TRUE)
+ user.suicide_log()
+ user.gib()
+
+/obj/item/assembly/signaler/anomaly/attackby(obj/item/I, mob/user, params)
+ if(I.tool_behaviour == TOOL_ANALYZER)
+ to_chat(user, "Analyzing... [src]'s stabilized field is fluctuating along frequency [format_frequency(frequency)], code [code].")
+ ..()
+
+//Anomaly cores
+/obj/item/assembly/signaler/anomaly/pyro
+ name = "\improper pyroclastic anomaly core"
+ desc = "The neutralized core of a pyroclastic anomaly. It feels warm to the touch. It'd probably be valuable for research."
+ icon_state = "pyro core"
+ anomaly_type = /obj/effect/anomaly/pyro
+
+/obj/item/assembly/signaler/anomaly/grav
+ name = "\improper gravitational anomaly core"
+ desc = "The neutralized core of a gravitational anomaly. It feels much heavier than it looks. It'd probably be valuable for research."
+ icon_state = "grav core"
+ anomaly_type = /obj/effect/anomaly/grav
+
+/obj/item/assembly/signaler/anomaly/flux
+ name = "\improper flux anomaly core"
+ desc = "The neutralized core of a flux anomaly. Touching it makes your skin tingle. It'd probably be valuable for research."
+ icon_state = "flux core"
+ anomaly_type = /obj/effect/anomaly/flux
+
+/obj/item/assembly/signaler/anomaly/bluespace
+ name = "\improper bluespace anomaly core"
+ desc = "The neutralized core of a bluespace anomaly. It keeps phasing in and out of view. It'd probably be valuable for research."
+ icon_state = "anomaly core"
+ anomaly_type = /obj/effect/anomaly/bluespace
+
+/obj/item/assembly/signaler/anomaly/vortex
+ name = "\improper vortex anomaly core"
+ desc = "The neutralized core of a vortex anomaly. It won't sit still, as if some invisible force is acting on it. It'd probably be valuable for research."
+ icon_state = "vortex core"
+ anomaly_type = /obj/effect/anomaly/bhole
/obj/item/assembly/signaler/cyborg
diff --git a/code/modules/mob/living/simple_animal/hostile/retaliate/clown.dm b/code/modules/mob/living/simple_animal/hostile/retaliate/clown.dm
index ca14d4ae67..c46df9e77d 100644
--- a/code/modules/mob/living/simple_animal/hostile/retaliate/clown.dm
+++ b/code/modules/mob/living/simple_animal/hostile/retaliate/clown.dm
@@ -1,14 +1,14 @@
/mob/living/simple_animal/hostile/retaliate/clown
name = "Clown"
desc = "A denizen of clown planet."
- icon = 'icons/mob/simple_human.dmi'
+ icon = 'icons/mob/clown_mobs.dmi'
icon_state = "clown"
icon_living = "clown"
icon_dead = "clown_dead"
icon_gib = "clown_gib"
+ health_doll_icon = "clown" //if >32x32, it will use this generic. for all the huge clown mobs that subtype from this
mob_biotypes = MOB_ORGANIC|MOB_HUMANOID
turns_per_move = 5
- response_help = "pokes"
response_disarm = "gently pushes aside"
response_harm = "robusts"
speak = list("HONK", "Honk!", "Welcome to clown planet!")
@@ -21,7 +21,6 @@
harm_intent_damage = 8
melee_damage_lower = 10
melee_damage_upper = 10
- attacktext = "attacks"
attack_sound = 'sound/items/bikehorn.ogg'
obj_damage = 0
environment_smash = ENVIRONMENT_SMASH_NONE
@@ -32,15 +31,246 @@
minbodytemp = 270
maxbodytemp = 370
unsuitable_atmos_damage = 10
-
- do_footstep = TRUE
+ footstep_type = FOOTSTEP_MOB_SHOE
+ var/banana_time = 0 // If there's no time set it won't spawn.
+ var/banana_type = /obj/item/grown/bananapeel
+ var/attack_reagent
/mob/living/simple_animal/hostile/retaliate/clown/handle_temperature_damage()
if(bodytemperature < minbodytemp)
adjustBruteLoss(10)
+ throw_alert("temp", /obj/screen/alert/cold, 2)
else if(bodytemperature > maxbodytemp)
adjustBruteLoss(15)
+ throw_alert("temp", /obj/screen/alert/hot, 3)
+ else
+ clear_alert("temp")
/mob/living/simple_animal/hostile/retaliate/clown/attack_hand(mob/living/carbon/human/M)
..()
- playsound(src.loc, 'sound/items/bikehorn.ogg', 50, 1)
+ playsound(src.loc, 'sound/items/bikehorn.ogg', 50, TRUE)
+
+/mob/living/simple_animal/hostile/retaliate/clown/Life()
+ . = ..()
+ if(banana_time && banana_time < world.time)
+ var/turf/T = get_turf(src)
+ var/list/adjacent = T.GetAtmosAdjacentTurfs(1)
+ new banana_type(pick(adjacent))
+ banana_time = world.time + rand(30,60)
+
+/mob/living/simple_animal/hostile/retaliate/clown/AttackingTarget()
+ . = ..()
+ if(attack_reagent && . && isliving(target))
+ var/mob/living/L = target
+ if(L.reagents)
+ L.reagents.add_reagent(attack_reagent, rand(1,5))
+
+/mob/living/simple_animal/hostile/retaliate/clown/lube
+ name = "Living Lube"
+ desc = "A puddle of lube brought to life by the honkmother."
+ icon_state = "lube"
+ icon_living = "lube"
+ turns_per_move = 1
+ response_help = "dips a finger into"
+ response_disarm = "gently scoops and pours aside"
+ emote_see = list("bubbles", "oozes")
+ loot = list(/obj/item/clothing/mask/gas/clown_hat, /obj/effect/particle_effect/foam)
+
+/mob/living/simple_animal/hostile/retaliate/clown/lube/Initialize()
+ . = ..()
+ AddElement(/datum/element/snailcrawl)
+
+/mob/living/simple_animal/hostile/retaliate/clown/banana
+ name = "Clownana"
+ desc = "A fusion of clown and banana DNA birthed from a botany experiment gone wrong."
+ icon_state = "banana tree"
+ icon_living = "banana tree"
+ response_disarm = "peels"
+ response_harm = "peels"
+ turns_per_move = 1
+ speak = list("HONK", "Honk!", "YA-HONK!!!")
+ emote_see = list("honks", "bites into the banana", "plucks a banana off its head", "photosynthesizes")
+ maxHealth = 120
+ health = 120
+ speed = -10
+ loot = list(/obj/item/clothing/mask/gas/clown_hat, /obj/effect/gibspawner/human, /obj/item/soap, /obj/item/seeds/banana)
+ banana_time = 20
+
+/mob/living/simple_animal/hostile/retaliate/clown/honkling
+ name = "Honkling"
+ desc = "A divine being sent by the Honkmother to spread joy. It's not dangerous, but it's a bit of a nuisance."
+ icon_state = "honkling"
+ icon_living = "honkling"
+ turns_per_move = 1
+ speed = -10
+ harm_intent_damage = 1
+ melee_damage_lower = 1
+ melee_damage_upper = 1
+ attacktext = "cheers up"
+ loot = list(/obj/item/clothing/mask/gas/clown_hat, /obj/effect/gibspawner/human, /obj/item/soap, /obj/item/seeds/banana/bluespace)
+ banana_type = /obj/item/grown/bananapeel
+ attack_reagent = /datum/reagent/consumable/laughter
+
+/mob/living/simple_animal/hostile/retaliate/clown/fleshclown
+ name = "Fleshclown"
+ desc = "A being forged out of the pure essence of pranking, cursed into existence by a cruel maker."
+ icon_state = "fleshclown"
+ icon_living = "fleshclown"
+ response_help = "reluctantly pokes"
+ response_disarm = "sinks his hands into the spongy flesh of"
+ response_harm = "cleanses the world of"
+ speak = list("HONK", "Honk!", "I didn't ask for this", "I feel constant and horrible pain", "YA-HONK!!!", "this body is a merciless and unforgiving prison", "I was born out of mirthful pranking but I live in suffering")
+ emote_see = list("honks", "sweats", "jiggles", "contemplates its existence")
+ speak_chance = 5
+ dextrous = TRUE
+ ventcrawler = VENTCRAWLER_ALWAYS
+ maxHealth = 140
+ health = 140
+ speed = -5
+ melee_damage_upper = 15
+ attacktext = "limply slaps"
+ obj_damage = 5
+ loot = list(/obj/item/clothing/suit/hooded/bloated_human, /obj/item/clothing/mask/gas/clown_hat, /obj/effect/gibspawner/human, /obj/item/soap)
+
+/mob/living/simple_animal/hostile/retaliate/clown/longface
+ name = "Longface"
+ desc = "Often found walking into the bar."
+ icon_state = "long face"
+ icon_living = "long face"
+ move_resist = INFINITY
+ turns_per_move = 10
+ response_help = "tries to awkwardly hug"
+ response_disarm = "pushes the unwieldy frame of"
+ response_harm = "tries to shut up"
+ speak = list("YA-HONK!!!")
+ emote_see = list("honks", "squeaks")
+ speak_chance = 60
+ maxHealth = 150
+ health = 150
+ pixel_x = -16
+ speed = 10
+ harm_intent_damage = 5
+ melee_damage_lower = 5
+ attacktext = "YA-HONKs"
+ loot = list(/obj/item/clothing/mask/gas/clown_hat, /obj/effect/gibspawner/human, /obj/item/soap)
+
+/mob/living/simple_animal/hostile/retaliate/clown/clownhulk
+ name = "Honk Hulk"
+ desc = "A cruel and fearsome clown. Don't make him angry."
+ icon_state = "honkhulk"
+ icon_living = "honkhulk"
+ move_resist = INFINITY
+ response_help = "tries desperately to appease"
+ response_disarm = "foolishly pushes"
+ response_harm = "angers"
+ speak = list("HONK", "Honk!", "HAUAUANK!!!", "GUUURRRRAAAHHH!!!")
+ emote_see = list("honks", "sweats", "grunts")
+ speak_chance = 5
+ maxHealth = 400
+ health = 400
+ pixel_x = -16
+ speed = 2
+ harm_intent_damage = 15
+ melee_damage_lower = 15
+ melee_damage_upper = 20
+ attacktext = "pummels"
+ obj_damage = 30
+ environment_smash = ENVIRONMENT_SMASH_WALLS
+ loot = list(/obj/item/clothing/mask/gas/clown_hat, /obj/effect/gibspawner/human, /obj/item/soap)
+
+/mob/living/simple_animal/hostile/retaliate/clown/clownhulk/chlown
+ name = "Chlown"
+ desc = "A real lunkhead who somehow gets all the girls."
+ icon_state = "chlown"
+ icon_living = "chlown"
+ response_help = "submits to"
+ response_disarm = "tries to assert dominance over"
+ response_harm = "makes a weak beta attack at"
+ speak = list("HONK", "Honk!", "Bruh", "cheeaaaahhh?")
+ emote_see = list("asserts his dominance", "emasculates everyone implicitly")
+ maxHealth = 500
+ health = 500
+ speed = -2
+ armour_penetration = 20
+ attacktext = "steals the girlfriend of"
+ attack_sound = 'sound/items/airhorn2.ogg'
+ loot = list(/obj/item/clothing/mask/gas/clown_hat, /obj/effect/gibspawner/human, /obj/effect/particle_effect/foam, /obj/item/soap)
+
+/mob/living/simple_animal/hostile/retaliate/clown/clownhulk/honcmunculus
+ name = "Honkmunculus"
+ desc = "A slender wiry figure of alchemical origin."
+ icon_state = "honkmunculus"
+ icon_living = "honkmunculus"
+ response_help = "skeptically pokes"
+ response_disarm = "pushes the unwieldy frame of"
+ speak = list("honk")
+ emote_see = list("squirms", "writhes")
+ speak_chance = 1
+ maxHealth = 200
+ health = 200
+ speed = -5
+ harm_intent_damage = 5
+ melee_damage_lower = 5
+ melee_damage_upper = 10
+ attacktext = "ferociously mauls"
+ environment_smash = ENVIRONMENT_SMASH_NONE
+ loot = list(/obj/item/clothing/mask/gas/clown_hat, /obj/effect/gibspawner/xeno/bodypartless, /obj/effect/particle_effect/foam, /obj/item/soap)
+ attack_reagent = /datum/reagent/peaceborg/confuse
+
+/mob/living/simple_animal/hostile/retaliate/clown/clownhulk/destroyer
+ name = "The Destroyer"
+ desc = "An ancient being born of arcane honking."
+ icon_state = "destroyer"
+ icon_living = "destroyer"
+ response_disarm = "bounces off of"
+ response_harm = "bounces off of"
+ speak = list("HONK!!!", "The Honkmother is merciful, so I must act out her wrath.", "parce mihi ad beatus honkmother placet mihi ut peccata committere,", "DIE!!!")
+ maxHealth = 400
+ health = 400
+ speed = 5
+ harm_intent_damage = 30
+ melee_damage_lower = 20
+ melee_damage_upper = 40
+ armour_penetration = 30
+ stat_attack = UNCONSCIOUS
+ attacktext = "acts out divine vengeance on"
+ obj_damage = 50
+ environment_smash = ENVIRONMENT_SMASH_RWALLS
+ loot = list(/obj/item/clothing/mask/gas/clown_hat, /obj/effect/gibspawner/human, /obj/effect/particle_effect/foam, /obj/item/soap)
+
+/mob/living/simple_animal/hostile/retaliate/clown/mutant
+ name = "Unknown"
+ desc = "Kill it for its own sake."
+ icon_state = "mutant"
+ icon_living = "mutant"
+ move_resist = INFINITY
+ turns_per_move = 10
+ response_help = "reluctantly sinks a finger into"
+ response_disarm = "squishes into"
+ response_harm = "squishes into"
+ speak = list("aaaaaahhhhuuhhhuhhhaaaaa", "AAAaaauuuaaAAAaauuhhh", "huuuuuh... hhhhuuuooooonnnnkk", "HuaUAAAnKKKK")
+ emote_see = list("squirms", "writhes", "pulsates", "froths", "oozes")
+ speak_chance = 10
+ maxHealth = 130
+ health = 130
+ pixel_x = -16
+ speed = -5
+ harm_intent_damage = 10
+ melee_damage_lower = 10
+ melee_damage_upper = 20
+ attacktext = "awkwardly flails at"
+ loot = list(/obj/item/clothing/mask/gas/clown_hat, /obj/effect/gibspawner/xeno/bodypartless, /obj/item/soap, /obj/effect/gibspawner/generic, /obj/effect/gibspawner/generic/animal, /obj/effect/gibspawner/human/bodypartless, /obj/effect/gibspawner/human)
+
+/mob/living/simple_animal/hostile/retaliate/clown/mutant/blob
+ name = "Something that was once a clown"
+ desc = "A grotesque bulging figure far mutated from it's original state."
+ icon_state = "blob"
+ icon_living = "blob"
+ speak = list("hey, buddy", "HONK!!!", "H-h-h-H-HOOOOONK!!!!", "HONKHONKHONK!!!", "HEY, BUCKO, GET BACK HERE!!!", "HOOOOOOOONK!!!")
+ emote_see = list("jiggles", "wobbles")
+ health = 130
+ mob_size = MOB_SIZE_LARGE
+ speed = 20
+ attacktext = "bounces off of"
+ loot = list(/obj/item/clothing/mask/gas/clown_hat, /obj/effect/gibspawner/xeno/bodypartless, /obj/effect/particle_effect/foam, /obj/item/soap, /obj/effect/gibspawner/generic, /obj/effect/gibspawner/generic/animal, /obj/effect/gibspawner/human/bodypartless, /obj/effect/gibspawner/human)
+ attack_reagent = /datum/reagent/toxin/mindbreaker
diff --git a/icons/mob/animal.dmi b/icons/mob/animal.dmi
index 988ae1a30f..13f97d3761 100644
Binary files a/icons/mob/animal.dmi and b/icons/mob/animal.dmi differ
diff --git a/icons/mob/clown_mobs.dmi b/icons/mob/clown_mobs.dmi
new file mode 100644
index 0000000000..803a99cd7a
Binary files /dev/null and b/icons/mob/clown_mobs.dmi differ
diff --git a/icons/obj/assemblies/new_assemblies.dmi b/icons/obj/assemblies/new_assemblies.dmi
index fa0c138d21..2283b84c43 100644
Binary files a/icons/obj/assemblies/new_assemblies.dmi and b/icons/obj/assemblies/new_assemblies.dmi differ