Ports TG Icemoon framework and map (#49680) (#12002)

* ports all the tg junk for icemoon, not yet changed to make it all compile

* fixes

* fixes

* fixes

* fixes

* fixes

* new stuff

* whew

* fixes

* it compiles, now to fix the maps

* fixes the maps

* fixes solars + removes the space tiles in the toxins burn chamber

* nukes the SpawnTerrain proc used for tg geysers

* linter fix

* fix

* fixes the non matching turf atmos (hopefully)

* more mapping fixes

* dmm2tgm

* unfucks changeturf for the more_caves

* fixes the volanic subtypes of the other thing

* fixes the stupid fucking tile placing list

* some map fixes, fixes the station_ruin loader shitting out errors this commit took 2 hours of my fucking life

* fixes a bunch of mismatch atmos in ruins

* fixes wendigo cave having no air

* backwards couch backwards couch

* fixes the SM up

* wendigos can't runtime when butchering if you can't butcher them 😎

* makes the wendigo fight have the same atmos as the surrounding icemoon

* Tweaks atmos mixture from o2=22;n2=82;TEMP=180 to o2=18;n2=63;TEMP=180, making lavaland weapons actually work

* makes the wendigo screech shake not completely aids

* fixes snowlegion portals dropping proper legions instead of skeles

* brings the engioutpost ruin over as well

* whoopps

* empty commit to reroll bots

* Fixes pirates, ops, the mining base, and gives pirates and ops drills

* fixes lone ops and ninjas

* fixes the snowed plating getting fucked when tiles are placed on it

* removes some OP junk from the wabbajack pool (aka removes non-antag headslugs again)

* more bug fixes

* empty commit to reroll bots

* hopefully finally kills the active turfs on the library ruin

Co-authored-by: kevinz000 <2003111+kevinz000@users.noreply.github.com>
This commit is contained in:
Detective-Google
2020-05-07 07:46:16 -05:00
committed by GitHub
parent e24bda9a9f
commit bd37d45334
123 changed files with 277438 additions and 220 deletions

View File

@@ -161,10 +161,14 @@
#define ATMOS_TANK_O2 "o2=100000;TEMP=293.15"
#define ATMOS_TANK_N2 "n2=100000;TEMP=293.15"
#define ATMOS_TANK_AIRMIX "o2=2644;n2=10580;TEMP=293.15"
//LAVALAND
#define LAVALAND_EQUIPMENT_EFFECT_PRESSURE 50 //what pressure you have to be under to increase the effect of equipment meant for lavaland
#define LAVALAND_DEFAULT_ATMOS "o2=14;n2=23;TEMP=300"
//SNOSTATION
#define ICEMOON_DEFAULT_ATMOS "o2=17;n2=63;TEMP=180"
//ATMOSIA GAS MONITOR TAGS
#define ATMOS_GAS_MONITOR_INPUT_O2 "o2_in"
#define ATMOS_GAS_MONITOR_OUTPUT_O2 "o2_out"

View File

@@ -110,7 +110,8 @@
#define COMSIG_TURF_MULTIZ_NEW "turf_multiz_new" //from base of turf/New(): (turf/source, direction)
// /atom/movable signals
#define COMSIG_MOVABLE_PRE_MOVE "movable_pre_move" //from base of atom/movable/Moved(): (/atom)
#define COMSIG_MOVABLE_PRE_MOVE "movable_pre_move" ///from base of atom/movable/Moved(): (/atom)
#define COMPONENT_MOVABLE_BLOCK_PRE_MOVE 1
#define COMSIG_MOVABLE_MOVED "movable_moved" //from base of atom/movable/Moved(): (/atom, dir)
#define COMSIG_MOVABLE_CROSS "movable_cross" //from base of atom/movable/Cross(): (/atom/movable)
#define COMSIG_MOVABLE_CROSSED "movable_crossed" //from base of atom/movable/Crossed(): (/atom/movable)

View File

@@ -174,7 +174,10 @@ GLOBAL_LIST_INIT(clawfootmob, typecacheof(list(
/mob/living/simple_animal/pet/fox,
/mob/living/simple_animal/chicken,
/mob/living/simple_animal/hostile/bear,
/mob/living/simple_animal/hostile/jungle/mega_arachnid
/mob/living/simple_animal/hostile/jungle/mega_arachnid,
/mob/living/simple_animal/hostile/asteroid/ice_whelp,
/mob/living/simple_animal/hostile/asteroid/wolf,
/mob/living/simple_animal/hostile/asteroid/polarbear
)))
GLOBAL_LIST_INIT(barefootmob, typecacheof(list(

View File

@@ -38,8 +38,15 @@ require only minor tweaks.
#define ZTRAIT_VR "Virtual Reality"
#define ZTRAIT_SPACE_RUINS "Space Ruins"
#define ZTRAIT_LAVA_RUINS "Lava Ruins"
#define ZTRAIT_ICE_RUINS "Ice Ruins"
#define ZTRAIT_ICE_RUINS_UNDERGROUND "Ice Ruins Underground"
#define ZTRAIT_ISOLATED_RUINS "Isolated Ruins" //Placing ruins on z levels with this trait will use turf reservation instead of usual placement.
//boolean - weather types that occur on the level
#define ZTRAIT_SNOWSTORM "Weather_Snowstorm"
#define ZTRAIT_ASHSTORM "Weather_Ashstorm"
#define ZTRAIT_ACIDRAIN "Weather_Acidrain"
// number - bombcap is multiplied by this before being applied to bombs
#define ZTRAIT_BOMBCAP_MULTIPLIER "Bombcap Multiplier"
@@ -68,6 +75,7 @@ require only minor tweaks.
#define ZTRAITS_SPACE list(ZTRAIT_LINKAGE = CROSSLINKED, ZTRAIT_SPACE_RUINS = TRUE)
#define ZTRAITS_LAVALAND list(\
ZTRAIT_MINING = TRUE, \
ZTRAIT_ASHSTORM = TRUE, \
ZTRAIT_LAVA_RUINS = TRUE, \
ZTRAIT_BOMBCAP_MULTIPLIER = 5, \
ZTRAIT_BASETURF = /turf/open/lava/smooth/lava_land_surface)

View File

@@ -265,6 +265,7 @@
#define WIZARD_AGE_MIN 30 //youngest a wizard can be
#define APPRENTICE_AGE_MIN 29 //youngest an apprentice can be
#define SHOES_SLOWDOWN 0 //How much shoes slow you down by default. Negative values speed you up
#define SHOES_SPEED_SLIGHT SHOES_SLOWDOWN - 1 // slightest speed boost to movement
#define POCKET_STRIP_DELAY 40 //time taken (in deciseconds) to search somebody's pockets
#define DOOR_CRUSH_DAMAGE 15 //the amount of damage that airlocks deal when they crush you
@@ -288,10 +289,4 @@
#define HUMAN_FIRE_STACK_ICON_NUM 3
#define PULL_PRONE_SLOWDOWN 0.6
#define FIREMAN_CARRY_SLOWDOWN 0
#define PIGGYBACK_CARRY_SLOWDOWN 1
//slowdown when in softcrit. Note that crawling slowdown will also apply at the same time!
#define SOFTCRIT_ADD_SLOWDOWN 2
//slowdown when crawling
#define CRAWLING_ADD_SLOWDOWN 4
#define SLEEP_CHECK_DEATH(X) sleep(X); if(QDELETED(src) || stat == DEAD) return;

View File

@@ -0,0 +1,10 @@
/// How much someone is slowed from pulling a prone human
#define PULL_PRONE_SLOWDOWN 0.6
/// How much someone is slowed from fireman carrying a human
#define FIREMAN_CARRY_SLOWDOWN 0
/// How much someone is slowed by piggybacking a human
#define PIGGYBACK_CARRY_SLOWDOWN 1
/// slowdown when in softcrit. Note that crawling slowdown will also apply at the same time!
#define SOFTCRIT_ADD_SLOWDOWN 2
/// slowdown when crawling
#define CRAWLING_ADD_SLOWDOWN 4

View File

@@ -38,11 +38,12 @@
#define BLOCK_GAS_SMOKE_EFFECT (1<<2) //blocks the effect that chemical clouds would have on a mob --glasses, mask and helmets ONLY!
#define ALLOWINTERNALS (1<<3) //mask allows internals
#define NOSLIP (1<<4) //prevents from slipping on wet floors, in space etc
#define THICKMATERIAL (1<<5) //prevents syringes, parapens and hypos if the external suit or helmet (if targeting head) has this flag. Example: space suits, biosuit, bombsuits, thick suits that cover your body.
#define VOICEBOX_TOGGLABLE (1<<6) //The voicebox in this clothing can be toggled.
#define VOICEBOX_DISABLED (1<<7) //The voicebox is currently turned off.
#define IGNORE_HAT_TOSS (1<<8) //Hats with negative effects when worn (i.e the tinfoil hat).
#define SCAN_REAGENTS (1<<9) // Allows helmets and glasses to scan reagents.
#define NOSLIP_ICE (1<<5) //prevents from slipping on frozen floors
#define THICKMATERIAL (1<<6) //prevents syringes, parapens and hypos if the external suit or helmet (if targeting head) has this flag. Example: space suits, biosuit, bombsuits, thick suits that cover your body.
#define VOICEBOX_TOGGLABLE (1<<7) //The voicebox in this clothing can be toggled.
#define VOICEBOX_DISABLED (1<<8) //The voicebox is currently turned off.
#define IGNORE_HAT_TOSS (1<<9) //Hats with negative effects when worn (i.e the tinfoil hat).
#define SCAN_REAGENTS (1<<10) // Allows helmets and glasses to scan reagents.
// Flags for the organ_flags var on /obj/item/organ

View File

@@ -65,6 +65,7 @@
#define FREQ_ENGINEERING 1357 // Engineering comms frequency, orange
#define FREQ_SECURITY 1359 // Security comms frequency, red
#define FREQ_HOLOGRID_SOLUTION 1433
#define FREQ_STATUS_DISPLAYS 1435
#define FREQ_ATMOS_ALARMS 1437 // air alarms <-> alert computers
#define FREQ_ATMOS_CONTROL 1439 // air alarms <-> vents and scrubbers

View File

@@ -80,7 +80,7 @@
#define STATUS_EFFECT_CRUSHERMARK /datum/status_effect/crusher_mark //if struck with a proto-kinetic crusher, takes a ton of damage
#define STATUS_EFFECT_SAWBLEED /datum/status_effect/saw_bleed //if the bleed builds up enough, takes a ton of damage
#define STATUS_EFFECT_SAWBLEED /datum/status_effect/stacking/saw_bleed //if the bleed builds up enough, takes a ton of damage
#define STATUS_EFFECT_NECKSLICE /datum/status_effect/neck_slice //Creates the flavor messages for the neck-slice

View File

@@ -58,6 +58,11 @@ GLOBAL_LIST_INIT(typecache_powerfailure_safe_areas, typecacheof(/area/engine/eng
else if(isarea(areatype))
var/area/areatemp = areatype
areatype = areatemp.type
else if(islist(areatype))
var/list/turfs = list()
for(var/A in areatype)
turfs += get_area_turfs(A)
return turfs
else if(!ispath(areatype))
return null

View File

@@ -434,6 +434,29 @@ Turf and target are separate in case you want to teleport some distance from a t
return locate(x,y,A.z)
/**
* Get ranged target turf, but with direct targets as opposed to directions
*
* Starts at atom A and gets the exact angle between A and target
* Moves from A with that angle, Range amount of times, until it stops, bound to map size
* Arguments:
* * A - Initial Firer / Position
* * target - Target to aim towards
* * range - Distance of returned target turf from A
* * offset - Angle offset, 180 input would make the returned target turf be in the opposite direction
*/
/proc/get_ranged_target_turf_direct(atom/A, atom/target, range, offset)
var/angle = arctan(target.x - A.x, target.y - A.y)
if(offset)
angle += offset
var/turf/T = get_turf(A)
for(var/i in 1 to range)
var/turf/check = locate(A.x + cos(angle) * i, A.y + sin(angle) * i, A.z)
if(!check)
break
T = check
return T
// returns turf relative to A offset in dx and dy tiles
// bound to map limits

View File

@@ -348,6 +348,11 @@
config_entry_value = 16
min_val = 0
/datum/config_entry/number/icemoon_budget
config_entry_value = 90
integer = FALSE
min_val = 0
/datum/config_entry/number/station_space_budget
config_entry_value = 10
min_val = 0

View File

@@ -16,6 +16,8 @@ SUBSYSTEM_DEF(mapping)
var/list/ruins_templates = list()
var/list/space_ruins_templates = list()
var/list/lava_ruins_templates = list()
var/list/ice_ruins_templates = list()
var/list/ice_ruins_underground_templates = list()
var/list/station_ruins_templates = list()
var/datum/space_level/isolated_ruins_z //Created on demand during ruin loading.
@@ -102,19 +104,32 @@ SUBSYSTEM_DEF(mapping)
loading_ruins = TRUE
var/list/lava_ruins = levels_by_trait(ZTRAIT_LAVA_RUINS)
if (lava_ruins.len)
seedRuins(lava_ruins, CONFIG_GET(number/lavaland_budget), /area/lavaland/surface/outdoors/unexplored, lava_ruins_templates)
seedRuins(lava_ruins, CONFIG_GET(number/lavaland_budget), list(/area/lavaland/surface/outdoors/unexplored), lava_ruins_templates)
for (var/lava_z in lava_ruins)
spawn_rivers(lava_z)
var/list/ice_ruins = levels_by_trait(ZTRAIT_ICE_RUINS)
if (ice_ruins.len)
// needs to be whitelisted for underground too so place_below ruins work
seedRuins(ice_ruins, CONFIG_GET(number/icemoon_budget), list(/area/icemoon/surface/outdoors/unexplored, /area/icemoon/underground/unexplored), ice_ruins_templates)
for (var/ice_z in ice_ruins)
spawn_rivers(ice_z, 4, /turf/open/openspace/icemoon, /area/icemoon/surface/outdoors/unexplored/rivers)
var/list/ice_ruins_underground = levels_by_trait(ZTRAIT_ICE_RUINS_UNDERGROUND)
if (ice_ruins_underground.len)
seedRuins(ice_ruins_underground, CONFIG_GET(number/icemoon_budget), list(/area/icemoon/underground/unexplored), ice_ruins_underground_templates)
for (var/ice_z in ice_ruins_underground)
spawn_rivers(ice_z, 4, level_trait(ice_z, ZTRAIT_BASETURF), /area/icemoon/underground/unexplored/rivers)
// Generate deep space ruins
var/list/space_ruins = levels_by_trait(ZTRAIT_SPACE_RUINS)
if (space_ruins.len)
seedRuins(space_ruins, CONFIG_GET(number/space_budget), /area/space, space_ruins_templates)
seedRuins(space_ruins, CONFIG_GET(number/space_budget), list(/area/space), space_ruins_templates)
// Generate station space ruins
var/list/station_ruins = levels_by_trait(ZTRAIT_STATION)
if (station_ruins.len)
seedRuins(station_ruins, CONFIG_GET(number/station_space_budget), /area/space/station_ruins, station_ruins_templates)
seedRuins(station_ruins, (SSmapping.config.station_ruin_budget < 0) ? CONFIG_GET(number/station_space_budget) : SSmapping.config.station_ruin_budget, list(/area/space/station_ruins), station_ruins_templates)
SSmapping.seedStation()
loading_ruins = FALSE
#endif
@@ -182,6 +197,8 @@ SUBSYSTEM_DEF(mapping)
ruins_templates = SSmapping.ruins_templates
space_ruins_templates = SSmapping.space_ruins_templates
lava_ruins_templates = SSmapping.lava_ruins_templates
ice_ruins_templates = SSmapping.ice_ruins_templates
ice_ruins_underground_templates = SSmapping.ice_ruins_underground_templates
station_ruins_templates = SSmapping.station_ruins_templates
shuttle_templates = SSmapping.shuttle_templates
shelter_templates = SSmapping.shelter_templates
@@ -268,7 +285,7 @@ SUBSYSTEM_DEF(mapping)
// load mining
if(config.minetype == "lavaland")
LoadGroup(FailedZs, "Lavaland", "map_files/Mining", "Lavaland.dmm", default_traits = ZTRAITS_LAVALAND)
else if (!isnull(config.minetype))
else if (!isnull(config.minetype) && config.minetype != "none")
INIT_ANNOUNCE("WARNING: An unknown minetype '[config.minetype]' was set! This is being ignored! Update the maploader code!")
#endif
@@ -372,6 +389,7 @@ GLOBAL_LIST_EMPTY(the_station_areas)
// Still supporting bans by filename
var/list/banned = generateMapList("[global.config.directory]/lavaruinblacklist.txt")
banned += generateMapList("[global.config.directory]/spaceruinblacklist.txt")
banned += generateMapList("[global.config.directory]/iceruinblacklist.txt")
banned += generateMapList("[global.config.directory]/stationruinblacklist.txt")
for(var/item in sortList(subtypesof(/datum/map_template/ruin), /proc/cmp_ruincost_priority))
@@ -389,6 +407,10 @@ GLOBAL_LIST_EMPTY(the_station_areas)
if(istype(R, /datum/map_template/ruin/lavaland))
lava_ruins_templates[R.name] = R
else if(istype(R, /datum/map_template/ruin/icemoon/underground))
ice_ruins_underground_templates[R.name] = R
else if(istype(R, /datum/map_template/ruin/icemoon))
ice_ruins_templates[R.name] = R
else if(istype(R, /datum/map_template/ruin/space))
space_ruins_templates[R.name] = R
else if(istype(R, /datum/map_template/ruin/station))

View File

@@ -1,13 +1,18 @@
/datum/component/knockback
/// distance the atom will be thrown
var/throw_distance
/// whether this can throw anchored targets (tables, etc)
var/throw_anchored
/// whether this is a gentle throw (default false means people thrown into walls are stunned / take damage)
var/throw_gentle
/datum/component/knockback/Initialize(throw_distance=1)
/datum/component/knockback/Initialize(throw_distance=1, throw_gentle=FALSE)
if(!isitem(parent) && !ishostile(parent) && !isgun(parent) && !ismachinery(parent) && !isstructure(parent))
return COMPONENT_INCOMPATIBLE
src.throw_distance = throw_distance
src.throw_anchored = throw_anchored
src.throw_gentle = throw_gentle
/datum/component/knockback/RegisterWithParent()
. = ..()
@@ -22,17 +27,29 @@
. = ..()
UnregisterSignal(parent, list(COMSIG_ITEM_AFTERATTACK, COMSIG_HOSTILE_ATTACKINGTARGET, COMSIG_PROJECTILE_ON_HIT))
/// triggered after an item attacks something
/datum/component/knockback/proc/item_afterattack(obj/item/source, atom/target, mob/user, proximity_flag, click_parameters)
if(!proximity_flag)
return
do_knockback(target, user, get_dir(source, target))
/// triggered after a hostile simplemob attacks something
/datum/component/knockback/proc/hostile_attackingtarget(mob/living/simple_animal/hostile/attacker, atom/target)
do_knockback(target, attacker, get_dir(attacker, target))
/// triggered after a projectile hits something
/datum/component/knockback/proc/projectile_hit(atom/fired_from, atom/movable/firer, atom/target, Angle)
do_knockback(target, null, angle2dir(Angle))
/**
* Throw a target in a direction
*
* Arguments:
* * target - Target atom to throw
* * thrower - Thing that caused this atom to be thrown
* * throw_dir - Direction to throw the atom
*/
/datum/component/knockback/proc/do_knockback(atom/target, mob/thrower, throw_dir)
if(!ismovable(target) || throw_dir == null)
return
@@ -43,4 +60,4 @@
throw_dir = turn(throw_dir, 180)
throw_distance *= -1
var/atom/throw_target = get_edge_target_turf(throwee, throw_dir)
throwee.safe_throw_at(throw_target, throw_distance, 1, thrower)
throwee.safe_throw_at(throw_target, throw_distance, 1, thrower) //, gentle = throw_gentle)

View File

@@ -0,0 +1,31 @@
/datum/element/snailcrawl
element_flags = ELEMENT_DETACH
/datum/element/snailcrawl/Attach(datum/target)
. = ..()
if(!ismovable(target))
return ELEMENT_INCOMPATIBLE
var/P
if(iscarbon(target))
P = .proc/snail_crawl
else
P = .proc/lubricate
RegisterSignal(target, COMSIG_MOVABLE_MOVED, P)
/datum/element/snailcrawl/Detach(mob/living/carbon/target)
. = ..()
UnregisterSignal(target, COMSIG_MOVABLE_MOVED)
if(istype(target))
target.remove_movespeed_modifier(/datum/movespeed_modifier/snail_crawl)
/datum/element/snailcrawl/proc/snail_crawl(mob/living/carbon/snail)
if(snail.resting && !snail.buckled && lubricate(snail))
snail.add_movespeed_modifier(/datum/movespeed_modifier/snail_crawl)
else
snail.remove_movespeed_modifier(/datum/movespeed_modifier/snail_crawl)
/datum/element/snailcrawl/proc/lubricate(atom/movable/snail)
var/turf/open/OT = get_turf(snail)
if(istype(OT))
OT.MakeSlippery(TURF_WET_LUBE, 20)
return TRUE

View File

@@ -0,0 +1,112 @@
// Hey! Listen! Update \config\iceruinblacklist.txt with your new ruins!
/datum/map_template/ruin/icemoon
prefix = "_maps/RandomRuins/IceRuins/"
allow_duplicates = FALSE
cost = 5
// above ground only
/datum/map_template/ruin/icemoon/lust
name = "Ruin of Lust"
id = "lust"
description = "Not exactly what you expected."
suffix = "icemoon_surface_lust.dmm"
/datum/map_template/ruin/icemoon/asteroid
name = "Asteroid Site"
id = "asteroidsite"
description = "Surprised to see us here?"
suffix = "icemoon_surface_asteroid.dmm"
/datum/map_template/ruin/icemoon/hotsprings
name = "Hot Springs"
id = "hotsprings"
description = "Just relax and take a dip, nothing will go wrong, I swear!"
suffix = "icemoon_surface_hotsprings.dmm"
/datum/map_template/ruin/icemoon/engioutpost
name = "Engineer Outpost"
id = "engioutpost"
description = "Blown up by an unfortunate accident."
suffix = "icemoon_surface_engioutpost.dmm"
/datum/map_template/ruin/icemoon/fountain
name = "Fountain Hall"
id = "fountain"
description = "The fountain has a warning on the side. DANGER: May have undeclared side effects that only become obvious when implemented."
prefix = "_maps/RandomRuins/AnywhereRuins/"
suffix = "fountain_hall.dmm"
// above and below ground together
/datum/map_template/ruin/icemoon/mining_site
name = "Mining Site"
id = "miningsite"
description = "Ruins of a site where people once mined with primitive tools for ore."
suffix = "icemoon_surface_mining_site.dmm"
always_place = TRUE
always_spawn_with = list(/datum/map_template/ruin/icemoon/underground/mining_site_below = PLACE_BELOW)
/datum/map_template/ruin/icemoon/underground/mining_site_below
name = "Mining Site Underground"
id = "miningsite-underground"
description = "Who knew ladders could be so useful?"
suffix = "icemoon_underground_mining_site.dmm"
unpickable = TRUE
// below ground only
/datum/map_template/ruin/icemoon/underground
name = "underground ruin"
/datum/map_template/ruin/icemoon/underground/abandonedvillage
name = "Abandoned Village"
id = "abandonedvillage"
description = "Who knows what lies within?"
suffix = "icemoon_underground_abandoned_village.dmm"
/datum/map_template/ruin/icemoon/underground/library
name = "Buried Library"
id = "buriedlibrary"
description = "A once grand library, now lost to the confines of the Ice Moon."
suffix = "icemoon_underground_library.dmm"
/datum/map_template/ruin/icemoon/underground/wrath
name = "Ruin of Wrath"
id = "wrath"
description = "You'll fight and fight and just keep fighting."
suffix = "icemoon_underground_wrath.dmm"
/datum/map_template/ruin/icemoon/underground/lavaland
name = "Lavaland Site"
id = "lavalandsite"
description = "I guess we never really left you huh?"
suffix = "icemoon_underground_lavaland.dmm"
/datum/map_template/ruin/icemoon/underground/puzzle
name = "Ancient Puzzle"
id = "puzzle"
description = "Mystery to be solved."
suffix = "icemoon_underground_puzzle.dmm"
/datum/map_template/ruin/icemoon/underground/bathhouse
name = "Bath House"
id = "bathhouse"
description = "A taste of paradise, locked in the hell of the Ice Moon."
suffix = "icemoon_underground_bathhouse.dmm"
/datum/map_template/ruin/icemoon/underground/wendigo_cave
name = "Wendigo Cave"
id = "wendigocave"
description = "Into the jaws of the beast."
suffix = "icemoon_underground_wendigo_cave.dmm"
/datum/map_template/ruin/icemoon/underground/free_golem
name = "Free Golem Ship"
id = "golem-ship"
description = "Lumbering humanoids, made out of precious metals, move inside this ship. They frequently leave to mine more minerals, which they somehow turn into more of them. \
Seem very intent on research and individual liberty, and also geology-based naming?"
prefix = "_maps/RandomRuins/AnywhereRuins/"
suffix = "golem_ship.dmm"
allow_duplicates = FALSE

View File

@@ -67,7 +67,8 @@
description = "Lumbering humanoids, made out of precious metals, move inside this ship. They frequently leave to mine more minerals, which they somehow turn into more of them. \
Seem very intent on research and individual liberty, and also geology based naming?"
cost = 20
suffix = "lavaland_surface_golem_ship.dmm"
prefix = "_maps/RandomRuins/AnywhereRuins/"
suffix = "golem_ship.dmm"
allow_duplicates = FALSE
/datum/map_template/ruin/lavaland/animal_hospital
@@ -175,7 +176,8 @@
name = "Fountain Hall"
id = "fountain"
description = "The fountain has a warning on the side. DANGER: May have undeclared side effects that only become obvious when implemented."
suffix = "lavaland_surface_fountain_hall.dmm"
prefix = "_maps/RandomRuins/AnywhereRuins/"
suffix = "fountain_hall.dmm"
cost = 5
allow_duplicates = FALSE

View File

@@ -391,78 +391,34 @@
owner.underlays -= marked_underlay //if this is being called, we should have an owner at this point.
..()
/datum/status_effect/saw_bleed
/datum/status_effect/stacking/saw_bleed
id = "saw_bleed"
duration = -1 //removed under specific conditions
tick_interval = 6
alert_type = null
var/mutable_appearance/bleed_overlay
var/mutable_appearance/bleed_underlay
var/bleed_amount = 3
var/bleed_buildup = 3
var/delay_before_decay = 5
delay_before_decay = 5
stack_threshold = 10
max_stacks = 10
overlay_file = 'icons/effects/bleed.dmi'
underlay_file = 'icons/effects/bleed.dmi'
overlay_state = "bleed"
underlay_state = "bleed"
var/bleed_damage = 200
var/needs_to_bleed = FALSE
/datum/status_effect/saw_bleed/Destroy()
if(owner)
owner.cut_overlay(bleed_overlay)
owner.underlays -= bleed_underlay
QDEL_NULL(bleed_overlay)
return ..()
/datum/status_effect/stacking/saw_bleed/fadeout_effect()
new /obj/effect/temp_visual/bleed(get_turf(owner))
/datum/status_effect/saw_bleed/on_apply()
if(owner.stat == DEAD)
return FALSE
bleed_overlay = mutable_appearance('icons/effects/bleed.dmi', "bleed[bleed_amount]")
bleed_underlay = mutable_appearance('icons/effects/bleed.dmi', "bleed[bleed_amount]")
var/icon/I = icon(owner.icon, owner.icon_state, owner.dir)
var/icon_height = I.Height()
bleed_overlay.pixel_x = -owner.pixel_x
bleed_overlay.pixel_y = FLOOR(icon_height * 0.25, 1)
bleed_overlay.transform = matrix() * (icon_height/world.icon_size) //scale the bleed overlay's size based on the target's icon size
bleed_underlay.pixel_x = -owner.pixel_x
bleed_underlay.transform = matrix() * (icon_height/world.icon_size) * 3
bleed_underlay.alpha = 40
owner.add_overlay(bleed_overlay)
owner.underlays += bleed_underlay
return ..()
/datum/status_effect/stacking/saw_bleed/threshold_cross_effect()
owner.adjustBruteLoss(bleed_damage)
var/turf/T = get_turf(owner)
new /obj/effect/temp_visual/bleed/explode(T)
for(var/d in GLOB.alldirs)
new /obj/effect/temp_visual/dir_setting/bloodsplatter(T, d)
playsound(T, "desceration", 100, TRUE, -1)
/datum/status_effect/saw_bleed/tick()
if(owner.stat == DEAD)
qdel(src)
else
add_bleed(-1)
/datum/status_effect/saw_bleed/proc/add_bleed(amount)
owner.cut_overlay(bleed_overlay)
owner.underlays -= bleed_underlay
bleed_amount += amount
if(bleed_amount)
if(bleed_amount >= 10)
needs_to_bleed = TRUE
qdel(src)
else
if(amount > 0)
tick_interval += delay_before_decay
bleed_overlay.icon_state = "bleed[bleed_amount]"
bleed_underlay.icon_state = "bleed[bleed_amount]"
owner.add_overlay(bleed_overlay)
owner.underlays += bleed_underlay
else
qdel(src)
/datum/status_effect/saw_bleed/on_remove()
. = ..()
if(needs_to_bleed)
var/turf/T = get_turf(owner)
new /obj/effect/temp_visual/bleed/explode(T)
for(var/d in GLOB.alldirs)
new /obj/effect/temp_visual/dir_setting/bloodsplatter(T, d)
playsound(T, "desceration", 200, 1, -1)
owner.adjustBruteLoss(bleed_damage)
else
new /obj/effect/temp_visual/bleed(get_turf(owner))
/datum/status_effect/stacking/saw_bleed/bloodletting
id = "bloodletting"
stack_threshold = 7
max_stacks = 7
bleed_damage = 20
/datum/status_effect/neck_slice
id = "neck_slice"

View File

@@ -7,7 +7,6 @@
var/duration = -1 //How long the status effect lasts in DECISECONDS. Enter -1 for an effect that never ends unless removed through some means.
var/tick_interval = 10 //How many deciseconds between ticks, approximately. Leave at 10 for every second.
var/mob/living/owner //The mob affected by the status effect.
var/status_type = STATUS_EFFECT_UNIQUE //How many of the effect can be on one mob, and what happens when you try to add another
var/on_remove_on_mob_delete = FALSE //if we call on_remove() when the mob is deleted
var/examine_text //If defined, this text will appear when the mob is examined - to use he, she etc. use "SUBJECTPRONOUN" and replace it in the examines themselves
var/alert_type = /obj/screen/alert/status_effect //the alert thrown by the status effect, contains name and description
@@ -16,6 +15,8 @@
/// If this is TRUE, the user will have sprint forcefully disabled while this is active.
var/blocks_sprint = FALSE
var/obj/screen/alert/status_effect/linked_alert = null //the alert itself, if it exists
/// How many of the effect can be on one mob, and what happens when you try to add another
var/status_type = STATUS_EFFECT_UNIQUE
/datum/status_effect/New(list/arguments)
on_creation(arglist(arguments))
@@ -67,6 +68,9 @@
/datum/status_effect/proc/tick() //Called every tick.
/datum/status_effect/proc/before_remove() //! Called before being removed; returning FALSE will cancel removal
return TRUE
/datum/status_effect/proc/on_remove() //Called whenever the buff expires or is removed; do note that at the point this is called, it is out of the owner's status_effects but owner is not yet null
SHOULD_CALL_PARENT(TRUE)
REMOVE_TRAIT(owner, TRAIT_COMBAT_MODE_LOCKED, src)
@@ -123,12 +127,13 @@
S1 = new effect(arguments)
. = S1
/mob/living/proc/remove_status_effect(effect) //removes all of a given status effect from this mob, returning TRUE if at least one was removed
/mob/living/proc/remove_status_effect(effect, ...) //removes all of a given status effect from this mob, returning TRUE if at least one was removed
. = FALSE
var/list/arguments = args.Copy(2)
if(status_effects)
var/datum/status_effect/S1 = effect
for(var/datum/status_effect/S in status_effects)
if(initial(S1.id) == S.id)
if(initial(S1.id) == S.id && S.before_remove(arguments))
qdel(S)
. = TRUE
@@ -147,3 +152,129 @@
for(var/datum/status_effect/S in status_effects)
if(initial(S1.id) == S.id)
. += S
//////////////////////
// STACKING EFFECTS //
//////////////////////
/datum/status_effect/stacking
id = "stacking_base"
duration = -1 //removed under specific conditions
alert_type = null
var/stacks = 0 //how many stacks are accumulated, also is # of stacks that target will have when first applied
var/delay_before_decay //deciseconds until ticks start occuring, which removes stacks (first stack will be removed at this time plus tick_interval)
tick_interval = 10 //deciseconds between decays once decay starts
var/stack_decay = 1 //how many stacks are lost per tick (decay trigger)
var/stack_threshold //special effects trigger when stacks reach this amount
var/max_stacks //stacks cannot exceed this amount
var/consumed_on_threshold = TRUE //if status should be removed once threshold is crossed
var/threshold_crossed = FALSE //set to true once the threshold is crossed, false once it falls back below
var/overlay_file
var/underlay_file
var/overlay_state // states in .dmi must be given a name followed by a number which corresponds to a number of stacks. put the state name without the number in these state vars
var/underlay_state // the number is concatonated onto the string based on the number of stacks to get the correct state name
var/mutable_appearance/status_overlay
var/mutable_appearance/status_underlay
/datum/status_effect/stacking/proc/threshold_cross_effect() //what happens when threshold is crossed
/datum/status_effect/stacking/proc/stacks_consumed_effect() //runs if status is deleted due to threshold being crossed
/datum/status_effect/stacking/proc/fadeout_effect() //runs if status is deleted due to being under one stack
/datum/status_effect/stacking/proc/stack_decay_effect() //runs every time tick() causes stacks to decay
/datum/status_effect/stacking/proc/on_threshold_cross()
threshold_cross_effect()
if(consumed_on_threshold)
stacks_consumed_effect()
qdel(src)
/datum/status_effect/stacking/proc/on_threshold_drop()
/datum/status_effect/stacking/proc/can_have_status()
return owner.stat != DEAD
/datum/status_effect/stacking/proc/can_gain_stacks()
return owner.stat != DEAD
/datum/status_effect/stacking/tick()
if(!can_have_status())
qdel(src)
else
add_stacks(-stack_decay)
stack_decay_effect()
/datum/status_effect/stacking/proc/add_stacks(stacks_added)
if(stacks_added > 0 && !can_gain_stacks())
return FALSE
owner.cut_overlay(status_overlay)
owner.underlays -= status_underlay
stacks += stacks_added
if(stacks > 0)
if(stacks >= stack_threshold && !threshold_crossed) //threshold_crossed check prevents threshold effect from occuring if changing from above threshold to still above threshold
threshold_crossed = TRUE
on_threshold_cross()
if(consumed_on_threshold)
return
else if(stacks < stack_threshold && threshold_crossed)
threshold_crossed = FALSE //resets threshold effect if we fall below threshold so threshold effect can trigger again
on_threshold_drop()
if(stacks_added > 0)
tick_interval += delay_before_decay //refreshes time until decay
stacks = min(stacks, max_stacks)
status_overlay.icon_state = "[overlay_state][stacks]"
status_underlay.icon_state = "[underlay_state][stacks]"
owner.add_overlay(status_overlay)
owner.underlays += status_underlay
else
fadeout_effect()
qdel(src) //deletes status if stacks fall under one
/datum/status_effect/stacking/on_creation(mob/living/new_owner, stacks_to_apply)
. = ..()
if(.)
add_stacks(stacks_to_apply)
/datum/status_effect/stacking/on_apply()
if(!can_have_status())
return FALSE
status_overlay = mutable_appearance(overlay_file, "[overlay_state][stacks]")
status_underlay = mutable_appearance(underlay_file, "[underlay_state][stacks]")
var/icon/I = icon(owner.icon, owner.icon_state, owner.dir)
var/icon_height = I.Height()
status_overlay.pixel_x = -owner.pixel_x
status_overlay.pixel_y = FLOOR(icon_height * 0.25, 1)
status_overlay.transform = matrix() * (icon_height/world.icon_size) //scale the status's overlay size based on the target's icon size
status_underlay.pixel_x = -owner.pixel_x
status_underlay.transform = matrix() * (icon_height/world.icon_size) * 3
status_underlay.alpha = 40
owner.add_overlay(status_overlay)
owner.underlays += status_underlay
return ..()
/datum/status_effect/stacking/Destroy()
if(owner)
owner.cut_overlay(status_overlay)
owner.underlays -= status_underlay
QDEL_NULL(status_overlay)
return ..()
/// Status effect from multiple sources, when all sources are removed, so is the effect
/datum/status_effect/grouped
status_type = STATUS_EFFECT_MULTIPLE //! Adds itself to sources and destroys itself if one exists already, there are never multiple
var/list/sources = list()
/datum/status_effect/grouped/on_creation(mob/living/new_owner, source)
var/datum/status_effect/grouped/existing = new_owner.has_status_effect(type)
if(existing)
existing.sources |= source
qdel(src)
return FALSE
else
sources |= source
return ..()
/datum/status_effect/grouped/before_remove(source)
sources -= source
return !length(sources)

View File

@@ -1,49 +1,96 @@
//The effects of weather occur across an entire z-level. For instance, lavaland has periodic ash storms that scorch most unprotected creatures.
/**
* Causes weather to occur on a z level in certain area types
*
* The effects of weather occur across an entire z-level. For instance, lavaland has periodic ash storms that scorch most unprotected creatures.
* Weather always occurs on different z levels at different times, regardless of weather type.
* Can have custom durations, targets, and can automatically protect indoor areas.
*
*/
/datum/weather
/// name of weather
var/name = "space wind"
/// description of weather
var/desc = "Heavy gusts of wind blanket the area, periodically knocking down anyone caught in the open."
var/telegraph_message = "<span class='warning'>The wind begins to pick up.</span>" //The message displayed in chat to foreshadow the weather's beginning
var/telegraph_duration = 300 //In deciseconds, how long from the beginning of the telegraph until the weather begins
var/telegraph_sound //The sound file played to everyone on an affected z-level
var/telegraph_overlay //The overlay applied to all tiles on the z-level
/// The message displayed in chat to foreshadow the weather's beginning
var/telegraph_message = "<span class='warning'>The wind begins to pick up.</span>"
var/weather_message = "<span class='userdanger'>The wind begins to blow ferociously!</span>" //Displayed in chat once the weather begins in earnest
var/weather_duration = 1200 //In deciseconds, how long the weather lasts once it begins
var/weather_duration_lower = 1200 //See above - this is the lowest possible duration
var/weather_duration_upper = 1500 //See above - this is the highest possible duration
/// In deciseconds, how long from the beginning of the telegraph until the weather begins
var/telegraph_duration = 300
/// The sound file played to everyone on an affected z-level
var/telegraph_sound
/// The overlay applied to all tiles on the z-level
var/telegraph_overlay
/// Displayed in chat once the weather begins in earnest
var/weather_message = "<span class='userdanger'>The wind begins to blow ferociously!</span>"
///In deciseconds, how long the weather lasts once it begins
var/weather_duration = 1200
///See above - this is the lowest possible duration
var/weather_duration_lower = 1200
///See above - this is the highest possible duration
var/weather_duration_upper = 1500
/// Looping sound while weather is occuring
var/weather_sound
/// Area overlay while the weather is occuring
var/weather_overlay
/// Color to apply to the area while weather is occuring
var/weather_color = null
var/end_message = "<span class='danger'>The wind relents its assault.</span>" //Displayed once the weather is over
var/end_duration = 300 //In deciseconds, how long the "wind-down" graphic will appear before vanishing entirely
/// Displayed once the weather is over
var/end_message = "<span class='danger'>The wind relents its assault.</span>"
/// In deciseconds, how long the "wind-down" graphic will appear before vanishing entirely
var/end_duration = 300
/// Sound that plays while weather is ending
var/end_sound
/// Area overlay while weather is ending
var/end_overlay
var/area_type = /area/space //Types of area to affect
var/list/impacted_areas = list() //Areas to be affected by the weather, calculated when the weather begins
var/list/protected_areas = list()//Areas that are protected and excluded from the affected areas.
var/impacted_z_levels // The list of z-levels that this weather is actively affecting
/// Types of area to affect
var/area_type = /area/space
/// TRUE value protects areas with outdoors marked as false, regardless of area type
var/protect_indoors = FALSE
/// Areas to be affected by the weather, calculated when the weather begins
var/list/impacted_areas = list()
var/overlay_layer = AREA_LAYER //Since it's above everything else, this is the layer used by default. TURF_LAYER is below mobs and walls if you need to use that.
var/aesthetic = FALSE //If the weather has no purpose other than looks
var/immunity_type = "storm" //Used by mobs to prevent them from being affected by the weather
/// Areas that are protected and excluded from the affected areas.
var/list/protected_areas = list()
/// The list of z-levels that this weather is actively affecting
var/impacted_z_levels
var/stage = END_STAGE //The stage of the weather, from 1-4
/// Since it's above everything else, this is the layer used by default. TURF_LAYER is below mobs and walls if you need to use that.
var/overlay_layer = AREA_LAYER
/// Plane for the overlay
var/overlay_plane = BLACKNESS_PLANE
/// If the weather has no purpose but aesthetics.
var/aesthetic = FALSE
/// Used by mobs to prevent them from being affected by the weather
var/immunity_type = "storm"
// These are read by the weather subsystem and used to determine when and where to run the weather.
var/probability = 0 // Weight amongst other eligible weather. If zero, will never happen randomly.
var/target_trait = ZTRAIT_STATION // The z-level trait to affect when run randomly or when not overridden.
/// The stage of the weather, from 1-4
var/stage = END_STAGE
/// Weight amongst other eligible weather. if zero, will never happen randomly.
var/probability = 0
/// The z-level trait to affect when run randomly or when not overridden.
var/target_trait = ZTRAIT_STATION
/// Whether a barometer can predict when the weather will happen
var/barometer_predictable = FALSE
var/next_hit_time = 0 //For barometers to know when the next storm will hit
/// For barometers to know when the next storm will hit
var/next_hit_time = 0
/datum/weather/New(z_levels)
..()
impacted_z_levels = z_levels
/**
* Telegraphs the beginning of the weather on the impacted z levels
*
* Sends sounds and details to mobs in the area
* Calculates duration and hit areas, and makes a callback for the actual weather to start
*
*/
/datum/weather/proc/telegraph()
if(stage == STARTUP_STAGE)
return
@@ -58,6 +105,8 @@
affectareas -= get_areas(V)
for(var/V in affectareas)
var/area/A = V
if(protect_indoors && !A.outdoors)
continue
if(A.z in impacted_z_levels)
impacted_areas |= A
weather_duration = rand(weather_duration_lower, weather_duration_upper)
@@ -72,6 +121,13 @@
SEND_SOUND(M, sound(telegraph_sound))
addtimer(CALLBACK(src, .proc/start), telegraph_duration)
/**
* Starts the actual weather and effects from it
*
* Updates area overlays and sends sounds and messages to mobs to notify them
* Begins dealing effects from weather to mobs in the area
*
*/
/datum/weather/proc/start()
if(stage >= MAIN_STAGE)
return
@@ -86,6 +142,13 @@
SEND_SOUND(M, sound(weather_sound))
addtimer(CALLBACK(src, .proc/wind_down), weather_duration)
/**
* Weather enters the winding down phase, stops effects
*
* Updates areas to be in the winding down phase
* Sends sounds and messages to mobs to notify them
*
*/
/datum/weather/proc/wind_down()
if(stage >= WIND_DOWN_STAGE)
return
@@ -100,6 +163,13 @@
SEND_SOUND(M, sound(end_sound))
addtimer(CALLBACK(src, .proc/end), end_duration)
/**
* Fully ends the weather
*
* Effects no longer occur and area overlays are removed
* Removes weather from processing completely
*
*/
/datum/weather/proc/end()
if(stage == END_STAGE)
return 1
@@ -115,7 +185,11 @@
if(can_weather_act(L))
weather_act(L)
/datum/weather/proc/can_weather_act(mob/living/L) //Can this weather impact a mob?
/**
* Returns TRUE if the living mob can be affected by the weather
*
*/
/datum/weather/proc/can_weather_act(mob/living/L)
var/turf/mob_turf = get_turf(L)
if(mob_turf && !(mob_turf.z in impacted_z_levels))
return
@@ -123,11 +197,19 @@
return
if(!(get_area(L) in impacted_areas))
return
return 1
return TRUE
/datum/weather/proc/weather_act(mob/living/L) //What effect does this weather have on the hapless mob?
/**
* Affects the mob with whatever the weather does
*
*/
/datum/weather/proc/weather_act(mob/living/L)
return
/**
* Updates the overlays on impacted areas
*
*/
/datum/weather/proc/update_areas()
for(var/V in impacted_areas)
var/area/N = V

View File

@@ -17,8 +17,9 @@
end_message = "<span class='boldannounce'>The downpour gradually slows to a light shower. It should be safe outside now.</span>"
end_sound = 'sound/ambience/acidrain_end.ogg'
area_type = /area/lavaland/surface/outdoors
target_trait = ZTRAIT_MINING
area_type = /area
protect_indoors = TRUE
target_trait = ZTRAIT_ACIDRAIN
immunity_type = "acid" // temp

View File

@@ -16,8 +16,9 @@
end_duration = 300
end_overlay = "light_ash"
area_type = /area/lavaland/surface/outdoors
target_trait = ZTRAIT_MINING
area_type = /area
protect_indoors = TRUE
target_trait = ZTRAIT_ASHSTORM
immunity_type = "ash"

View File

@@ -15,8 +15,9 @@
end_duration = 100
end_message = "<span class='boldannounce'>The snowfall dies down, it should be safe to go outside again.</span>"
area_type = /area/awaymission/snowdin/outside
target_trait = ZTRAIT_AWAY
area_type = /area
protect_indoors = TRUE
target_trait = ZTRAIT_SNOWSTORM
immunity_type = "snow"

View File

@@ -11,13 +11,27 @@
mouse_opacity = MOUSE_OPACITY_TRANSPARENT
invisibility = INVISIBILITY_LIGHTING
var/map_name // Set in New(); preserves the name set by the map maker, even if renamed by the Blueprints.
/// Set in New(); preserves the name set by the map maker, even if renamed by the Blueprints.
var/map_name
var/valid_territory = TRUE // If it's a valid territory for gangs to claim
var/blob_allowed = TRUE // Does it count for blobs score? By default, all areas count.
var/clockwork_warp_allowed = TRUE // Can servants warp into this area from Reebe?
/// If it's valid territory for gangs/cults to summon
var/valid_territory = TRUE
/// if blobs can spawn there and if it counts towards their score.
var/blob_allowed = TRUE
/// whether servants can warp into this area from Reebe
var/clockwork_warp_allowed = TRUE
/// Message to display when the clockwork warp fails
var/clockwork_warp_fail = "The structure there is too dense for warping to pierce. (This is normal in high-security areas.)"
/// If mining tunnel generation is allowed in this area
var/tunnel_allowed = FALSE
/// If flora are allowed to spawn in this area randomly through tunnel generation
var/flora_allowed = FALSE
/// if mobs can be spawned by natural random generation
var/mob_spawn_allowed = FALSE
/// If megafauna can be spawned by natural random generation
var/megafauna_spawn_allowed = FALSE
var/fire = null
var/atmos = TRUE
var/atmosalm = FALSE
@@ -25,11 +39,14 @@
var/lightswitch = TRUE
var/requires_power = TRUE
var/always_unpowered = FALSE // This gets overridden to 1 for space in area/Initialize().
/// This gets overridden to 1 for space in area/Initialize().
var/always_unpowered = FALSE
var/outdoors = FALSE //For space, the asteroid, lavaland, etc. Used with blueprints to determine if we are adding a new area (vs editing a station room)
/// For space, the asteroid, lavaland, etc. Used with blueprints to determine if we are adding a new area (vs editing a station room)
var/outdoors = FALSE
var/areasize = 0 //Size of the area in open turfs, only calculated for indoors areas.
/// Size of the area in open turfs, only calculated for indoors areas.
var/areasize = 0
var/power_equip = TRUE
var/power_light = TRUE
@@ -43,9 +60,12 @@
var/static_environ
var/has_gravity = 0
var/noteleport = FALSE //Are you forbidden from teleporting to the area? (centcom, mobs, wizard, hand teleporter)
var/hidden = FALSE //Hides area from player Teleport function.
var/safe = FALSE //Is the area teleport-safe: no space / radiation / aggresive mobs / other dangers
/// Are you forbidden from teleporting to the area? (centcom, mobs, wizard, hand teleporter)
var/noteleport = FALSE
/// Hides area from player Teleport function.
var/hidden = FALSE
/// Is the area teleport-safe: no space / radiation / aggresive mobs / other dangers
var/safe = FALSE
/// If false, loading multiple maps with this area type will create multiple instances.
var/unique = TRUE

View File

@@ -3,6 +3,7 @@
/area/mine
icon_state = "mining"
has_gravity = STANDARD_GRAVITY
flora_allowed = TRUE
/area/mine/explored
name = "Mine"
@@ -17,6 +18,7 @@
outdoors = TRUE
flags_1 = NONE
ambientsounds = MINING
flora_allowed = FALSE
/area/mine/unexplored
name = "Mine"
@@ -31,6 +33,7 @@
outdoors = TRUE
flags_1 = NONE
ambientsounds = MINING
tunnel_allowed = TRUE
/area/mine/lobby
name = "Mining Station"
@@ -82,6 +85,7 @@
icon_state = "mining"
has_gravity = STANDARD_GRAVITY
flags_1 = NONE
flora_allowed = TRUE
/area/lavaland/surface
name = "Lavaland"
@@ -114,9 +118,79 @@
/area/lavaland/surface/outdoors/unexplored //monsters and ruins spawn here
icon_state = "unexplored"
tunnel_allowed = TRUE
mob_spawn_allowed = TRUE
/area/lavaland/surface/outdoors/unexplored/danger //megafauna will also spawn here
icon_state = "danger"
megafauna_spawn_allowed = TRUE
/area/lavaland/surface/outdoors/explored
name = "Lavaland Labor Camp"
flora_allowed = FALSE
/**********************Ice Moon Areas**************************/
/area/icemoon
icon_state = "mining"
has_gravity = STANDARD_GRAVITY
flags_1 = NONE
flora_allowed = TRUE
blob_allowed = FALSE
/area/icemoon/surface
name = "Icemoon"
icon_state = "explored"
always_unpowered = TRUE
poweralm = FALSE
power_environ = FALSE
power_equip = FALSE
power_light = FALSE
requires_power = TRUE
ambientsounds = MINING
/area/icemoon/underground
name = "Icemoon Caves"
outdoors = TRUE
always_unpowered = TRUE
requires_power = TRUE
poweralm = FALSE
power_environ = FALSE
power_equip = FALSE
power_light = FALSE
ambientsounds = MINING
/area/icemoon/underground/unexplored // mobs and megafauna and ruins spawn here
name = "Icemoon Caves"
icon_state = "unexplored"
tunnel_allowed = TRUE
mob_spawn_allowed = TRUE
megafauna_spawn_allowed = TRUE
/area/icemoon/underground/unexplored/rivers // rivers spawn here
icon_state = "danger"
/area/icemoon/underground/explored
name = "Icemoon Underground"
flora_allowed = FALSE
/area/icemoon/surface/outdoors
name = "Icemoon Wastes"
outdoors = TRUE
/area/icemoon/surface/outdoors/labor_camp
name = "Icemoon Labor Camp"
flora_allowed = FALSE
/area/icemoon/surface/outdoors/unexplored //monsters and ruins spawn here
icon_state = "unexplored"
tunnel_allowed = TRUE
mob_spawn_allowed = TRUE
/area/icemoon/surface/outdoors/unexplored/rivers // rivers spawn here
icon_state = "danger"
/area/icemoon/surface/outdoors/unexplored/rivers/no_monsters
mob_spawn_allowed = FALSE

View File

@@ -0,0 +1,9 @@
// Icemoon Ruins
/area/ruin/unpowered/buried_library
name = "Buried Library"
icon_state = "dk_yellow"
/area/ruin/powered/bathhouse
name = "Bath House"
icon_state = "dk_yellow"

View File

@@ -20,6 +20,9 @@
if(!newloc.Enter(src, src.loc))
return
if (SEND_SIGNAL(src, COMSIG_MOVABLE_PRE_MOVE, newloc) & COMPONENT_MOVABLE_BLOCK_PRE_MOVE)
return
// Past this is the point of no return
var/atom/oldloc = loc
var/area/oldarea = get_area(oldloc)

View File

@@ -642,6 +642,9 @@
for(var/obj/effect/landmark/carpspawn/L in GLOB.landmarks_list)
if(isturf(L.loc))
spawn_locs += L.loc
for(var/obj/effect/landmark/loneopspawn/L in GLOB.landmarks_list)
if(isturf(L.loc))
spawn_locs += L.loc
if(!spawn_locs.len)
return FALSE
spawn_loc = pick(spawn_locs)

View File

@@ -313,6 +313,11 @@ INITIALIZE_IMMEDIATE(/obj/effect/landmark/start/new_player)
name = "carpspawn"
icon_state = "carp_spawn"
// lone op (optional)
/obj/effect/landmark/loneopspawn
name = "loneop+ninjaspawn"
icon_state = "snukeop_spawn"
// observer-start.
/obj/effect/landmark/observer_start
name = "Observer-Start"
@@ -512,3 +517,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

View File

@@ -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
@@ -183,3 +184,47 @@
else
real_target = get_turf(linked)
return real_target
/obj/effect/portal/permanent
name = "permanent portal"
desc = "An unwavering portal that will never fade."
hardlinked = FALSE // dont qdel my portal nerd
force_teleport = TRUE // force teleports because they're a mapmaker tool
var/id // var edit or set id in map editor
/obj/effect/portal/permanent/proc/set_linked()
if(!id)
return
for(var/obj/effect/portal/permanent/P in GLOB.portals - src)
if(P.id == id)
P.linked = src
linked = P
break
/obj/effect/portal/permanent/teleport(atom/movable/M, force = FALSE)
set_linked() // update portal links
. = ..()
/obj/effect/portal/permanent/one_way // doesn't have a return portal, can have multiple exits, /obj/effect/landmark/portal_exit to mark them
name = "one-way portal"
desc = "You get the feeling that this might not be the safest thing you've ever done."
/obj/effect/portal/permanent/one_way/set_linked()
if(!id)
return
var/list/possible_turfs = list()
for(var/obj/effect/landmark/portal_exit/PE in GLOB.landmarks_list)
if(PE.id == id)
var/turf/T = get_turf(PE)
if(T)
possible_turfs |= T
if(possible_turfs.len)
hard_target = pick(possible_turfs)
/obj/effect/portal/permanent/one_way/one_use
name = "one-use portal"
desc = "This is probably the worst decision you'll ever make in your life."
/obj/effect/portal/permanent/one_way/one_use/teleport(atom/movable/M, force = FALSE)
. = ..()
qdel(src)

View File

@@ -351,6 +351,12 @@
light_color = "#FFAA44"
flashlight_power = 0.8
/obj/item/flashlight/lantern/jade
name = "jade lantern"
desc = "An ornate, green lantern."
color = LIGHT_COLOR_GREEN
light_color = LIGHT_COLOR_GREEN
/obj/item/flashlight/slime
gender = PLURAL
name = "glowing slime extract"

View File

@@ -8,6 +8,7 @@
level = 1
var/trigger_mob = TRUE
var/trigger_item = FALSE
var/specific_item = null
var/trigger_silent = FALSE
var/sound/trigger_sound = 'sound/effects/pressureplate.ogg'
var/obj/item/assembly/signaler/sigdev = null
@@ -35,6 +36,8 @@
. = ..()
if(!can_trigger || !active)
return
if(trigger_item && !istype(AM, specific_item))
return
if(trigger_mob && isliving(AM))
var/mob/living/L = AM
to_chat(L, "<span class='warning'>You feel something click beneath you!</span>")

View File

@@ -3,6 +3,7 @@
* Fork
* Kitchen knives
* Ritual Knife
* Bloodletter
* Butcher's cleaver
* Combat Knife
* Rolling Pins
@@ -97,6 +98,28 @@
righthand_file = 'icons/mob/inhands/equipment/kitchen_righthand.dmi'
w_class = WEIGHT_CLASS_NORMAL
/obj/item/kitchen/knife/bloodletter
name = "bloodletter"
desc = "An occult looking dagger that is cold to the touch. Somehow, the flawless orb on the pommel is made entirely of liquid blood."
icon = 'icons/obj/ice_moon/artifacts.dmi'
icon_state = "bloodletter"
w_class = WEIGHT_CLASS_NORMAL
/// Bleed stacks applied when an organic mob target is hit
var/bleed_stacks_per_hit = 3
/obj/item/kitchen/knife/bloodletter/afterattack(atom/target, mob/user, proximity_flag, click_parameters)
. = ..()
if(!isliving(target) || !proximity_flag)
return
var/mob/living/M = target
if(!(M.mob_biotypes & MOB_ORGANIC))
return
var/datum/status_effect/stacking/saw_bleed/bloodletting/B = M.has_status_effect(/datum/status_effect/stacking/saw_bleed/bloodletting)
if(!B)
M.apply_status_effect(/datum/status_effect/stacking/saw_bleed/bloodletting, bleed_stacks_per_hit)
else
B.add_stacks(bleed_stacks_per_hit)
/obj/item/kitchen/knife/butcher
name = "butcher's cleaver"
icon_state = "butch"

View File

@@ -0,0 +1,146 @@
//**************
//*****Keys*******************
//************** ** **
/obj/item/keycard
name = "security keycard"
desc = "This feels like it belongs to a door."
icon = 'icons/obj/puzzle_small.dmi'
icon_state = "keycard"
force = 0
throwforce = 0
w_class = WEIGHT_CLASS_TINY
throw_speed = 1
throw_range = 7
resistance_flags = INDESTRUCTIBLE | FIRE_PROOF | ACID_PROOF | LAVA_PROOF
var/puzzle_id = null
//Two test keys for use alongside the two test doors.
/obj/item/keycard/cheese
name = "cheese keycard"
desc = "Look, I still don't understand the reference. What the heck is a keyzza?"
color = "#f0da12"
puzzle_id = "cheese"
/obj/item/keycard/swordfish
name = "titanic keycard"
desc = "Smells like it was at the bottom of a harbor."
color = "#3bbbdb"
puzzle_id = "swordfish"
//***************
//*****Doors*****
//***************
/obj/machinery/door/keycard
name = "locked door"
desc = "This door only opens when a keycard is swiped. It looks virtually indestructable."
icon = 'icons/obj/doors/puzzledoor/default.dmi'
icon_state = "door_closed"
explosion_block = 3
heat_proof = TRUE
max_integrity = 600
armor = list("melee" = 100, "bullet" = 100, "laser" = 100, "energy" = 100, "bomb" = 100, "bio" = 100, "rad" = 100, "fire" = 100, "acid" = 100)
resistance_flags = INDESTRUCTIBLE | FIRE_PROOF | ACID_PROOF | LAVA_PROOF
damage_deflection = 70
/// Make sure that the key has the same puzzle_id as the keycard door!
var/puzzle_id = null
/// Message that occurs when the door is opened
var/open_message = "The door beeps, and slides opens."
//Standard Expressions to make keycard doors basically un-cheeseable
/obj/machinery/door/keycard/Bumped(atom/movable/AM)
return !density && ..()
/obj/machinery/door/keycard/emp_act(severity)
return
/obj/machinery/door/keycard/ex_act(severity, target)
return
/obj/machinery/door/keycard/try_to_activate_door(mob/user)
add_fingerprint(user)
if(operating)
return
/obj/machinery/door/keycard/attackby(obj/item/I, mob/user, params)
. = ..()
if(istype(I,/obj/item/keycard))
var/obj/item/keycard/key = I
if((!puzzle_id || puzzle_id == key.puzzle_id) && density)
if(open_message)
to_chat(user, "<span class='notice'>[open_message]</span>")
open()
return
else if(puzzle_id != key.puzzle_id)
to_chat(user, "<span class='notice'>[src] buzzes. This must not be the right key.</span>")
return
else
to_chat(user, "<span class='notice'>This door doesn't appear to close.</span>")
return
//Test doors. Gives admins a few doors to use quickly should they so choose.
/obj/machinery/door/keycard/cheese
name = "blue airlock"
desc = "Smells like... pizza?"
puzzle_id = "cheese"
/obj/machinery/door/keycard/swordfish
name = "blue airlock"
desc = "If nautical nonsense be something you wish."
puzzle_id = "swordfish"
//*************************
//***Box Pushing Puzzles***
//*************************
//We're working off a subtype of pressureplates, which should work just a BIT better now.
/obj/structure/holobox
name = "holobox"
desc = "A hard-light box, containing a secure decryption key."
icon = 'icons/obj/puzzle_small.dmi'
icon_state = "laserbox"
density = TRUE
resistance_flags = INDESTRUCTIBLE | FIRE_PROOF | ACID_PROOF | LAVA_PROOF
//Uses the pressure_plate settings for a pretty basic custom pattern that waits for a specific item to trigger. Easy enough to retool for mapping purposes or subtypes.
/obj/item/pressure_plate/hologrid
name = "hologrid"
desc = "A high power, electronic input port for a holobox, which can unlock the hologrid's storage compartment. Safe to stand on."
icon = 'icons/obj/puzzle_small.dmi'
icon_state = "lasergrid"
anchored = TRUE
trigger_mob = FALSE
trigger_item = TRUE
specific_item = /obj/structure/holobox
removable_signaller = FALSE //Being a pressure plate subtype, this can also use signals.
roundstart_signaller_freq = FREQ_HOLOGRID_SOLUTION //Frequency is kept on it's own default channel however.
active = TRUE
trigger_delay = 10
resistance_flags = INDESTRUCTIBLE | FIRE_PROOF | ACID_PROOF | LAVA_PROOF
var/reward = /obj/item/reagent_containers/food/snacks/cookie
var/claimed = FALSE
/obj/item/pressure_plate/hologrid/examine(mob/user)
. = ..()
if(claimed)
. += "<span class='notice'>This one appears to be spent already.</span>"
/obj/item/pressure_plate/hologrid/trigger()
if(!claimed)
new reward(loc)
flick("lasergrid_a",src)
icon_state = "lasergrid_full"
claimed = TRUE
/obj/item/pressure_plate/hologrid/Crossed(atom/movable/AM)
. = ..()
if(trigger_item && istype(AM, specific_item) && !claimed)
AM.anchored = TRUE
flick("laserbox_burn", AM)
trigger()
sleep(15)
qdel(AM)
// snowflake code until undertile elements
/obj/item/pressure_plate/hologrid/hide()
. = ..()
anchored = TRUE

View File

@@ -178,6 +178,11 @@ GLOBAL_LIST_INIT(leather_recipes, list ( \
icon_state = "sinew"
novariants = TRUE
/obj/item/stack/sheet/sinew/wolf
name = "wolf sinew"
desc = "Long stringy filaments which came from the insides of a wolf."
singular_name = "wolf sinew"
GLOBAL_LIST_INIT(sinew_recipes, list ( \
new/datum/stack_recipe("sinew restraints", /obj/item/restraints/handcuffs/sinew, 1), \
@@ -202,6 +207,11 @@ GLOBAL_LIST_INIT(sinew_recipes, list ( \
w_class = WEIGHT_CLASS_NORMAL
layer = MOB_LAYER
/obj/item/stack/sheet/animalhide/goliath_hide/polar_bear_hide
name = "polar bear hides"
desc = "Pieces of a polar bear's fur, these might be able to make your suit a bit more durable to attack from the local fauna."
icon_state = "polar_bear_hide"
singular_name = "polar bear hide"
/obj/item/stack/sheet/animalhide/ashdrake
name = "ash drake hide"

View File

@@ -350,11 +350,28 @@
icon = 'icons/obj/flora/rocks.dmi'
resistance_flags = FIRE_PROOF
density = TRUE
/// Itemstack that is dropped when a rock is mined with a pickaxe
var/obj/item/stack/mineResult = /obj/item/stack/ore/glass/basalt
/// Amount of the itemstack to drop
var/mineAmount = 20
/obj/structure/flora/rock/Initialize()
. = ..()
icon_state = "[icon_state][rand(1,3)]"
/obj/structure/flora/rock/attackby(obj/item/W, mob/user, params)
if(!mineResult || W.tool_behaviour != TOOL_MINING)
return ..()
if(flags_1 & NODECONSTRUCT_1)
return ..()
to_chat(user, "<span class='notice'>You start mining...</span>")
if(W.use_tool(src, user, 40, volume=50))
to_chat(user, "<span class='notice'>You finish mining the rock.</span>")
if(mineResult && mineAmount)
new mineResult(get_turf(src), mineAmount)
SSblackbox.record_feedback("tally", "pick_used_mining", 1, W.type)
qdel(src)
/obj/structure/flora/rock/pile
icon_state = "lavarocks"
desc = "A pile of rocks."

View File

@@ -0,0 +1,178 @@
GLOBAL_LIST_INIT(ore_probability, list(/obj/item/stack/ore/uranium = 50,
/obj/item/stack/ore/iron = 100,
/obj/item/stack/ore/plasma = 75,
/obj/item/stack/ore/silver = 50,
/obj/item/stack/ore/gold = 50,
/obj/item/stack/ore/diamond = 25,
/obj/item/stack/ore/bananium = 5,
/obj/item/stack/ore/titanium = 75))
/obj/structure/spawner/ice_moon
name = "cave entrance"
desc = "A hole in the ground, filled with monsters ready to defend it."
icon = 'icons/mob/nest.dmi'
icon_state = "hole"
faction = list("mining")
max_mobs = 3
max_integrity = 250
mob_types = list(/mob/living/simple_animal/hostile/asteroid/wolf)
move_resist = INFINITY
anchored = TRUE
/obj/structure/spawner/ice_moon/Initialize()
. = ..()
clear_rock()
/**
* Clears rocks around the spawner when it is created
*
*/
/obj/structure/spawner/ice_moon/proc/clear_rock()
for(var/turf/F in RANGE_TURFS(2, src))
if(abs(src.x - F.x) + abs(src.y - F.y) > 3)
continue
if(ismineralturf(F))
var/turf/closed/mineral/M = F
M.ScrapeAway(null, CHANGETURF_IGNORE_AIR)
/obj/structure/spawner/ice_moon/deconstruct(disassembled)
destroy_effect()
drop_loot()
return ..()
/**
* Effects and messages created when the spawner is destroyed
*
*/
/obj/structure/spawner/ice_moon/proc/destroy_effect()
playsound(loc,'sound/effects/explosionfar.ogg', 200, TRUE)
visible_message("<span class='boldannounce'>[src] collapses, sealing everything inside!</span>\n<span class='warning'>Ores fall out of the cave as it is destroyed!</span>")
/**
* Drops items after the spawner is destroyed
*
*/
/obj/structure/spawner/ice_moon/proc/drop_loot()
for(var/type in GLOB.ore_probability)
var/chance = GLOB.ore_probability[type]
if(!prob(chance))
continue
new type(loc, rand(5, 10))
/obj/structure/spawner/ice_moon/polarbear
max_mobs = 1
spawn_time = 60 SECONDS
mob_types = list(/mob/living/simple_animal/hostile/asteroid/polarbear)
/obj/structure/spawner/ice_moon/polarbear/clear_rock()
for(var/turf/F in RANGE_TURFS(1, src))
if(ismineralturf(F))
var/turf/closed/mineral/M = F
M.ScrapeAway(null, CHANGETURF_IGNORE_AIR)
/obj/structure/spawner/ice_moon/demonic_portal
name = "demonic portal"
desc = "A portal that goes to another world, normal creatures couldn't survive there."
icon_state = "nether"
mob_types = list(/mob/living/simple_animal/hostile/asteroid/ice_demon)
light_range = 1
light_color = LIGHT_COLOR_RED
/obj/structure/spawner/ice_moon/demonic_portal/clear_rock()
for(var/turf/F in RANGE_TURFS(3, src))
if(abs(src.x - F.x) + abs(src.y - F.y) > 5)
continue
if(ismineralturf(F))
var/turf/closed/mineral/M = F
M.ScrapeAway(null, CHANGETURF_IGNORE_AIR)
/obj/structure/spawner/ice_moon/demonic_portal/destroy_effect()
new /obj/effect/collapsing_demonic_portal(loc)
/obj/structure/spawner/ice_moon/demonic_portal/drop_loot()
return
/obj/structure/spawner/ice_moon/demonic_portal/ice_whelp
mob_types = list(/mob/living/simple_animal/hostile/asteroid/ice_whelp)
/obj/structure/spawner/ice_moon/demonic_portal/snowlegion
mob_types = list(/mob/living/simple_animal/hostile/asteroid/hivelord/legion/snow/tendril)
/obj/effect/collapsing_demonic_portal
name = "collapsing demonic portal"
desc = "It's slowly fading!"
layer = TABLE_LAYER
icon = 'icons/mob/nest.dmi'
icon_state = "nether"
anchored = TRUE
density = TRUE
/obj/effect/collapsing_demonic_portal/Initialize()
. = ..()
playsound(loc,'sound/effects/tendril_destroyed.ogg', 200, FALSE, 50, TRUE, TRUE)
visible_message("<span class='boldannounce'>[src] begins to collapse, cutting it off from this world!</span>")
animate(src, transform = matrix().Scale(0, 1), alpha = 50, time = 5 SECONDS)
addtimer(CALLBACK(src, .proc/collapse), 5 SECONDS)
/obj/effect/collapsing_demonic_portal/proc/collapse()
visible_message("<span class='warning'>Something slips out of [src]!</span>")
var/loot = rand(1, 28)
switch(loot)
if(1)
new /obj/item/clothing/suit/space/hardsuit/cult(loc)
if(2)
new /obj/item/clothing/glasses/godeye(loc)
if(3)
new /obj/item/reagent_containers/glass/bottle/potion/flight(loc)
if(4)
new /obj/item/organ/heart/cursed/wizard(loc)
if(5)
new /obj/item/jacobs_ladder(loc)
if(6)
new /obj/item/rod_of_asclepius(loc)
if(7)
new /obj/item/warp_cube/red(loc)
if(8)
new /obj/item/wisp_lantern(loc)
if(9)
new /obj/item/immortality_talisman(loc)
if(10)
new /obj/item/book/granter/spell/summonitem(loc)
if(11)
new /obj/item/clothing/neck/necklace/memento_mori(loc)
if(12)
new /obj/item/borg/upgrade/modkit/lifesteal(loc)
new /obj/item/bedsheet/cult(loc)
if(13)
new /obj/item/disk/design_disk/modkit_disc/mob_and_turf_aoe(loc)
if(14)
new /obj/item/disk/design_disk/modkit_disc/bounty(loc)
if(15)
new /obj/item/ship_in_a_bottle(loc)
new /obj/item/oar(loc)
if(16)
new /obj/item/seeds/gatfruit(loc)
if(17)
new /obj/item/reagent_containers/food/drinks/drinkingglass/filled/nuka_cola(loc)
if(18)
new /obj/item/assembly/signaler/anomaly/bluespace(loc)
if(19)
new /obj/item/disk/design_disk/modkit_disc/resonator_blast(loc)
if(20)
new /obj/item/disk/design_disk/modkit_disc/rapid_repeater(loc)
if(21)
new /obj/item/slimepotion/transference(loc)
if(22)
new /obj/item/slime_extract/adamantine(loc)
if(23)
new /obj/item/weldingtool/abductor(loc)
if(24)
new /obj/structure/elite_tumor(loc)
if(25)
new /mob/living/simple_animal/hostile/retaliate/clown/clownhulk(loc)
if(26)
new /obj/item/clothing/shoes/winterboots/ice_boots(loc)
if(27)
new /obj/item/book/granter/spell/sacredflame(loc)
if(28)
new /mob/living/simple_animal/hostile/megafauna/blood_drunk_miner/doom(loc)

View File

@@ -0,0 +1,86 @@
//If you look at the "geyser_soup" overlay icon_state, you'll see that the first frame has 25 ticks.
//That's because the first 18~ ticks are completely skipped for some ungodly weird fucking byond reason
/obj/structure/geyser
name = "geyser"
icon = 'icons/obj/lavaland/terrain.dmi'
icon_state = "geyser"
anchored = TRUE
var/erupting_state = null //set to null to get it greyscaled from "[icon_state]_soup". Not very usable with the whole random thing, but more types can be added if you change the spawn prob
var/activated = FALSE //whether we are active and generating chems
var/reagent_id = /datum/reagent/fuel/oil
var/potency = 2 //how much reagents we add every process (2 seconds)
var/max_volume = 500
var/start_volume = 50
/obj/structure/geyser/proc/start_chemming()
activated = TRUE
create_reagents(max_volume, DRAINABLE)
reagents.add_reagent(reagent_id, start_volume)
START_PROCESSING(SSfluids, src) //It's main function is to be plumbed, so use SSfluids
if(erupting_state)
icon_state = erupting_state
else
var/mutable_appearance/I = mutable_appearance('icons/obj/lavaland/terrain.dmi', "[icon_state]_soup")
I.color = mix_color_from_reagents(reagents.reagent_list)
add_overlay(I)
/obj/structure/geyser/process()
if(activated && reagents.total_volume <= reagents.maximum_volume) //this is also evaluated in add_reagent, but from my understanding proc calls are expensive
reagents.add_reagent(reagent_id, potency)
/obj/structure/geyser/plunger_act(obj/item/plunger/P, mob/living/user, _reinforced)
if(!_reinforced)
to_chat(user, "<span class='warning'>The [P.name] isn't strong enough!</span>")
return
if(activated)
to_chat(user, "<span class'warning'>The [name] is already active!</span>")
return
to_chat(user, "<span class='notice'>You start vigorously plunging [src]!</span>")
if(do_after(user, 50 * P.plunge_mod, target = src) && !activated)
start_chemming()
/obj/structure/geyser/random
erupting_state = null
var/list/options = list(/datum/reagent/clf3 = 10, /datum/reagent/water/hollowwater = 10, /datum/reagent/medicine/omnizine/protozine = 6, /datum/reagent/wittel = 1)
/obj/structure/geyser/random/Initialize()
. = ..()
reagent_id = pickweight(options)
/obj/item/plunger
name = "plunger"
desc = "It's a plunger for plunging."
icon = 'icons/obj/watercloset.dmi'
icon_state = "plunger"
slot_flags = ITEM_SLOT_MASK
var/plunge_mod = 1 //time*plunge_mod = total time we take to plunge an object
var/reinforced = FALSE //whether we do heavy duty stuff like geysers
/obj/item/plunger/attack_obj(obj/O, mob/living/user)
if(!O.plunger_act(src, user, reinforced))
return ..()
/obj/item/plunger/throw_impact(atom/hit_atom, datum/thrownthing/tt)
. = ..()
if(tt.target_zone != BODY_ZONE_HEAD)
return
if(iscarbon(hit_atom))
var/mob/living/carbon/H = hit_atom
if(!H.wear_mask)
H.equip_to_slot_if_possible(src, ITEM_SLOT_MASK)
H.visible_message("<span class='warning'>The plunger slams into [H]'s face!</span>", "<span class='warning'>The plunger suctions to your face!</span>")
/obj/item/plunger/reinforced
name = "reinforced plunger"
desc = "It's an M. 7 Reinforced Plunger© for heavy duty plunging."
icon_state = "reinforced_plunger"
reinforced = TRUE
plunge_mod = 0.8
custom_premium_price = 1200

View File

@@ -25,6 +25,9 @@
/obj/structure/spawner/lavaland/legion
mob_types = list(/mob/living/simple_animal/hostile/asteroid/hivelord/legion/tendril)
/obj/structure/spawner/lavaland/icewatcher
mob_types = list(/mob/living/simple_animal/hostile/asteroid/basilisk/watcher/icewing)
GLOBAL_LIST_INIT(tendrils, list())
/obj/structure/spawner/lavaland/Initialize()
. = ..()
@@ -94,4 +97,4 @@ GLOBAL_LIST_INIT(tendrils, list())
for(var/turf/T in range(2,src))
if(!T.density)
T.TerraformTurf(/turf/open/chasm/lavaland, /turf/open/chasm/lavaland, flags = CHANGETURF_INHERIT_AIR)
qdel(src)
qdel(src)

View File

@@ -134,6 +134,15 @@
icon = 'icons/turf/walls.dmi'
icon_state = "icerock"
/turf/closed/indestructible/rock/snow/ice/ore
icon = 'icons/turf/walls/icerock_wall.dmi'
icon_state = "icerock"
smooth = SMOOTH_MORE|SMOOTH_BORDER
canSmoothWith = list (/turf/closed)
pixel_x = -4
pixel_y = -4
/turf/closed/indestructible/paper
name = "thick paper wall"
desc = "A wall layered with impenetrable sheets of paper."

View File

@@ -110,6 +110,9 @@
if(prob(12))
icon_state = "necro[rand(2,3)]"
/turf/open/indestructible/necropolis/ice
initial_gas_mix = ICEMOON_DEFAULT_ATMOS
/turf/open/indestructible/necropolis/air
initial_gas_mix = OPENTURF_DEFAULT_ATMOS

View File

@@ -146,3 +146,13 @@ GLOBAL_DATUM_INIT(openspace_backdrop_one_for_all, /atom/movable/openspace_backdr
PlaceOnTop(/turf/open/floor/plating, flags = CHANGETURF_INHERIT_AIR)
return TRUE
return FALSE
/turf/open/openspace/icemoon
name = "ice chasm"
baseturfs = /turf/open/openspace/icemoon
can_cover_up = FALSE
can_build_on = FALSE
initial_gas_mix = ICEMOON_DEFAULT_ATMOS
/turf/open/openspace/icemoon/can_zFall(atom/movable/A, levels = 1, turf/target)
return TRUE

View File

@@ -88,6 +88,15 @@
light_power = 0.65 //less bright, too
light_color = LIGHT_COLOR_LAVA //let's just say you're falling into lava, that makes sense right
// Chasms for Ice moon, with planetary atmos and glow
/turf/open/chasm/icemoon
icon = 'icons/turf/floors/icechasms.dmi'
initial_gas_mix = ICEMOON_DEFAULT_ATMOS
planetary_atmos = TRUE
baseturfs = /turf/open/chasm/icemoon
light_range = 1.9
light_power = 0.65
light_color = LIGHT_COLOR_PURPLE
// Chasms for the jungle, with planetary atmos and a different icon
/turf/open/chasm/jungle
@@ -115,4 +124,4 @@
. = ..()
var/turf/T = safepick(get_area_turfs(/area/fabric_of_reality))
if(T)
set_target(T)
set_target(T)

View File

@@ -48,7 +48,9 @@
"oldburning","light-on-r","light-on-y","light-on-g","light-on-b", "wood", "carpetsymbol", "carpetstar",
"carpetcorner", "carpetside", "carpet", "ironsand1", "ironsand2", "ironsand3", "ironsand4", "ironsand5",
"ironsand6", "ironsand7", "ironsand8", "ironsand9", "ironsand10", "ironsand11",
"ironsand12", "ironsand13", "ironsand14", "ironsand15")
"ironsand12", "ironsand13", "ironsand14", "ironsand15",
"snow", "snow0", "snow1", "snow2", "snow3", "snow4", "snow5", "snow6", "snow7", "snow8", "snow9", "snow10", "snow11", "snow12", "snow-ice", "snow_dug",
"unsmooth", "smooth", "1-i", "2-i", "3-i", "4-i", "1-n", "2-n", "3-s", "4-s", "1-w", "2-e", "3-w", "4-e", "1-nw", "2-ne", "3-sw", "4-se", "1-f", "2-f", "3-f", "4-f")
if(broken || burnt || (icon_state in icons_to_ignore_at_floor_init)) //so damaged/burned tiles or plating icons aren't saved as the default
icon_regular_floor = "floor"
else

View File

@@ -13,11 +13,15 @@
barefootstep = FOOTSTEP_SAND
clawfootstep = FOOTSTEP_SAND
heavyfootstep = FOOTSTEP_GENERIC_HEAVY
/// Environment type for the turf
var/environment_type = "asteroid"
/// Base turf type to be created by the tunnel
var/turf_type = /turf/open/floor/plating/asteroid //Because caves do whacky shit to revert to normal
var/floor_variance = 20 //probability floor has a different icon state
/// Probability the floor has a different icon state
var/floor_variance = 20
attachment_holes = FALSE
var/obj/item/stack/digResult = /obj/item/stack/ore/glass/basalt
/// Whether the turf has been dug or not
var/dug
/turf/open/floor/plating/asteroid/Initialize()
@@ -27,6 +31,7 @@
if(prob(floor_variance))
icon_state = "[environment_type][rand(0,12)]"
/// Drops itemstack when dug and changes icon
/turf/open/floor/plating/asteroid/proc/getDug()
new digResult(src, 5)
if(postdig_icon_change)
@@ -35,6 +40,7 @@
icon_state = "[environment_type]_dug"
dug = TRUE
/// If the user can dig the turf
/turf/open/floor/plating/asteroid/proc/can_dig(mob/user)
if(!dug)
return TRUE
@@ -135,16 +141,30 @@
#define SPAWN_BUBBLEGUM 6
/turf/open/floor/plating/asteroid/airless/cave
/// Length of the tunnel
var/length = 100
/// Mobs that can spawn in the tunnel, weighted list
var/list/mob_spawn_list
/// Megafauna that can spawn in the tunnel, weighted list
var/list/megafauna_spawn_list
/// Flora that can spawn in the tunnel, weighted list
var/list/flora_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
var/forward_cave_dir = 1
/// Backwards cave direction for tracking
var/backward_cave_dir = 2
/// If the tunnel is moving backwards
var/going_backwards = TRUE
/// If this is a cave creating type
var/has_data = FALSE
/// 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
@@ -163,6 +183,47 @@
/turf/open/floor/plating/asteroid/airless/cave/volcanic/has_data //subtype for producing a tunnel with given data
has_data = TRUE
/turf/open/floor/plating/asteroid/airless/cave/snow
gender = PLURAL
name = "snow"
desc = "Looks cold."
icon = 'icons/turf/snow.dmi'
baseturfs = /turf/open/floor/plating/asteroid/snow/icemoon
icon_state = "snow"
icon_plating = "snow"
initial_gas_mix = ICEMOON_DEFAULT_ATMOS
slowdown = 2
environment_type = "snow"
flags_1 = NONE
planetary_atmos = TRUE
burnt_states = list("snow_dug")
bullet_sizzle = TRUE
bullet_bounce_sound = null
digResult = /obj/item/stack/sheet/mineral/snow
mob_spawn_list = list(/mob/living/simple_animal/hostile/asteroid/wolf = 50, /obj/structure/spawner/ice_moon = 3, \
/mob/living/simple_animal/hostile/asteroid/polarbear = 30, /obj/structure/spawner/ice_moon/polarbear = 3, \
/mob/living/simple_animal/hostile/asteroid/hivelord/legion/snow = 50, /mob/living/simple_animal/hostile/asteroid/goldgrub = 10)
flora_spawn_list = list(/obj/structure/flora/tree/pine = 2, /obj/structure/flora/grass/both = 12)
data_having_type = /turf/open/floor/plating/asteroid/airless/cave/snow/has_data
turf_type = /turf/open/floor/plating/asteroid/snow/icemoon
choose_turf_type = list(/turf/open/floor/plating/asteroid/snow/icemoon = 19, /turf/open/floor/plating/ice/icemoon = 1)
pick_tunnel_width = list("1" = 6, "2" = 1)
/turf/open/floor/plating/asteroid/airless/cave/snow/underground
mob_spawn_list = list(/mob/living/simple_animal/hostile/asteroid/ice_demon = 50, /obj/structure/spawner/ice_moon/demonic_portal = 3, \
/mob/living/simple_animal/hostile/asteroid/ice_whelp = 30, /obj/structure/spawner/ice_moon/demonic_portal/ice_whelp = 3, \
/mob/living/simple_animal/hostile/asteroid/hivelord/legion/snow = 50, /obj/structure/spawner/ice_moon/demonic_portal/snowlegion = 3)
flora_spawn_list = list(/obj/structure/flora/rock/icy = 6, /obj/structure/flora/rock/pile/icy = 6)
data_having_type = /turf/open/floor/plating/asteroid/airless/cave/snow/underground/has_data
choose_turf_type = null
/turf/open/floor/plating/asteroid/airless/cave/snow/has_data //subtype for producing a tunnel with given data
has_data = TRUE
/turf/open/floor/plating/asteroid/airless/cave/snow/underground/has_data //subtype for producing a tunnel with given data
has_data = TRUE
/turf/open/floor/plating/asteroid/airless/cave/Initialize()
if (!mob_spawn_list)
mob_spawn_list = list(/mob/living/simple_animal/hostile/asteroid/goldgrub = 1, /mob/living/simple_animal/hostile/asteroid/goliath = 5, /mob/living/simple_animal/hostile/asteroid/basilisk = 4, /mob/living/simple_animal/hostile/asteroid/hivelord = 3)
@@ -175,6 +236,7 @@
if(!has_data)
produce_tunnel_from_data()
/// Sets the tunnel length and direction
/turf/open/floor/plating/asteroid/airless/cave/proc/get_cave_data(set_length, exclude_dir = -1)
// If set_length (arg1) isn't defined, get a random length; otherwise assign our length to the length arg.
if(!set_length)
@@ -187,6 +249,7 @@
// Get the opposite direction of our facing direction
backward_cave_dir = angle2dir(dir2angle(forward_cave_dir) + 180)
/// Gets the tunnel length and direction then makes the tunnel
/turf/open/floor/plating/asteroid/airless/cave/proc/produce_tunnel_from_data(tunnel_length, excluded_dir = -1)
get_cave_data(tunnel_length, excluded_dir)
// Make our tunnels
@@ -196,10 +259,22 @@
// Kill ourselves by replacing ourselves with a normal floor.
SpawnFloor(src)
/**
* Makes the tunnel and spawns things inside of it
*
* Picks a tunnel width for the tunnel and then starts spawning turfs in the direction it moves in
* Can randomly change directions of the tunnel, stops if it hits the edge of the map, or a no tunnel area
* Can randomly make new tunnels out of itself
*
*/
/turf/open/floor/plating/asteroid/airless/cave/proc/make_tunnel(dir)
var/turf/closed/mineral/tunnel = src
var/next_angle = pick(45, -45)
var/tunnel_width = 1
if(pick_tunnel_width)
tunnel_width = text2num(pickweight(pick_tunnel_width))
for(var/i = 0; i < length; i++)
if(!sanity)
break
@@ -210,9 +285,11 @@
// Expand the edges of our tunnel
for(var/edge_angle in L)
var/turf/closed/mineral/edge = get_step(tunnel, angle2dir(dir2angle(dir) + edge_angle))
if(istype(edge))
SpawnFloor(edge)
var/turf/closed/mineral/edge = tunnel
for(var/current_tunnel_width = 1 to tunnel_width)
edge = get_step(edge, angle2dir(dir2angle(dir) + edge_angle))
if(istype(edge))
SpawnFloor(edge)
if(!sanity)
break
@@ -223,9 +300,12 @@
if(istype(tunnel))
// Small chance to have forks in our tunnel; otherwise dig our tunnel.
if(i > 3 && prob(20))
if(istype(tunnel.loc, /area/mine/explored) || (istype(tunnel.loc, /area/lavaland/surface/outdoors) && !istype(tunnel.loc, /area/lavaland/surface/outdoors/unexplored)))
sanity = 0
break
if(isarea(tunnel.loc))
var/area/A = tunnel.loc
if(!A.tunnel_allowed)
sanity = 0
break
var/turf/open/floor/plating/asteroid/airless/cave/C = tunnel.ChangeTurf(data_having_type, null, CHANGETURF_IGNORE_AIR)
C.going_backwards = FALSE
C.produce_tunnel_from_data(rand(10, 15), dir)
@@ -241,26 +321,35 @@
setDir(angle2dir(dir2angle(dir) )+ next_angle)
/// 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)
for(var/S in RANGE_TURFS(1, src))
var/turf/NT = S
if(!NT || isspaceturf(NT) || istype(NT.loc, /area/mine/explored) || (istype(NT.loc, /area/lavaland/surface/outdoors) && !istype(NT.loc, /area/lavaland/surface/outdoors/unexplored)))
sanity = 0
break
if(!sanity)
var/area/A = T.loc
if(!A.tunnel_allowed)
sanity = 0
return
SpawnFlora(T)
SpawnMonster(T)
if(choose_turf_type)
turf_type = pickweight(choose_turf_type)
if(turf_type == initial(turf_type)) // Don't spawn different turf types under flora or terrain
var/spawned_flora = FALSE
if(is_mining_level(z))
spawned_flora = SpawnFlora(T)
if(!spawned_flora) // no rocks beneath mob spawners / mobs.
SpawnMonster(T)
T.ChangeTurf(turf_type, null, CHANGETURF_IGNORE_AIR)
/// Spawns a random mob or megafauna in the tunnel
/turf/open/floor/plating/asteroid/airless/cave/proc/SpawnMonster(turf/T)
if(!isarea(loc))
return
var/area/A = loc
if(prob(30))
if(istype(loc, /area/mine/explored) || !istype(loc, /area/lavaland/surface/outdoors/unexplored))
if(!A.mob_spawn_allowed)
return
var/randumb = pickweight(mob_spawn_list)
if(!randumb)
return
while(randumb == SPAWN_MEGAFAUNA)
if(istype(loc, /area/lavaland/surface/outdoors/unexplored/danger)) //this is danger. it's boss time.
if(A.megafauna_spawn_allowed && megafauna_spawn_list && megafauna_spawn_list.len) //this is danger. it's boss time.
var/maybe_boss = pickweight(megafauna_spawn_list)
if(megafauna_spawn_list[maybe_boss])
randumb = maybe_boss
@@ -278,22 +367,26 @@
return //prevents tendrils spawning in each other's collapse range
new randumb(T)
return
return TRUE
#undef SPAWN_MEGAFAUNA
#undef SPAWN_BUBBLEGUM
/// Spawns a random flora in the tunnel, can spawn clumps of them.
/turf/open/floor/plating/asteroid/airless/cave/proc/SpawnFlora(turf/T)
if(prob(12))
if(istype(loc, /area/mine/explored) || istype(loc, /area/lavaland/surface/outdoors/explored))
return
if(isarea(loc))
var/area/A = loc
if(!A.flora_allowed)
return
var/randumb = pickweight(flora_spawn_list)
for(var/obj/structure/flora/ash/F in range(4, T)) //Allows for growing patches, but not ridiculous stacks of flora
if(!randumb)
return
for(var/obj/structure/flora/F in range(4, T)) // Allows for growing patches, but not ridiculous stacks of flora
if(!istype(F, randumb))
return
new randumb(T)
return TRUE
/turf/open/floor/plating/asteroid/snow
gender = PLURAL
@@ -322,6 +415,15 @@
return TRUE
return FALSE
/turf/open/floor/plating/asteroid/snow/icemoon
baseturfs = /turf/open/floor/plating/asteroid/snow/icemoon
initial_gas_mix = ICEMOON_DEFAULT_ATMOS
/turf/open/lava/plasma/ice_moon
initial_gas_mix = ICEMOON_DEFAULT_ATMOS
baseturfs = /turf/open/lava/plasma/ice_moon
planetary_atmos = TRUE
/turf/open/floor/plating/asteroid/snow/ice
name = "icy snow"
desc = "Looks colder."
@@ -336,6 +438,15 @@
clawfootstep = FOOTSTEP_HARD_CLAW
heavyfootstep = FOOTSTEP_GENERIC_HEAVY
/turf/open/floor/plating/asteroid/snow/ice/icemoon
baseturfs = /turf/open/floor/plating/asteroid/snow/ice/icemoon
initial_gas_mix = ICEMOON_DEFAULT_ATMOS
planetary_atmos = TRUE
/turf/open/floor/plating/asteroid/snow/ice/icemoon/solarpanel
icon = 'icons/turf/floors.dmi'
icon_state = "solarpanel"
/turf/open/floor/plating/asteroid/snow/ice/burn_tile()
return FALSE
@@ -347,4 +458,4 @@
/turf/open/floor/plating/asteroid/snow/atmosphere
initial_gas_mix = FROZEN_ATMOS
planetary_atmos = FALSE
planetary_atmos = FALSE

View File

@@ -3,6 +3,10 @@
icon_state = "plating"
initial_gas_mix = AIRLESS_ATMOS
/turf/open/floor/plating/icemoon
icon_state = "plating"
initial_gas_mix = ICEMOON_DEFAULT_ATMOS
/turf/open/floor/plating/abductor
name = "alien floor"
icon_state = "alienpod1"
@@ -209,6 +213,8 @@
/turf/open/floor/plating/ice/burn_tile()
return
/turf/open/floor/plating/ice/icemoon
initial_gas_mix = ICEMOON_DEFAULT_ATMOS
/turf/open/floor/plating/snowed
name = "snowed-over plating"
@@ -240,4 +246,6 @@
/turf/open/floor/plating/snowed/temperatre
temperature = 255.37
/turf/open/floor/plating/snowed/smoothed/icemoon
initial_gas_mix = ICEMOON_DEFAULT_ATMOS

View File

@@ -147,6 +147,11 @@
var/mineralChance = 13
var/display_icon_state = "rock"
/turf/closed/mineral/random/more_caves
mineralSpawnChanceList = list(/turf/closed/mineral/uranium = 5, /turf/closed/mineral/diamond = 1, /turf/closed/mineral/gold = 10,
/turf/closed/mineral/silver = 12, /turf/closed/mineral/plasma = 20, /turf/closed/mineral/iron = 40, /turf/closed/mineral/titanium = 11,
/turf/closed/mineral/gibtonite = 4, /turf/open/floor/plating/asteroid/airless/cave = 15, /turf/closed/mineral/bscrystal = 1)
/turf/closed/mineral/random/Initialize()
mineralSpawnChanceList = typelist("mineralSpawnChanceList", mineralSpawnChanceList)
@@ -195,11 +200,27 @@
turf_type = /turf/open/floor/plating/asteroid/basalt/lava_land_surface
baseturfs = /turf/open/floor/plating/asteroid/basalt/lava_land_surface
initial_gas_mix = LAVALAND_DEFAULT_ATMOS
defer_change = 1
defer_change = TRUE
mineralSpawnChanceList = list(
/turf/closed/mineral/uranium/volcanic = 35, /turf/closed/mineral/diamond/volcanic = 30, /turf/closed/mineral/gold/volcanic = 45, /turf/closed/mineral/titanium/volcanic = 45,
/turf/closed/mineral/silver/volcanic = 50, /turf/closed/mineral/plasma/volcanic = 50, /turf/closed/mineral/bscrystal/volcanic = 20)
/turf/closed/mineral/random/high_chance/snow
name = "snowy mountainside"
icon = 'icons/turf/mining.dmi'
smooth_icon = 'icons/turf/walls/mountain_wall.dmi'
icon_state = "mountainrock"
smooth = SMOOTH_MORE|SMOOTH_BORDER
canSmoothWith = list (/turf/closed)
defer_change = TRUE
environment_type = "snow"
turf_type = /turf/open/floor/plating/asteroid/snow/icemoon
baseturfs = /turf/open/floor/plating/asteroid/snow/icemoon
initial_gas_mix = ICEMOON_DEFAULT_ATMOS
mineralSpawnChanceList = list(
/turf/closed/mineral/uranium/ice/icemoon = 35, /turf/closed/mineral/diamond/ice/icemoon = 30, /turf/closed/mineral/gold/ice/icemoon = 45, /turf/closed/mineral/titanium/ice/icemoon = 45,
/turf/closed/mineral/silver/ice/icemoon = 50, /turf/closed/mineral/plasma/ice/icemoon = 50, /turf/closed/mineral/bscrystal/ice/icemoon = 20)
/turf/closed/mineral/random/high_chance/earth_like
icon_state = "rock_highchance_oxy"
turf_type = /turf/open/floor/plating/asteroid
@@ -236,7 +257,7 @@
turf_type = /turf/open/floor/plating/asteroid/basalt/lava_land_surface
baseturfs = /turf/open/floor/plating/asteroid/basalt/lava_land_surface
initial_gas_mix = LAVALAND_DEFAULT_ATMOS
defer_change = 1
defer_change = TRUE
mineralChance = 10
mineralSpawnChanceList = list(
@@ -244,6 +265,36 @@
/turf/closed/mineral/silver/volcanic = 12, /turf/closed/mineral/plasma/volcanic = 20, /turf/closed/mineral/iron/volcanic = 40,
/turf/closed/mineral/gibtonite/volcanic = 4, /turf/open/floor/plating/asteroid/airless/cave/volcanic = 1, /turf/closed/mineral/bscrystal/volcanic = 1)
/turf/closed/mineral/random/volcanic/more_caves
mineralSpawnChanceList = list(
/turf/closed/mineral/uranium/volcanic = 5, /turf/closed/mineral/diamond/volcanic = 1, /turf/closed/mineral/gold/volcanic = 10, /turf/closed/mineral/titanium/volcanic = 11,
/turf/closed/mineral/silver/volcanic = 12, /turf/closed/mineral/plasma/volcanic = 20, /turf/closed/mineral/iron/volcanic = 40,
/turf/closed/mineral/gibtonite/volcanic = 4, /turf/open/floor/plating/asteroid/airless/cave/volcanic = 15, /turf/closed/mineral/bscrystal/volcanic = 1)
/turf/closed/mineral/random/snow
name = "snowy mountainside"
icon = 'icons/turf/mining.dmi'
smooth_icon = 'icons/turf/walls/mountain_wall.dmi'
icon_state = "mountainrock"
smooth = SMOOTH_MORE|SMOOTH_BORDER
canSmoothWith = list (/turf/closed)
defer_change = TRUE
environment_type = "snow"
turf_type = /turf/open/floor/plating/asteroid/snow/icemoon
baseturfs = /turf/open/floor/plating/asteroid/snow/icemoon
initial_gas_mix = ICEMOON_DEFAULT_ATMOS
mineralChance = 10
mineralSpawnChanceList = list(
/turf/closed/mineral/uranium/ice/icemoon = 5, /turf/closed/mineral/diamond/ice/icemoon = 1, /turf/closed/mineral/gold/ice/icemoon = 10, /turf/closed/mineral/titanium/ice/icemoon = 11,
/turf/closed/mineral/silver/ice/icemoon = 12, /turf/closed/mineral/plasma/ice/icemoon = 20, /turf/closed/mineral/iron/ice/icemoon = 40,
/turf/closed/mineral/gibtonite/ice/icemoon = 4, /turf/open/floor/plating/asteroid/airless/cave/snow = 1, /turf/closed/mineral/bscrystal/ice/icemoon = 1)
/turf/closed/mineral/random/snow/no_caves
mineralSpawnChanceList = list(
/turf/closed/mineral/uranium/ice/icemoon = 5, /turf/closed/mineral/diamond/ice/icemoon = 1, /turf/closed/mineral/gold/ice/icemoon = 10, /turf/closed/mineral/titanium/ice/icemoon = 11,
/turf/closed/mineral/silver/ice/icemoon = 12, /turf/closed/mineral/plasma/ice/icemoon = 20, /turf/closed/mineral/iron/ice/icemoon = 40,
/turf/closed/mineral/gibtonite/ice/icemoon = 4, /turf/closed/mineral/bscrystal/ice/icemoon = 1)
/turf/closed/mineral/random/labormineral
mineralSpawnChanceList = list(
@@ -252,18 +303,51 @@
/turf/closed/mineral/gibtonite = 2)
icon_state = "rock_labor"
/turf/closed/mineral/random/snow/underground
mineralSpawnChanceList = list(
/turf/closed/mineral/uranium/ice/icemoon = 5, /turf/closed/mineral/diamond/ice/icemoon = 1, /turf/closed/mineral/gold/ice/icemoon = 10, /turf/closed/mineral/titanium/ice/icemoon = 11,
/turf/closed/mineral/silver/ice/icemoon = 12, /turf/closed/mineral/plasma/ice/icemoon = 20, /turf/closed/mineral/iron/ice/icemoon = 40,
/turf/closed/mineral/gibtonite/ice/icemoon = 4, /turf/open/floor/plating/asteroid/airless/cave/snow/underground = 1, /turf/closed/mineral/bscrystal/ice/icemoon = 1)
/turf/closed/mineral/random/snow/more_caves
mineralSpawnChanceList = list(
/turf/closed/mineral/uranium/ice/icemoon = 5, /turf/closed/mineral/diamond/ice/icemoon = 1, /turf/closed/mineral/gold/ice/icemoon = 10, /turf/closed/mineral/titanium/ice/icemoon = 11,
/turf/closed/mineral/silver/ice/icemoon = 12, /turf/closed/mineral/plasma/ice/icemoon = 20, /turf/closed/mineral/iron/ice/icemoon = 40,
/turf/closed/mineral/gibtonite/ice/icemoon = 4, /turf/open/floor/plating/asteroid/airless/cave/snow = 15, /turf/closed/mineral/bscrystal/ice/icemoon = 1)
/turf/closed/mineral/random/labormineral/volcanic
environment_type = "basalt"
turf_type = /turf/open/floor/plating/asteroid/basalt/lava_land_surface
baseturfs = /turf/open/floor/plating/asteroid/basalt/lava_land_surface
initial_gas_mix = LAVALAND_DEFAULT_ATMOS
defer_change = 1
defer_change = TRUE
mineralSpawnChanceList = list(
/turf/closed/mineral/uranium/volcanic = 3, /turf/closed/mineral/diamond/volcanic = 1, /turf/closed/mineral/gold/volcanic = 8, /turf/closed/mineral/titanium/volcanic = 8,
/turf/closed/mineral/silver/volcanic = 20, /turf/closed/mineral/plasma/volcanic = 30, /turf/closed/mineral/bscrystal/volcanic = 1, /turf/closed/mineral/gibtonite/volcanic = 2,
/turf/closed/mineral/iron/volcanic = 95)
//Subtypes for placing ores manually.
/turf/closed/mineral/random/labormineral/ice
name = "snowy mountainside"
icon = 'icons/turf/mining.dmi'
smooth_icon = 'icons/turf/walls/mountain_wall.dmi'
icon_state = "mountainrock"
smooth = SMOOTH_MORE|SMOOTH_BORDER
canSmoothWith = list (/turf/closed)
defer_change = TRUE
environment_type = "snow"
turf_type = /turf/open/floor/plating/asteroid/snow/icemoon
baseturfs = /turf/open/floor/plating/asteroid/snow/icemoon
initial_gas_mix = ICEMOON_DEFAULT_ATMOS
defer_change = TRUE
mineralSpawnChanceList = list(
/turf/closed/mineral/uranium/ice/icemoon = 3, /turf/closed/mineral/diamond/ice/icemoon = 1, /turf/closed/mineral/gold/ice/icemoon = 8, /turf/closed/mineral/titanium/ice/icemoon = 8,
/turf/closed/mineral/silver/ice/icemoon = 20, /turf/closed/mineral/plasma/ice/icemoon = 30, /turf/closed/mineral/bscrystal/ice/icemoon = 1, /turf/closed/mineral/gibtonite/ice/icemoon = 2,
/turf/closed/mineral/iron/ice/icemoon = 95)
/turf/closed/mineral/iron
mineralType = /obj/item/stack/ore/iron
@@ -294,6 +378,11 @@
initial_gas_mix = FROZEN_ATMOS
defer_change = TRUE
/turf/closed/mineral/iron/ice/icemoon
turf_type = /turf/open/floor/plating/asteroid/snow/ice/icemoon
baseturfs = /turf/open/floor/plating/asteroid/snow/ice/icemoon
initial_gas_mix = ICEMOON_DEFAULT_ATMOS
/turf/closed/mineral/uranium
mineralType = /obj/item/stack/ore/uranium
@@ -306,7 +395,21 @@
turf_type = /turf/open/floor/plating/asteroid/basalt/lava_land_surface
baseturfs = /turf/open/floor/plating/asteroid/basalt/lava_land_surface
initial_gas_mix = LAVALAND_DEFAULT_ATMOS
defer_change = 1
defer_change = TRUE
/turf/closed/mineral/uranium/ice
environment_type = "snow_cavern"
icon_state = "icerock_Uranium"
smooth_icon = 'icons/turf/walls/icerock_wall.dmi'
turf_type = /turf/open/floor/plating/asteroid/snow/ice
baseturfs = /turf/open/floor/plating/asteroid/snow/ice
initial_gas_mix = FROZEN_ATMOS
defer_change = TRUE
/turf/closed/mineral/uranium/ice/icemoon
turf_type = /turf/open/floor/plating/asteroid/snow/ice/icemoon
baseturfs = /turf/open/floor/plating/asteroid/snow/ice/icemoon
initial_gas_mix = ICEMOON_DEFAULT_ATMOS
/turf/closed/mineral/uranium/earth_like
icon_state = "rock_oxy"
@@ -327,7 +430,7 @@
turf_type = /turf/open/floor/plating/asteroid/basalt/lava_land_surface
baseturfs = /turf/open/floor/plating/asteroid/basalt/lava_land_surface
initial_gas_mix = LAVALAND_DEFAULT_ATMOS
defer_change = 1
defer_change = TRUE
/turf/closed/mineral/diamond/earth_like
icon_state = "rock_oxy"
@@ -345,6 +448,11 @@
initial_gas_mix = FROZEN_ATMOS
defer_change = TRUE
/turf/closed/mineral/diamond/ice/icemoon
turf_type = /turf/open/floor/plating/asteroid/snow/ice/icemoon
baseturfs = /turf/open/floor/plating/asteroid/snow/ice/icemoon
initial_gas_mix = ICEMOON_DEFAULT_ATMOS
/turf/closed/mineral/gold
mineralType = /obj/item/stack/ore/gold
@@ -357,7 +465,7 @@
turf_type = /turf/open/floor/plating/asteroid/basalt/lava_land_surface
baseturfs = /turf/open/floor/plating/asteroid/basalt/lava_land_surface
initial_gas_mix = LAVALAND_DEFAULT_ATMOS
defer_change = 1
defer_change = TRUE
/turf/closed/mineral/gold/earth_like
icon_state = "rock_oxy"
@@ -366,6 +474,19 @@
initial_gas_mix = OPENTURF_DEFAULT_ATMOS
defer_change = TRUE
/turf/closed/mineral/gold/ice
environment_type = "snow_cavern"
icon_state = "icerock_gold"
smooth_icon = 'icons/turf/walls/icerock_wall.dmi'
turf_type = /turf/open/floor/plating/asteroid/snow/ice
baseturfs = /turf/open/floor/plating/asteroid/snow/ice
initial_gas_mix = FROZEN_ATMOS
defer_change = TRUE
/turf/closed/mineral/gold/ice/icemoon
turf_type = /turf/open/floor/plating/asteroid/snow/ice/icemoon
baseturfs = /turf/open/floor/plating/asteroid/snow/ice/icemoon
initial_gas_mix = ICEMOON_DEFAULT_ATMOS
/turf/closed/mineral/silver
mineralType = /obj/item/stack/ore/silver
@@ -378,7 +499,7 @@
turf_type = /turf/open/floor/plating/asteroid/basalt/lava_land_surface
baseturfs = /turf/open/floor/plating/asteroid/basalt/lava_land_surface
initial_gas_mix = LAVALAND_DEFAULT_ATMOS
defer_change = 1
defer_change = TRUE
/turf/closed/mineral/silver/earth_like
icon_state = "rock_oxy"
@@ -387,6 +508,19 @@
initial_gas_mix = OPENTURF_DEFAULT_ATMOS
defer_change = TRUE
/turf/closed/mineral/silver/ice
environment_type = "snow_cavern"
icon_state = "icerock_silver"
smooth_icon = 'icons/turf/walls/icerock_wall.dmi'
turf_type = /turf/open/floor/plating/asteroid/snow/ice
baseturfs = /turf/open/floor/plating/asteroid/snow/ice
initial_gas_mix = FROZEN_ATMOS
defer_change = TRUE
/turf/closed/mineral/silver/ice/icemoon
turf_type = /turf/open/floor/plating/asteroid/snow/ice/icemoon
baseturfs = /turf/open/floor/plating/asteroid/snow/ice/icemoon
initial_gas_mix = ICEMOON_DEFAULT_ATMOS
/turf/closed/mineral/titanium
mineralType = /obj/item/stack/ore/titanium
@@ -399,7 +533,7 @@
turf_type = /turf/open/floor/plating/asteroid/basalt/lava_land_surface
baseturfs = /turf/open/floor/plating/asteroid/basalt/lava_land_surface
initial_gas_mix = LAVALAND_DEFAULT_ATMOS
defer_change = 1
defer_change = TRUE
/turf/closed/mineral/titanium/earth_like
icon_state = "rock_oxy"
@@ -408,6 +542,19 @@
initial_gas_mix = OPENTURF_DEFAULT_ATMOS
defer_change = TRUE
/turf/closed/mineral/titanium/ice
environment_type = "snow_cavern"
icon_state = "icerock_titanium"
smooth_icon = 'icons/turf/walls/icerock_wall.dmi'
turf_type = /turf/open/floor/plating/asteroid/snow/ice
baseturfs = /turf/open/floor/plating/asteroid/snow/ice
initial_gas_mix = FROZEN_ATMOS
defer_change = TRUE
/turf/closed/mineral/titanium/ice/icemoon
turf_type = /turf/open/floor/plating/asteroid/snow/ice/icemoon
baseturfs = /turf/open/floor/plating/asteroid/snow/ice/icemoon
initial_gas_mix = ICEMOON_DEFAULT_ATMOS
/turf/closed/mineral/plasma
mineralType = /obj/item/stack/ore/plasma
@@ -420,7 +567,7 @@
turf_type = /turf/open/floor/plating/asteroid/basalt/lava_land_surface
baseturfs = /turf/open/floor/plating/asteroid/basalt/lava_land_surface
initial_gas_mix = LAVALAND_DEFAULT_ATMOS
defer_change = 1
defer_change = TRUE
/turf/closed/mineral/plasma/earth_like
icon_state = "rock_oxy"
@@ -438,6 +585,10 @@
initial_gas_mix = FROZEN_ATMOS
defer_change = TRUE
/turf/closed/mineral/plasma/ice/icemoon
turf_type = /turf/open/floor/plating/asteroid/snow/ice/icemoon
baseturfs = /turf/open/floor/plating/asteroid/snow/ice/icemoon
initial_gas_mix = ICEMOON_DEFAULT_ATMOS
/turf/closed/mineral/bananium
@@ -454,6 +605,21 @@
initial_gas_mix = OPENTURF_DEFAULT_ATMOS
defer_change = TRUE
/turf/closed/mineral/bananium/ice
environment_type = "snow_cavern"
icon_state = "icerock_Bananium"
smooth_icon = 'icons/turf/walls/icerock_wall.dmi'
turf_type = /turf/open/floor/plating/asteroid/snow/ice
baseturfs = /turf/open/floor/plating/asteroid/snow/ice
initial_gas_mix = FROZEN_ATMOS
defer_change = TRUE
/turf/closed/mineral/bananium/ice/icemoon
turf_type = /turf/open/floor/plating/asteroid/snow/ice/icemoon
baseturfs = /turf/open/floor/plating/asteroid/snow/ice/icemoon
initial_gas_mix = ICEMOON_DEFAULT_ATMOS
/turf/closed/mineral/bscrystal
mineralType = /obj/item/stack/ore/bluespace_crystal
mineralAmt = 1
@@ -466,7 +632,7 @@
turf_type = /turf/open/floor/plating/asteroid/basalt/lava_land_surface
baseturfs = /turf/open/floor/plating/asteroid/basalt/lava_land_surface
initial_gas_mix = LAVALAND_DEFAULT_ATMOS
defer_change = 1
defer_change = TRUE
/turf/closed/mineral/bscrystal/earth_like
icon_state = "rock_oxy"
@@ -475,6 +641,19 @@
initial_gas_mix = OPENTURF_DEFAULT_ATMOS
defer_change = TRUE
/turf/closed/mineral/bscrystal/ice
environment_type = "snow_cavern"
icon_state = "icerock_BScrystal"
smooth_icon = 'icons/turf/walls/icerock_wall.dmi'
turf_type = /turf/open/floor/plating/asteroid/snow/ice
baseturfs = /turf/open/floor/plating/asteroid/snow/ice
initial_gas_mix = FROZEN_ATMOS
defer_change = TRUE
/turf/closed/mineral/bscrystal/ice/icemoon
turf_type = /turf/open/floor/plating/asteroid/snow/ice/icemoon
baseturfs = /turf/open/floor/plating/asteroid/snow/ice/icemoon
initial_gas_mix = ICEMOON_DEFAULT_ATMOS
/turf/closed/mineral/volcanic
environment_type = "basalt"
@@ -486,7 +665,7 @@
environment_type = "basalt"
turf_type = /turf/open/floor/plating/asteroid/basalt/lava_land_surface
baseturfs = /turf/open/floor/plating/asteroid/basalt/lava_land_surface
defer_change = 1
defer_change = TRUE
/turf/closed/mineral/earth_like
icon_state = "rock_oxy"
@@ -506,7 +685,7 @@
initial_gas_mix = LAVALAND_DEFAULT_ATMOS
environment_type = "waste"
turf_type = /turf/open/floor/plating/ashplanet/rocky
defer_change = 1
defer_change = TRUE
/turf/closed/mineral/snowmountain
name = "snowy mountainside"
@@ -521,6 +700,11 @@
turf_type = /turf/open/floor/plating/asteroid/snow
defer_change = TRUE
/turf/closed/mineral/snowmountain/icemoon
turf_type = /turf/open/floor/plating/asteroid/snow/icemoon
baseturfs = /turf/open/floor/plating/asteroid/snow/icemoon
initial_gas_mix = ICEMOON_DEFAULT_ATMOS
/turf/closed/mineral/snowmountain/cavern
name = "ice cavern rock"
icon = 'icons/turf/mining.dmi'
@@ -532,6 +716,11 @@
environment_type = "snow_cavern"
turf_type = /turf/open/floor/plating/asteroid/snow/ice
/turf/closed/mineral/snowmountain/cavern/icemoon
baseturfs = /turf/open/floor/plating/asteroid/snow/ice/icemoon
turf_type = /turf/open/floor/plating/asteroid/snow/ice/icemoon
initial_gas_mix = ICEMOON_DEFAULT_ATMOS
//GIBTONITE
/turf/closed/mineral/gibtonite
@@ -634,7 +823,7 @@
turf_type = /turf/open/floor/plating/asteroid/basalt/lava_land_surface
baseturfs = /turf/open/floor/plating/asteroid/basalt/lava_land_surface
initial_gas_mix = LAVALAND_DEFAULT_ATMOS
defer_change = 1
defer_change = TRUE
/turf/closed/mineral/gibtonite/earth_like
icon_state = "rock_oxy"
@@ -642,3 +831,18 @@
baseturfs = /turf/open/floor/plating/asteroid
initial_gas_mix = OPENTURF_DEFAULT_ATMOS
defer_change = TRUE
/turf/closed/mineral/gibtonite/ice
environment_type = "snow_cavern"
icon_state = "icerock_Gibtonite"
smooth_icon = 'icons/turf/walls/icerock_wall.dmi'
turf_type = /turf/open/floor/plating/asteroid/snow/ice
baseturfs = /turf/open/floor/plating/asteroid/snow/ice
initial_gas_mix = FROZEN_ATMOS
defer_change = TRUE
/turf/closed/mineral/gibtonite/ice/icemoon
turf_type = /turf/open/floor/plating/asteroid/snow/ice/icemoon
baseturfs = /turf/open/floor/plating/asteroid/snow/ice/icemoon
initial_gas_mix = ICEMOON_DEFAULT_ATMOS

View File

@@ -705,10 +705,17 @@
var/list/names = list()
names += "---- Space Ruins ----"
for(var/name in SSmapping.space_ruins_templates)
names[name] = list(SSmapping.space_ruins_templates[name], ZTRAIT_SPACE_RUINS, /area/space)
names[name] = list(SSmapping.space_ruins_templates[name], ZTRAIT_SPACE_RUINS, list(/area/space))
names += "---- Lava Ruins ----"
for(var/name in SSmapping.lava_ruins_templates)
names[name] = list(SSmapping.lava_ruins_templates[name], ZTRAIT_LAVA_RUINS, /area/lavaland/surface/outdoors/unexplored)
names[name] = list(SSmapping.lava_ruins_templates[name], ZTRAIT_LAVA_RUINS, list(/area/lavaland/surface/outdoors/unexplored))
names += "---- Ice Ruins ----"
for(var/name in SSmapping.ice_ruins_templates)
names[name] = list(SSmapping.ice_ruins_templates[name], ZTRAIT_ICE_RUINS, list(/area/icemoon/surface/outdoors/unexplored, /area/icemoon/underground/unexplored))
names += "---- Ice Underground Ruins ----"
for(var/name in SSmapping.ice_ruins_underground_templates)
names[name] = list(SSmapping.ice_ruins_underground_templates[name], ZTRAIT_ICE_RUINS_UNDERGROUND, list(/area/icemoon/underground/unexplored))
var/ruinname = input("Select ruin", "Spawn Ruin") as null|anything in names
var/data = names[ruinname]

View File

@@ -27,6 +27,9 @@
for(var/obj/effect/landmark/carpspawn/L in GLOB.landmarks_list)
if(isturf(L.loc))
spawn_locs += L.loc
for(var/obj/effect/landmark/loneopspawn/L in GLOB.landmarks_list)
if(isturf(L.loc))
spawn_locs += L.loc
if(!spawn_locs)
message_admins("No valid spawn locations found, aborting...")

View File

@@ -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("<span class='suicide'>[user]'s [src] is reacting to the radio signal, warping [user.p_their()] body!</span>")
user.suiciding = 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, "<span class='notice'>Analyzing... [src]'s stabilized field is fluctuating along frequency [format_frequency(frequency)], code [code].</span>")
..()
//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

View File

@@ -143,6 +143,13 @@
max_heat_protection_temperature = SHOES_MAX_TEMP_PROTECT
pocket_storage_component_path = /datum/component/storage/concrete/pockets/shoes
/obj/item/clothing/shoes/winterboots/ice_boots
name = "ice hiking boots"
desc = "A pair of winter boots with special grips on the bottom, designed to prevent slipping on frozen surfaces."
icon_state = "iceboots"
item_state = "iceboots"
clothing_flags = NOSLIP_ICE
/obj/item/clothing/shoes/winterboots/christmasbootsr
name = "red christmas boots"
desc = "A pair of fluffy red christmas boots!"

View File

@@ -19,6 +19,8 @@
var/list/spawn_locs = list()
for(var/obj/effect/landmark/carpspawn/L in GLOB.landmarks_list)
spawn_locs += L.loc
for(var/obj/effect/landmark/loneopspawn/L in GLOB.landmarks_list)
spawn_locs += L.loc
if(!spawn_locs.len)
return MAP_ERROR

View File

@@ -58,6 +58,9 @@
var/list/candidates = pollGhostCandidates("Do you wish to be considered for pirate crew?", ROLE_TRAITOR)
shuffle_inplace(candidates)
if(!SSmapping.empty_space)
SSmapping.empty_space = SSmapping.add_new_zlevel("Empty Area For Pirates", list(ZTRAIT_LINKAGE = SELFLOOPING))
var/datum/map_template/shuttle/pirate/default/ship = new
var/x = rand(TRANSITIONEDGE,world.maxx - TRANSITIONEDGE - ship.width)
var/y = rand(TRANSITIONEDGE,world.maxy - TRANSITIONEDGE - ship.height)

View File

@@ -22,6 +22,7 @@
var/traits = null
var/space_ruin_levels = 2
var/space_empty_levels = 1
var/station_ruin_budget = -1 // can be set to manually override the station ruins budget on maps that don't support station ruins, stopping the error from being unable to place the ruins.
var/minetype = "lavaland"
@@ -134,6 +135,9 @@
log_world("map_config space_empty_levels is not a number!")
return
if("station_ruin_budget" in json)
station_ruin_budget = json["station_ruin_budget"]
temp = json["year_offset"]
if (isnum(temp))
year_offset = temp

View File

@@ -11,9 +11,17 @@
for(var/turf/check in get_affected_turfs(central_turf,1))
var/area/new_area = get_area(check)
if(!(istype(new_area, allowed_areas)) || check.flags_1 & NO_RUINS_1)
valid = FALSE
valid = FALSE // set to false before we check
if(check.flags_1 & NO_RUINS_1)
break
for(var/type in allowed_areas)
if(istype(new_area, type)) // it's at least one of our types so it's whitelisted
valid = TRUE
break
if(!valid)
break
if(!valid)
continue
@@ -51,7 +59,7 @@
new /obj/effect/landmark/ruin(center, src)
return center
/proc/seedRuins(list/z_levels = null, budget = 0, whitelist = /area/space, list/potentialRuins)
/proc/seedRuins(list/z_levels = null, budget = 0, whitelist = list(/area/space), list/potentialRuins)
if(!z_levels || !z_levels.len)
WARNING("No Z levels provided - Not generating ruins")
return

View File

@@ -659,6 +659,7 @@
nemesis_factions = list("mining", "boss")
var/transform_cooldown
var/swiping = FALSE
var/bleed_stacks_per_hit = 3
total_mass = 2.75
total_mass_on = 5
@@ -701,12 +702,11 @@
user.changeNext_move(CLICK_CD_MELEE * 0.5) //when closed, it attacks very rapidly
/obj/item/melee/transforming/cleaving_saw/nemesis_effects(mob/living/user, mob/living/target)
var/datum/status_effect/saw_bleed/B = target.has_status_effect(STATUS_EFFECT_SAWBLEED)
var/datum/status_effect/stacking/saw_bleed/B = target.has_status_effect(STATUS_EFFECT_SAWBLEED)
if(!B)
if(!active) //This isn't in the above if-check so that the else doesn't care about active
target.apply_status_effect(STATUS_EFFECT_SAWBLEED)
target.apply_status_effect(STATUS_EFFECT_SAWBLEED,bleed_stacks_per_hit)
else
B.add_bleed(B.bleed_buildup)
B.add_stacks(bleed_stacks_per_hit)
/obj/item/melee/transforming/cleaving_saw/attack(mob/living/target, mob/living/carbon/human/user)
if(!active || swiping || !target.density || get_turf(target) == get_turf(user))

View File

@@ -24,13 +24,18 @@
/mob/living/carbon/human/slip(knockdown_amount, obj/O, lube)
if(HAS_TRAIT(src, TRAIT_NOSLIPALL))
return 0
if (!(lube&GALOSHES_DONT_HELP))
if (!(lube & GALOSHES_DONT_HELP))
if(HAS_TRAIT(src, TRAIT_NOSLIPWATER))
return 0
if(shoes && istype(shoes, /obj/item/clothing))
var/obj/item/clothing/CS = shoes
if (CS.clothing_flags & NOSLIP)
return 0
if (lube & SLIDE_ICE)
if(shoes && istype(shoes, /obj/item/clothing))
var/obj/item/clothing/CS = shoes
if (CS.clothing_flags & NOSLIP_ICE)
return FALSE
return ..()
/mob/living/carbon/human/experience_pressure_difference()

View File

@@ -265,4 +265,12 @@ Difficulty: Medium
desc = "The sweet blood, oh, it sings to me."
invisibility = 100
/mob/living/simple_animal/hostile/megafauna/blood_drunk_miner/doom
name = "hostile-environment miner"
desc = "A miner destined to hop across dimensions for all eternity, hunting anomalous creatures."
speed = 8
move_to_delay = 8
ranged_cooldown_time = 8
dash_cooldown = 8
#undef MINER_DASH_RANGE

View File

@@ -0,0 +1,361 @@
/*
Difficulty: Extremely Hard
*/
/mob/living/simple_animal/hostile/megafauna/demonic_frost_miner
name = "demonic-frost miner"
desc = "An extremely geared miner, driven crazy or possessed by the demonic forces here, either way a terrifying enemy."
health = 1500
maxHealth = 1500
icon_state = "demonic_miner"
icon_living = "demonic_miner"
icon = 'icons/mob/icemoon/icemoon_monsters.dmi'
attacktext = "pummels"
attack_sound = 'sound/weapons/sonic_jackhammer.ogg'
mob_biotypes = MOB_ORGANIC|MOB_HUMANOID
light_color = "#E4C7C5"
movement_type = GROUND
weather_immunities = list("snow")
speak_emote = list("roars")
armour_penetration = 100
melee_damage_lower = 10
melee_damage_upper = 10
aggro_vision_range = 18 // large vision range so combat doesn't abruptly end when someone runs a bit away
rapid_melee = 4
speed = 20
move_to_delay = 20
ranged = TRUE
crusher_loot = list(/obj/effect/decal/remains/plasma, /obj/item/crusher_trophy/ice_block_talisman)
loot = list(/obj/effect/decal/remains/plasma)
wander = FALSE
del_on_death = TRUE
blood_volume = BLOOD_VOLUME_NORMAL
deathmessage = "falls to the ground, decaying into plasma particles."
deathsound = "bodyfall"
attack_action_types = list(/datum/action/innate/megafauna_attack/frost_orbs,
/datum/action/innate/megafauna_attack/snowball_machine_gun,
/datum/action/innate/megafauna_attack/ice_shotgun)
/// Modifies the speed of the projectiles the demonic frost miner shoots out
var/projectile_speed_multiplier = 1
/// If the demonic frost miner is in its enraged state
var/enraged = FALSE
/// If the demonic frost miner is currently transforming to its enraged state
var/enraging = FALSE
/mob/living/simple_animal/hostile/megafauna/demonic_frost_miner/Initialize()
. = ..()
AddComponent(/datum/component/knockback, 7, FALSE, TRUE)
AddComponent(/datum/component/lifesteal, 50)
/datum/action/innate/megafauna_attack/frost_orbs
name = "Fire Frost Orbs"
icon_icon = 'icons/mob/actions/actions_items.dmi'
button_icon_state = "sniper_zoom"
chosen_message = "<span class='colossus'>You are now sending out frost orbs to track in on a target.</span>"
chosen_attack_num = 1
/datum/action/innate/megafauna_attack/snowball_machine_gun
name = "Fire Snowball Machine Gun"
icon_icon = 'icons/obj/guns/energy.dmi'
button_icon_state = "kineticgun"
chosen_message = "<span class='colossus'>You are now firing a snowball machine gun at a target.</span>"
chosen_attack_num = 2
/datum/action/innate/megafauna_attack/ice_shotgun
name = "Fire Ice Shotgun"
icon_icon = 'icons/obj/guns/projectile.dmi'
button_icon_state = "shotgun"
chosen_message = "<span class='colossus'>You are now firing shotgun ice blasts.</span>"
chosen_attack_num = 3
/mob/living/simple_animal/hostile/megafauna/demonic_frost_miner/OpenFire()
check_enraged()
projectile_speed_multiplier = 1 - enraged * 0.25
SetRecoveryTime(100, 100)
if(client)
switch(chosen_attack)
if(1)
frost_orbs()
if(2)
snowball_machine_gun()
if(3)
ice_shotgun()
return
var/easy_attack = prob(80 - enraged * 40)
chosen_attack = rand(1, 3)
switch(chosen_attack)
if(1)
if(easy_attack)
frost_orbs(10, 8)
else
frost_orbs(5, 16)
if(2)
if(easy_attack)
snowball_machine_gun()
else
INVOKE_ASYNC(src, .proc/ice_shotgun, 5, list(list(-180, -140, -100, -60, -20, 20, 60, 100, 140), list(-160, -120, -80, -40, 0, 40, 80, 120, 160)))
snowball_machine_gun(5 * 8, 5)
if(3)
if(easy_attack)
ice_shotgun()
else
ice_shotgun(5, list(list(0, 30, 60, 90, 120, 150, 180, 210, 240, 270, 300, 330), list(-30, -15, 0, 15, 30)))
/obj/item/projectile/frost_orb
name = "frost orb"
icon_state = "ice_1"
damage = 20
armour_penetration = 100
speed = 10
homing_turn_speed = 30
damage_type = BURN
/obj/item/projectile/frost_orb/on_hit(atom/target, blocked = FALSE)
. = ..()
if(isturf(target) || isobj(target))
target.ex_act(EXPLODE_HEAVY)
/obj/item/projectile/snowball
name = "machine-gun snowball"
icon_state = "nuclear_particle"
damage = 5
armour_penetration = 100
speed = 4
damage_type = BRUTE
/obj/item/projectile/ice_blast
name = "ice blast"
icon_state = "ice_2"
damage = 15
armour_penetration = 100
speed = 4
damage_type = BRUTE
/obj/item/projectile/ice_blast/on_hit(atom/target, blocked = FALSE)
. = ..()
if(isturf(target) || isobj(target))
target.ex_act(EXPLODE_HEAVY)
/mob/living/simple_animal/hostile/megafauna/demonic_frost_miner/ex_act(severity, target)
adjustBruteLoss(30 * severity - 120)
visible_message("<span class='danger'>[src] absorbs the explosion!</span>", "<span class='userdanger'>You absorb the explosion!</span>")
/mob/living/simple_animal/hostile/megafauna/demonic_frost_miner/Goto(target, delay, minimum_distance)
if(enraging)
return
return ..()
/mob/living/simple_animal/hostile/megafauna/demonic_frost_miner/MoveToTarget(list/possible_targets)
if(enraging)
return
return ..()
/mob/living/simple_animal/hostile/megafauna/demonic_frost_miner/Move()
if(enraging)
return
return ..()
/// Shoots out homing frost orbs that explode into ice blast projectiles after a couple seconds
/mob/living/simple_animal/hostile/megafauna/demonic_frost_miner/proc/frost_orbs(added_delay = 10, shoot_times = 8)
for(var/i in 1 to shoot_times)
var/turf/startloc = get_turf(src)
var/turf/endloc = get_turf(target)
if(!endloc)
break
var/obj/item/projectile/frost_orb/P = new(startloc)
P.preparePixelProjectile(endloc, startloc)
P.firer = src
if(target)
P.original = target
P.set_homing_target(target)
P.fire(rand(0, 360))
addtimer(CALLBACK(P, /obj/item/projectile/frost_orb/proc/orb_explosion, projectile_speed_multiplier), 20) // make the orbs home in after a second
SLEEP_CHECK_DEATH(added_delay)
SetRecoveryTime(40, 60)
/// Called when the orb is exploding, shoots out projectiles
/obj/item/projectile/frost_orb/proc/orb_explosion(projectile_speed_multiplier)
for(var/i in 0 to 5)
var/angle = i * 60
var/turf/startloc = get_turf(src)
var/turf/endloc = get_turf(original)
if(!startloc || !endloc)
break
var/obj/item/projectile/ice_blast/P = new(startloc)
P.speed *= projectile_speed_multiplier
P.preparePixelProjectile(endloc, startloc, null, angle + rand(-10, 10))
P.firer = firer
if(original)
P.original = original
P.fire()
qdel(src)
/// Shoots out snowballs with a random spread
/mob/living/simple_animal/hostile/megafauna/demonic_frost_miner/proc/snowball_machine_gun(shots = 60, spread = 45)
for(var/i in 1 to shots)
var/turf/startloc = get_turf(src)
var/turf/endloc = get_turf(target)
if(!endloc)
break
var/obj/item/projectile/P = new /obj/item/projectile/snowball(startloc)
P.speed *= projectile_speed_multiplier
P.preparePixelProjectile(endloc, startloc, null, rand(-spread, spread))
P.firer = src
if(target)
P.original = target
P.fire()
SLEEP_CHECK_DEATH(1)
SetRecoveryTime(15, 15)
/// Shoots out ice blasts in a shotgun like pattern
/mob/living/simple_animal/hostile/megafauna/demonic_frost_miner/proc/ice_shotgun(shots = 5, list/patterns = list(list(-40, -20, 0, 20, 40), list(-30, -10, 10, 30)))
for(var/i in 1 to shots)
var/list/pattern = patterns[i % length(patterns) + 1] // alternating patterns
for(var/spread in pattern)
var/turf/startloc = get_turf(src)
var/turf/endloc = get_turf(target)
if(!endloc)
break
var/obj/item/projectile/P = new /obj/item/projectile/ice_blast(startloc)
P.speed *= projectile_speed_multiplier
P.preparePixelProjectile(endloc, startloc, null, spread)
P.firer = src
if(target)
P.original = target
P.fire()
SLEEP_CHECK_DEATH(8)
SetRecoveryTime(15, 20)
/// Checks if the demonic frost miner is ready to be enraged
/mob/living/simple_animal/hostile/megafauna/demonic_frost_miner/proc/check_enraged()
if(enraged)
return
if(health > maxHealth*0.25)
return
SetRecoveryTime(80, 80)
adjustHealth(-maxHealth)
enraged = TRUE
enraging = TRUE
animate(src, pixel_y = pixel_y + 96, time = 100, easing = ELASTIC_EASING)
spin(100, 10)
SLEEP_CHECK_DEATH(60)
playsound(src, 'sound/effects/explosion3.ogg', 100, TRUE)
icon_state = "demonic_miner_phase2"
animate(src, pixel_y = pixel_y - 96, time = 8, flags = ANIMATION_END_NOW)
spin(8, 2)
SLEEP_CHECK_DEATH(8)
for(var/mob/living/L in viewers(src))
shake_camera(L, 3, 2)
playsound(src, 'sound/effects/meteorimpact.ogg', 100, TRUE)
setMovetype(movement_type | FLYING)
enraging = FALSE
adjustHealth(-maxHealth)
/mob/living/simple_animal/hostile/megafauna/demonic_frost_miner/death(gibbed, list/force_grant)
if(health > 0)
return
var/turf/T = get_turf(src)
var/loot = rand(1, 3)
switch(loot)
if(1)
new /obj/item/resurrection_crystal(T)
if(2)
new /obj/item/clothing/shoes/winterboots/ice_boots/speedy(T)
if(3)
new /obj/item/pickaxe/drill/jackhammer/demonic(T)
return ..()
/obj/item/resurrection_crystal
name = "resurrection crystal"
desc = "When used by anything holding it, this crystal gives them a second chance at life if they die."
icon = 'icons/obj/objects.dmi'
icon_state = "demonic_crystal"
/obj/item/resurrection_crystal/attack_self(mob/living/user)
if(!iscarbon(user))
to_chat(user, "<span class='notice'>A dark presence stops you from absorbing the crystal.</span>")
return
forceMove(user)
to_chat(user, "<span class='notice'>You feel a bit safer... but a demonic presence lurks in the back of your head...</span>")
RegisterSignal(user, COMSIG_MOB_DEATH, .proc/resurrect)
/// Resurrects the target when they die by cloning them into a new duplicate body and transferring their mind to the clone on a safe station turf
/obj/item/resurrection_crystal/proc/resurrect(mob/living/carbon/user, gibbed)
user.visible_message("<span class='notice'>You see [user]'s soul dragged out of their body!</span>", "<span class='notice'>You feel your soul dragged away to a fresh body!</span>")
var/typepath = user.type
var/turf/T = find_safe_turf()
var/mob/living/carbon/clone = new typepath(T)
clone.real_name = user.real_name
user.dna.transfer_identity(clone)
clone.updateappearance(mutcolor_update=1)
user.mind.transfer_to(clone) // second life
to_chat(clone, "<span class='notice'>You blink and find yourself in [get_area_name(T)].</span>")
user.gib()
qdel(src)
/obj/item/clothing/shoes/winterboots/ice_boots/speedy
name = "cursed ice hiking boots"
desc = "A pair of winter boots contractually made by a devil, they cannot be taken off once put on."
slowdown = SHOES_SPEED_SLIGHT
/obj/item/clothing/shoes/winterboots/ice_boots/speedy/Initialize()
. = ..()
ADD_TRAIT(src, TRAIT_NODROP, CURSED_ITEM_TRAIT)
/obj/item/pickaxe/drill/jackhammer/demonic
name = "demonic jackhammer"
desc = "Cracks rocks at an inhuman speed, as well as being enhanced for combat purposes."
toolspeed = 0
/obj/item/pickaxe/drill/jackhammer/demonic/Initialize()
. = ..()
AddComponent(/datum/component/knockback, 4, FALSE, TRUE)
AddComponent(/datum/component/lifesteal, 5)
/obj/item/crusher_trophy/ice_block_talisman
name = "ice block talisman"
desc = "A glowing trinket that a demonic miner had on him, it seems he couldn't utilize it for whatever reason."
icon_state = "ice_trap_talisman"
denied_type = /obj/item/crusher_trophy/ice_block_talisman
/obj/item/crusher_trophy/ice_block_talisman/effect_desc()
return "mark detonation to freeze a creature in a block of ice for a period, preventing them from moving"
/obj/item/crusher_trophy/ice_block_talisman/on_mark_detonation(mob/living/target, mob/living/user)
target.apply_status_effect(/datum/status_effect/ice_block_talisman)
/datum/status_effect/ice_block_talisman
id = "ice_block_talisman"
duration = 25
status_type = STATUS_EFFECT_REFRESH
alert_type = /obj/screen/alert/status_effect/ice_block_talisman
/// Stored icon overlay for the hit mob, removed when effect is removed
var/icon/cube
/obj/screen/alert/status_effect/ice_block_talisman
name = "Frozen Solid"
desc = "You're frozen inside an ice cube, and cannot move!"
icon_state = "frozen"
/datum/status_effect/ice_block_talisman/on_apply()
RegisterSignal(owner, COMSIG_MOVABLE_PRE_MOVE, .proc/owner_moved)
if(!owner.stat)
to_chat(owner, "<span class='userdanger'>You become frozen in a cube!</span>")
cube = icon('icons/effects/freeze.dmi', "ice_cube")
var/icon/size_check = icon(owner.icon, owner.icon_state)
cube.Scale(size_check.Width(), size_check.Height())
owner.add_overlay(cube)
return ..()
/// Blocks movement from the status effect owner
/datum/status_effect/ice_block_talisman/proc/owner_moved()
return COMPONENT_MOVABLE_BLOCK_PRE_MOVE
/datum/status_effect/ice_block_talisman/on_remove()
. = ..()
if(!owner.stat)
to_chat(owner, "<span class='notice'>The cube melts!</span>")
owner.cut_overlay(cube)
UnregisterSignal(owner, COMSIG_MOVABLE_PRE_MOVE)

View File

@@ -394,3 +394,26 @@ Difficulty: Medium
/mob/living/simple_animal/hostile/megafauna/dragon/lesser/grant_achievement(medaltype,scoretype)
return
//fire line keeps going even if dragon is deleted
/proc/dragon_fire_line(source, list/turfs)
var/list/hit_list = list()
for(var/turf/T in turfs)
if(istype(T, /turf/closed))
break
new /obj/effect/hotspot(T)
T.hotspot_expose(700,50,1)
for(var/mob/living/L in T.contents)
if(L in hit_list || L == source)
continue
hit_list += L
L.adjustFireLoss(20)
to_chat(L, "<span class='userdanger'>You're hit by [source]'s fire breath!</span>")
// deals damage to mechs
for(var/obj/mecha/M in T.contents)
if(M in hit_list)
continue
hit_list += M
M.take_damage(45, BRUTE, "melee", 1)
sleep(1.5)

View File

@@ -27,23 +27,51 @@
mob_size = MOB_SIZE_LARGE
layer = LARGE_MOB_LAYER //Looks weird with them slipping under mineral walls and cameras and shit otherwise
flags_1 = PREVENT_CONTENTS_EXPLOSION_1 | HEAR_1
/// Crusher loot dropped when fauna killed with a crusher
var/list/crusher_loot
var/medal_type
/// Score given to players when the fauna is killed
var/score_type = BOSS_SCORE
/// If the megafauna is actually killed (vs entering another phase)
var/elimination = 0
/// Modifies attacks when at lower health
var/anger_modifier = 0
/// Internal tracking GPS inside fauna
var/obj/item/gps/internal
/// Next time fauna can use a melee attack
var/recovery_time = 0
var/true_spawn = TRUE // if this is a megafauna that should grant achievements, or have a gps signal
var/nest_range = 10
var/chosen_attack = 1 // chosen attack num
var/list/attack_action_types = list()
var/small_sprite_type
/mob/living/simple_animal/hostile/megafauna/Initialize(mapload)
. = ..()
apply_status_effect(STATUS_EFFECT_CRUSHERDAMAGETRACKING)
ADD_TRAIT(src, TRAIT_NO_TELEPORT, MEGAFAUNA_TRAIT)
for(var/action_type in attack_action_types)
var/datum/action/innate/megafauna_attack/attack_action = new action_type()
attack_action.Grant(src)
if(small_sprite_type)
var/datum/action/small_sprite/small_action = new small_sprite_type()
small_action.Grant(src)
/mob/living/simple_animal/hostile/megafauna/Destroy()
QDEL_NULL(internal)
. = ..()
/mob/living/simple_animal/hostile/megafauna/Moved()
if(nest && nest.parent && get_dist(nest.parent, src) > nest_range)
var/turf/closest = get_turf(nest.parent)
for(var/i = 1 to nest_range)
closest = get_step(closest, get_dir(closest, src))
forceMove(closest) // someone teleported out probably and the megafauna kept chasing them
target = null
return
return ..()
/mob/living/simple_animal/hostile/megafauna/death(gibbed)
if(health > 0)
return
@@ -134,3 +162,21 @@
SSmedals.SetScore(BOSS_SCORE, C, 1)
SSmedals.SetScore(score_type, C, 1)
return TRUE
/datum/action/innate/megafauna_attack
name = "Megafauna Attack"
icon_icon = 'icons/mob/actions/actions_animal.dmi'
button_icon_state = ""
var/mob/living/simple_animal/hostile/megafauna/M
var/chosen_message
var/chosen_attack_num = 0
/datum/action/innate/megafauna_attack/Grant(mob/living/L)
if(istype(L, /mob/living/simple_animal/hostile/megafauna))
M = L
return ..()
return FALSE
/datum/action/innate/megafauna_attack/Activate()
M.chosen_attack = chosen_attack_num
to_chat(M, chosen_message)

View File

@@ -0,0 +1,201 @@
/*
Difficulty: Hard
*/
/mob/living/simple_animal/hostile/megafauna/wendigo
name = "wendigo"
desc = "A mythological man-eating legendary creature, you probably aren't going to survive this."
health = 2500
maxHealth = 2500
icon_state = "wendigo"
icon_living = "wendigo"
icon_dead = "wendigo_dead"
icon = 'icons/mob/icemoon/64x64megafauna.dmi'
attacktext = "claws"
attack_sound = 'sound/magic/demon_attack1.ogg'
weather_immunities = list("snow")
speak_emote = list("roars")
armour_penetration = 40
melee_damage_lower = 40
melee_damage_upper = 40
vision_range = 9
aggro_vision_range = 18 // man-eating for a reason
speed = 8
move_to_delay = 8
rapid_melee = 16 // every 1/8 second
melee_queue_distance = 20 // as far as possible really, need this because of charging and teleports
ranged = TRUE
pixel_x = -16
loot = list(/obj/item/wendigo_blood)
crusher_loot = list(/obj/item/wendigo_blood, /obj/item/crusher_trophy/demon_claws)
wander = FALSE
del_on_death = TRUE
blood_volume = BLOOD_VOLUME_NORMAL
deathmessage = "falls, shaking the ground around it"
deathsound = 'sound/effects/gravhit.ogg'
attack_action_types = list(/datum/action/innate/megafauna_attack/heavy_stomp,
/datum/action/innate/megafauna_attack/teleport,
/datum/action/innate/megafauna_attack/disorienting_scream)
/// Saves the turf the megafauna was created at (spawns exit portal here)
var/turf/starting
/// Range for wendigo stomping when it moves
var/stomp_range = 1
/// Stores directions the mob is moving, then calls that a move has fully ended when these directions are removed in moved
var/stored_move_dirs = 0
/// If the wendigo is allowed to move
var/can_move = TRUE
/datum/action/innate/megafauna_attack/heavy_stomp
name = "Heavy Stomp"
icon_icon = 'icons/mob/actions/actions_items.dmi'
button_icon_state = "sniper_zoom"
chosen_message = "<span class='colossus'>You are now stomping the ground around you.</span>"
chosen_attack_num = 1
/datum/action/innate/megafauna_attack/teleport
name = "Teleport"
icon_icon = 'icons/effects/bubblegum.dmi'
button_icon_state = "smack ya one"
chosen_message = "<span class='colossus'>You are now teleporting at the target you click on.</span>"
chosen_attack_num = 2
/datum/action/innate/megafauna_attack/disorienting_scream
name = "Disorienting Scream"
icon_icon = 'icons/turf/walls/wall.dmi'
button_icon_state = "wall"
chosen_message = "<span class='colossus'>You are now screeching, disorienting targets around you.</span>"
chosen_attack_num = 3
/mob/living/simple_animal/hostile/megafauna/wendigo/Initialize()
. = ..()
starting = get_turf(src)
/mob/living/simple_animal/hostile/megafauna/wendigo/OpenFire()
SetRecoveryTime(0, 100)
if(health <= maxHealth*0.5)
stomp_range = 2
speed = 6
move_to_delay = 6
else
stomp_range = initial(stomp_range)
speed = initial(speed)
move_to_delay = initial(move_to_delay)
if(client)
switch(chosen_attack)
if(1)
heavy_stomp()
if(2)
teleport()
if(3)
disorienting_scream()
return
chosen_attack = rand(1, 3)
switch(chosen_attack)
if(1)
heavy_stomp()
if(2)
teleport()
if(3)
disorienting_scream()
/mob/living/simple_animal/hostile/megafauna/wendigo/Move(atom/newloc, direct)
if(!can_move)
return
stored_move_dirs |= direct
return ..()
/mob/living/simple_animal/hostile/megafauna/wendigo/Moved(atom/oldloc, direct)
. = ..()
stored_move_dirs &= ~direct
if(!stored_move_dirs)
INVOKE_ASYNC(src, .proc/ground_slam, stomp_range, 1)
/// Slams the ground around the wendigo throwing back enemies caught nearby
/mob/living/simple_animal/hostile/megafauna/wendigo/proc/ground_slam(range, delay)
var/turf/orgin = get_turf(src)
var/list/all_turfs = RANGE_TURFS(range, orgin)
for(var/i = 0 to range)
for(var/turf/T in all_turfs)
if(get_dist(orgin, T) > i)
continue
playsound(T,'sound/effects/bamf.ogg', 600, TRUE, 10)
new /obj/effect/temp_visual/small_smoke/halfsecond(T)
for(var/mob/living/L in T)
if(L == src || L.throwing)
continue
to_chat(L, "<span class='userdanger'>[src]'s ground slam shockwave sends you flying!</span>")
var/turf/thrownat = get_ranged_target_turf_direct(src, L, 8, rand(-10, 10))
L.throw_at(thrownat, 8, 2, src, TRUE) //, force = MOVE_FORCE_OVERPOWERING, gentle = TRUE)
L.apply_damage(20, BRUTE)
shake_camera(L, 2, 1)
all_turfs -= T
sleep(delay)
/// Larger but slower ground stomp
/mob/living/simple_animal/hostile/megafauna/wendigo/proc/heavy_stomp()
can_move = FALSE
ground_slam(5, 2)
SetRecoveryTime(0, 0)
can_move = TRUE
/// Teleports to a location 4 turfs away from the enemy in view
/mob/living/simple_animal/hostile/megafauna/wendigo/proc/teleport()
var/list/possible_ends = list()
for(var/turf/T in view(4, target.loc) - view(3, target.loc))
if(isclosedturf(T))
continue
possible_ends |= T
var/turf/end = pick(possible_ends)
do_teleport(src, end, 0, channel=TELEPORT_CHANNEL_BLUESPACE, forced = TRUE)
SetRecoveryTime(20, 0)
/// Shakes all nearby enemies screens and animates the wendigo shaking up and down
/mob/living/simple_animal/hostile/megafauna/wendigo/proc/disorienting_scream()
can_move = FALSE
playsound(src, 'sound/magic/demon_dies.ogg', 600, FALSE, 10)
animate(src, pixel_z = rand(5, 15), time = 1, loop = 6)
animate(pixel_z = 0, time = 1)
for(var/mob/living/L in get_hearers_in_view(7, src) - src)
shake_camera(L, 30, 1)
to_chat(L, "<span class='danger'>The wendigo screams loudly!</span>")
SetRecoveryTime(30, 0)
SLEEP_CHECK_DEATH(12)
can_move = TRUE
return
/mob/living/simple_animal/hostile/megafauna/wendigo/death(gibbed, list/force_grant)
if(health > 0)
return
var/obj/effect/portal/permanent/one_way/exit = new /obj/effect/portal/permanent/one_way(starting)
exit.id = "wendigo arena exit"
exit.add_atom_colour(COLOR_RED_LIGHT, ADMIN_COLOUR_PRIORITY)
exit.set_light(20, 1, LIGHT_COLOR_RED)
return ..()
/obj/item/wendigo_blood
name = "bottle of wendigo blood"
desc = "You're not actually going to drink this, are you?"
icon = 'icons/obj/wizard.dmi'
icon_state = "vial"
/obj/item/wendigo_blood/attack_self(mob/living/user)
if(!ishuman(user))
return
var/mob/living/carbon/human/H = user
if(!H.mind)
return
to_chat(H, "<span class='danger'>Power courses through you! You can now shift your form at will.</span>")
var/obj/effect/proc_holder/spell/targeted/shapeshift/polar_bear/P = new
H.mind.AddSpell(P)
playsound(H.loc,'sound/items/drink.ogg', rand(10,50), TRUE)
qdel(src)
/obj/effect/proc_holder/spell/targeted/shapeshift/polar_bear
name = "Polar Bear Form"
desc = "Take on the shape of a polar bear."
invocation = "RAAAAAAAAWR!"
convert_damage = FALSE
shapeshift_type = /mob/living/simple_animal/hostile/asteroid/polarbear

View File

@@ -424,3 +424,29 @@
l_pocket = /obj/item/reagent_containers/food/drinks/soda_cans/buzz_fuzz
mask = /obj/item/clothing/mask/rat/bee
. = ..()
// Snow Legion
/mob/living/simple_animal/hostile/asteroid/hivelord/legion/snow
name = "snow legion"
desc = "You can still see what was once a human under the shifting snowy mass, clearly decorated by a clown."
icon = 'icons/mob/icemoon/icemoon_monsters.dmi'
icon_state = "snowlegion"
icon_living = "snowlegion"
icon_aggro = "snowlegion_alive"
icon_dead = "snowlegion"
crusher_loot = /obj/item/crusher_trophy/legion_skull
loot = list(/obj/item/organ/regenerative_core/legion)
brood_type = /mob/living/simple_animal/hostile/asteroid/hivelordbrood/legion/snow
/mob/living/simple_animal/hostile/asteroid/hivelord/legion/snow/tendril
fromtendril = TRUE
// Snow Legion skull
/mob/living/simple_animal/hostile/asteroid/hivelordbrood/legion/snow
name = "snow legion"
desc = "One of many."
icon = 'icons/mob/icemoon/icemoon_monsters.dmi'
icon_state = "snowlegion_head"
icon_living = "snowlegion_head"
icon_aggro = "snowlegion_head"
icon_dead = "snowlegion_head"

View File

@@ -0,0 +1,76 @@
/mob/living/simple_animal/hostile/asteroid/ice_demon
name = "demonic watcher"
desc = "A creature formed entirely out of ice, bluespace energy emanates from inside of it."
icon = 'icons/mob/icemoon/icemoon_monsters.dmi'
icon_state = "ice_demon"
icon_living = "ice_demon"
icon_dead = "ice_demon_dead"
icon_gib = "syndicate_gib"
mob_biotypes = MOB_ORGANIC|MOB_BEAST
mouse_opacity = MOUSE_OPACITY_ICON
speak_emote = list("telepathically cries")
speed = 2
move_to_delay = 2
projectiletype = /obj/item/projectile/temp/basilisk/ice
projectilesound = 'sound/weapons/pierce.ogg'
ranged = TRUE
ranged_message = "manifests ice"
ranged_cooldown_time = 30
minimum_distance = 3
retreat_distance = 3
maxHealth = 150
health = 150
obj_damage = 40
melee_damage_lower = 15
melee_damage_upper = 15
attacktext = "slices"
attack_sound = 'sound/weapons/bladeslice.ogg'
vision_range = 9
aggro_vision_range = 9
move_force = MOVE_FORCE_VERY_STRONG
move_resist = MOVE_FORCE_VERY_STRONG
pull_force = MOVE_FORCE_VERY_STRONG
del_on_death = TRUE
loot = list(/obj/item/stack/ore/bluespace_crystal = 3)
crusher_loot = /obj/item/crusher_trophy/watcher_wing/ice_wing
deathmessage = "fades as the energies that tied it to this world dissipate."
deathsound = 'sound/magic/demon_dies.ogg'
stat_attack = UNCONSCIOUS
movement_type = FLYING
robust_searching = TRUE
/// Distance the demon will teleport from the target
var/teleport_distance = 3
/obj/item/projectile/temp/basilisk/ice
name = "ice blast"
damage = 5
nodamage = FALSE
temperature = -75
/mob/living/simple_animal/hostile/asteroid/ice_demon/OpenFire()
if(teleport_distance <= 0)
return ..()
var/list/possible_ends = list()
for(var/turf/T in view(teleport_distance, target.loc) - view(teleport_distance - 1, target.loc))
if(isclosedturf(T))
continue
possible_ends |= T
var/turf/end = pick(possible_ends)
do_teleport(src, end, 0, channel=TELEPORT_CHANNEL_BLUESPACE, forced = TRUE)
SLEEP_CHECK_DEATH(8)
return ..()
/mob/living/simple_animal/hostile/asteroid/ice_demon/Life()
. = ..()
if(!. || target)
return
adjustHealth(-maxHealth*0.025)
/mob/living/simple_animal/hostile/asteroid/ice_demon/death(gibbed)
move_force = MOVE_FORCE_DEFAULT
move_resist = MOVE_RESIST_DEFAULT
pull_force = PULL_FORCE_DEFAULT
var/turf/T = get_turf(src)
if(T && prob(5))
new /obj/item/assembly/signaler/anomaly/bluespace(T)
return ..()

View File

@@ -0,0 +1,54 @@
/mob/living/simple_animal/hostile/asteroid/ice_whelp
name = "ice whelp"
desc = "The offspring of an ice drake, weak in comparison but still terrifying."
icon = 'icons/mob/icemoon/icemoon_monsters.dmi'
icon_state = "ice_whelp"
icon_living = "ice_whelp"
icon_dead = "ice_whelp_dead"
mob_biotypes = MOB_ORGANIC|MOB_BEAST
mouse_opacity = MOUSE_OPACITY_ICON
friendly = "stares down"
speak_emote = list("roars")
speed = 30
move_to_delay = 30
ranged = TRUE
ranged_cooldown_time = 40
maxHealth = 350
health = 350
obj_damage = 40
armour_penetration = 20
melee_damage_lower = 20
melee_damage_upper = 20
attacktext = "chomps"
attack_sound = 'sound/magic/demon_attack1.ogg'
vision_range = 9
aggro_vision_range = 9
move_force = MOVE_FORCE_VERY_STRONG
move_resist = MOVE_FORCE_VERY_STRONG
pull_force = MOVE_FORCE_VERY_STRONG
butcher_results = list(/obj/item/stack/ore/diamond = 3, /obj/item/stack/sheet/sinew = 2, /obj/item/stack/sheet/bone = 10, /obj/item/stack/sheet/animalhide/ashdrake = 1)
loot = list()
crusher_loot = /obj/item/crusher_trophy/tail_spike
deathmessage = "collapses on it's side."
deathsound = 'sound/magic/demon_dies.ogg'
stat_attack = UNCONSCIOUS
robust_searching = TRUE
/// How far the whelps fire can go
var/fire_range = 4
/mob/living/simple_animal/hostile/asteroid/ice_whelp/OpenFire()
var/turf/T = get_ranged_target_turf_direct(src, target, fire_range)
var/list/burn_turfs = getline(src, T) - get_turf(src)
dragon_fire_line(src, burn_turfs)
/mob/living/simple_animal/hostile/asteroid/ice_whelp/Life()
. = ..()
if(!. || target)
return
adjustHealth(-maxHealth*0.025)
/mob/living/simple_animal/hostile/asteroid/ice_whelp/death(gibbed)
move_force = MOVE_FORCE_DEFAULT
move_resist = MOVE_RESIST_DEFAULT
pull_force = PULL_FORCE_DEFAULT
return ..()

View File

@@ -28,7 +28,7 @@
/mob/living/simple_animal/hostile/asteroid/Aggro()
..()
if(vision_range != aggro_vision_range)
if(vision_range == aggro_vision_range && icon_aggro)
icon_state = icon_aggro
/mob/living/simple_animal/hostile/asteroid/LoseAggro()

View File

@@ -0,0 +1,56 @@
/mob/living/simple_animal/hostile/asteroid/polarbear
name = "polar bear"
desc = "An aggressive animal that defends it's territory with incredible power. These beasts don't run from their enemies."
icon = 'icons/mob/icemoon/icemoon_monsters.dmi'
icon_state = "polarbear"
icon_living = "polarbear"
icon_dead = "polarbear_dead"
mob_biotypes = MOB_ORGANIC|MOB_BEAST
mouse_opacity = MOUSE_OPACITY_ICON
friendly = "growls at"
speak_emote = list("growls")
speed = 12
move_to_delay = 12
maxHealth = 300
health = 300
obj_damage = 40
melee_damage_lower = 25
melee_damage_upper = 25
attacktext = "claws"
attack_sound = 'sound/weapons/bladeslice.ogg'
vision_range = 2 // don't aggro unless you basically antagonize it, though they will kill you worse than a goliath will
aggro_vision_range = 9
move_force = MOVE_FORCE_VERY_STRONG
move_resist = MOVE_FORCE_VERY_STRONG
pull_force = MOVE_FORCE_VERY_STRONG
butcher_results = list(/obj/item/reagent_containers/food/snacks/meat/slab/bear = 3, /obj/item/stack/sheet/bone = 2)
guaranteed_butcher_results = list(/obj/item/stack/sheet/animalhide/goliath_hide/polar_bear_hide = 1)
loot = list()
crusher_loot = /obj/item/crusher_trophy/goliath_tentacle
stat_attack = UNCONSCIOUS
robust_searching = TRUE
/// Message for when the polar bear starts to attack faster
var/aggressive_message_said = FALSE
/mob/living/simple_animal/hostile/asteroid/polarbear/adjustHealth(amount, updating_health = TRUE, forced = FALSE)
. = ..()
if(health > maxHealth*0.5)
rapid_melee = initial(rapid_melee)
return
if(!aggressive_message_said && target)
visible_message("<span class='danger'>The [name] gets an enraged look at [target]!</span>")
aggressive_message_said = TRUE
rapid_melee = 2
/mob/living/simple_animal/hostile/asteroid/polarbear/Life()
. = ..()
if(!. || target)
return
adjustHealth(-maxHealth*0.025)
aggressive_message_said = FALSE
/mob/living/simple_animal/hostile/asteroid/polarbear/death(gibbed)
move_force = MOVE_FORCE_DEFAULT
move_resist = MOVE_RESIST_DEFAULT
pull_force = PULL_FORCE_DEFAULT
return ..()

View File

@@ -0,0 +1,57 @@
/mob/living/simple_animal/hostile/asteroid/wolf
name = "white wolf"
desc = "A beast that survives by feasting on weaker opponents, they're much stronger with numbers."
icon = 'icons/mob/icemoon/icemoon_monsters.dmi'
icon_state = "whitewolf"
icon_living = "whitewolf"
icon_dead = "whitewolf_dead"
mob_biotypes = MOB_ORGANIC|MOB_BEAST
mouse_opacity = MOUSE_OPACITY_ICON
friendly = "howls at"
speak_emote = list("howls")
speed = 5
move_to_delay = 5
maxHealth = 130
health = 130
obj_damage = 15
melee_damage_lower = 7.5
melee_damage_upper = 7.5
rapid_melee = 2 // every second attack
dodging = TRUE
dodge_prob = 50
attacktext = "bites"
attack_sound = 'sound/weapons/bite.ogg'
vision_range = 7
aggro_vision_range = 7
move_force = MOVE_FORCE_WEAK
move_resist = MOVE_FORCE_WEAK
pull_force = MOVE_FORCE_WEAK
butcher_results = list(/obj/item/reagent_containers/food/snacks/meat/slab = 2, /obj/item/stack/sheet/sinew/wolf = 2, /obj/item/stack/sheet/bone = 2)
loot = list()
crusher_loot = /obj/item/crusher_trophy/watcher_wing
stat_attack = UNCONSCIOUS
robust_searching = TRUE
/// Message for when the wolf decides to start running away
var/retreat_message_said = FALSE
/mob/living/simple_animal/hostile/asteroid/wolf/Move(atom/newloc)
if(newloc && newloc.z == z && (islava(newloc) || ischasm(newloc)))
return FALSE
return ..()
/mob/living/simple_animal/hostile/asteroid/wolf/adjustHealth(amount, updating_health = TRUE, forced = FALSE)
. = ..()
if(stat == DEAD || health > maxHealth*0.1)
retreat_distance = initial(retreat_distance)
return
if(!retreat_message_said && target)
visible_message("<span class='danger'>The [name] tries to flee from [target]!</span>")
retreat_message_said = TRUE
retreat_distance = 30
/mob/living/simple_animal/hostile/asteroid/wolf/Life()
. = ..()
if(!. || target)
return
adjustHealth(-maxHealth*0.025)
retreat_message_said = FALSE

View File

@@ -1,14 +1,13 @@
/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"
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 +20,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 +30,245 @@
minbodytemp = 270
maxbodytemp = 370
unsuitable_atmos_damage = 10
do_footstep = TRUE
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

View File

@@ -41,6 +41,9 @@ Contents:
for(var/obj/effect/landmark/carpspawn/L in GLOB.landmarks_list)
if(isturf(L.loc))
spawn_locs += L.loc
for(var/obj/effect/landmark/loneopspawn/L in GLOB.landmarks_list)
if(isturf(L.loc))
spawn_locs += L.loc
if(!spawn_locs.len)
return kill()
spawn_loc = pick(spawn_locs)

View File

@@ -182,18 +182,14 @@
var/path = pick(/mob/living/simple_animal/hostile/carp,
/mob/living/simple_animal/hostile/bear,
/mob/living/simple_animal/hostile/mushroom,
/mob/living/simple_animal/hostile/statue,
/mob/living/simple_animal/hostile/retaliate/bat,
/mob/living/simple_animal/hostile/retaliate/goat,
/mob/living/simple_animal/hostile/killertomato,
/mob/living/simple_animal/hostile/poison/giant_spider,
/mob/living/simple_animal/hostile/poison/giant_spider/hunter,
/mob/living/simple_animal/hostile/blob/blobbernaut/independent,
/mob/living/simple_animal/hostile/carp/ranged,
/mob/living/simple_animal/hostile/carp/ranged/chaos,
/mob/living/simple_animal/hostile/asteroid/basilisk/watcher,
/mob/living/simple_animal/hostile/asteroid/goliath/beast,
/mob/living/simple_animal/hostile/headcrab,
/mob/living/simple_animal/hostile/morph,
/mob/living/simple_animal/hostile/stickman,
/mob/living/simple_animal/hostile/stickman/dog,

View File

@@ -0,0 +1,37 @@
GLOBAL_LIST_EMPTY(cursed_minds)
/**
* Turns whoever enters into a mob
*
* If mob is chosen, turns the person into a random animal type
* Once the spring is used, it cannot be used by the same mind ever again
* After usage, teleports the user back to a random safe turf (so mobs are not killed by ice moon atmosphere)
*
*/
/turf/open/water/cursed_spring
baseturfs = /turf/open/water/cursed_spring
initial_gas_mix = ICEMOON_DEFAULT_ATMOS
/turf/open/water/cursed_spring/Entered(atom/movable/thing, atom/oldLoc)
. = ..()
if(!isliving(thing))
return
var/mob/living/L = thing
if(!L.client)
return
if(GLOB.cursed_minds[L.mind])
return
GLOB.cursed_minds[L.mind] = TRUE
RegisterSignal(L.mind, COMSIG_PARENT_QDELETING, .proc/remove_from_cursed)
L = wabbajack(L, "animal") // Appearance randomization removed so citadel players don't get randomized into some ungodly ugly creature and complain
var/turf/T = find_safe_turf()
L.forceMove(T)
to_chat(L, "<span class='notice'>You blink and find yourself in [get_area_name(T)].</span>")
/**
* Deletes minds from the cursed minds list after their deletion
*
*/
/turf/open/water/cursed_spring/proc/remove_from_cursed(datum/mind/M)
GLOB.cursed_minds -= M

View File

@@ -0,0 +1,33 @@
/obj/machinery/door/keycard/library
name = "wooden door"
desc = "A dusty, scratched door with a thick lock attached."
icon = 'icons/obj/doors/puzzledoor/wood.dmi'
puzzle_id = "library"
open_message = "The door opens with a loud creak."
/obj/item/keycard/library
name = "golden key"
desc = "A dull, golden key."
icon_state = "golden_key"
puzzle_id = "library"
/obj/item/paper/crumpled/bloody/fluff/stations/lavaland/library/warning
name = "ancient note"
info = "<b>Here lies the vast collection of He Who Knows Ten Thousand Things. May all who pursue this knowledge for power be cursed a thousand times.</b>"
/obj/item/paper/crumpled/fluff/stations/lavaland/library/diary
name = "diary entry 13"
info = "It has been a week since the library was buried. I am so hungry that I can barely muster the energy to think, let alone write. The owl is gone."
/obj/item/paper/crumpled/fluff/stations/lavaland/library/diary2
name = "diary entry 18"
info = "I've lost track of time. I lack the strength to even pick up books off the shelves. To think, after all this time spent searching for the library, I will die before I can so much as graze the depth of its knowledge."
/obj/item/feather
name = "feather"
desc = "A dark, wilting feather. It seems as old as time."
icon = 'icons/obj/objects.dmi'
icon_state = "feather"
force = 0
throwforce = 0
w_class = WEIGHT_CLASS_TINY

View File

@@ -557,7 +557,7 @@
dwidth = 1
width = 3
height = 4
var/target_area = /area/lavaland/surface/outdoors
var/target_area = list(/area/lavaland/surface/outdoors, /area/icemoon/underground/unexplored/rivers)
var/edge_distance = 16
// Minimal distance from the map edge, setting this too low can result in shuttle landing on the edge and getting "sliced"

View File

@@ -13,6 +13,7 @@
var/view_range = 7
var/x_offset = 0
var/y_offset = 0
var/list/whitelist_turfs = list(/turf/open/space, /turf/open/floor/plating, /turf/open/lava)
var/space_turfs_only = TRUE
var/see_hidden = FALSE
var/designate_time = 0
@@ -22,6 +23,7 @@
/obj/machinery/computer/camera_advanced/shuttle_docker/Initialize()
. = ..()
GLOB.navigation_computers += src
whitelist_turfs = typecacheof(whitelist_turfs)
/obj/machinery/computer/camera_advanced/shuttle_docker/Destroy()
. = ..()
@@ -226,6 +228,11 @@
if(!ispath(turf_type, /turf/open/space))
return SHUTTLE_DOCKER_BLOCKED
if(length(whitelist_turfs))
var/turf_type = hidden_turf_info ? hidden_turf_info[2] : T.type
if(!is_type_in_typecache(turf_type, whitelist_turfs))
return SHUTTLE_DOCKER_BLOCKED
// Checking for overlapping dock boundaries
for(var/i in 1 to overlappers.len)
var/obj/docking_port/port = overlappers[i]

View File

@@ -62,6 +62,8 @@
view_range = 13
x_offset = -7
y_offset = -1
space_turfs_only = FALSE
whitelist_turfs = list(/turf/open/space, /turf/open/floor/plating, /turf/open/lava, /turf/closed/mineral)
see_hidden = TRUE
#undef SYNDICATE_CHALLENGE_TIMER
#undef SYNDICATE_CHALLENGE_TIMER