# Conflicts:
#	code/modules/ninja/suit/ninjaDrainAct.dm
This commit is contained in:
zerothebigboy
2021-05-02 22:47:39 -04:00
448 changed files with 310031 additions and 306315 deletions
File diff suppressed because it is too large Load Diff
+4
View File
@@ -30,3 +30,7 @@
var/obj/machinery/camera/cam = X
cam.lostTargetRef(WEAKREF(O))
return
/area/ai_monitored/turret_protected/ai/Initialize()
. = ..()
src.area_flags |= ABDUCTOR_PROOF
+50 -52
View File
@@ -13,6 +13,8 @@
mouse_opacity = MOUSE_OPACITY_TRANSPARENT
invisibility = INVISIBILITY_LIGHTING
var/area_flags = VALID_TERRITORY | BLOBS_ALLOWED | UNIQUE_AREA
var/fire = null
///Whether there is an atmos alarm in this area
var/atmosalm = FALSE
@@ -60,7 +62,7 @@
///This datum, if set, allows terrain generation behavior to be ran on Initialize()
// var/datum/map_generator/map_generator
var/datum/map_generator/map_generator
///Used to decide what kind of reverb the area makes sound have
var/sound_environment = SOUND_ENVIRONMENT_NONE
@@ -70,12 +72,8 @@
/// Set in New(); preserves the name set by the map maker, even if renamed by the Blueprints.
var/map_name
/// If it's valid territory for gangs/cults to summon
var/valid_territory = TRUE
/// malf ais can hack this
var/valid_malf_hack = 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
@@ -107,14 +105,10 @@
var/static_light = 0
var/static_environ
/// 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
var/no_air = null
@@ -157,7 +151,7 @@ GLOBAL_LIST_EMPTY(teleportlocs)
/proc/process_teleport_locs()
for(var/V in GLOB.sortedAreas)
var/area/AR = V
if(istype(AR, /area/shuttle) || AR.noteleport)
if(istype(AR, /area/shuttle) || (AR.area_flags & NOTELEPORT))
continue
if(GLOB.teleportlocs[AR.name])
continue
@@ -177,7 +171,7 @@ GLOBAL_LIST_EMPTY(teleportlocs)
/area/New()
// This interacts with the map loader, so it needs to be set immediately
// rather than waiting for atoms to initialize.
if (unique)
if (area_flags & UNIQUE_AREA)
GLOB.areas_by_type[type] = src
if(!minimap_color) // goes in New() because otherwise it doesn't fucking work
@@ -228,7 +222,7 @@ GLOBAL_LIST_EMPTY(teleportlocs)
reg_in_areas_in_z()
//so far I'm only implementing it on mapped unique areas, it's easier this way.
if(unique && sub_areas)
if((area_flags & UNIQUE_AREA) && sub_areas)
if(type in sub_areas)
WARNING("\"[src]\" typepath found inside its own sub-areas list, please make sure it doesn't share its parent type initial sub-areas value.")
sub_areas = null
@@ -261,21 +255,20 @@ GLOBAL_LIST_EMPTY(teleportlocs)
power_change() // all machines set to current power level, also updates icon
update_beauty()
/// Soon ™
/area/proc/RunGeneration()
// if(map_generator)
// map_generator = new map_generator()
// var/list/turfs = list()
// for(var/turf/T in contents)
// turfs += T
// map_generator.generate_terrain(turfs)
if(map_generator)
map_generator = new map_generator()
var/list/turfs = list()
for(var/turf/T in contents)
turfs += T
map_generator.generate_terrain(turfs)
/area/proc/test_gen()
// if(map_generator)
// var/list/turfs = list()
// for(var/turf/T in contents)
// turfs += T
// map_generator.generate_terrain(turfs)
if(map_generator)
var/list/turfs = list()
for(var/turf/T in contents)
turfs += T
map_generator.generate_terrain(turfs)
/**
* Register this area as belonging to a z level
@@ -327,6 +320,8 @@ GLOBAL_LIST_EMPTY(teleportlocs)
* Sends to all ai players, alert consoles, drones and alarm monitor programs in the world
*/
/area/proc/poweralert(state, obj/source)
if (area_flags & NO_ALERTS)
return
if (state != poweralm)
poweralm = state
if(istype(source)) //Only report power alarms on the z-level where the source is located.
@@ -358,6 +353,8 @@ GLOBAL_LIST_EMPTY(teleportlocs)
p.triggerAlarm("Power", src, cameras, source)
/area/proc/atmosalert(danger_level, obj/source)
if (area_flags & NO_ALERTS)
return
if(danger_level != atmosalm)
if (danger_level==2)
@@ -420,19 +417,19 @@ GLOBAL_LIST_EMPTY(teleportlocs)
if (!fire)
set_fire_alarm_effects(TRUE)
ModifyFiredoors(FALSE)
for (var/item in GLOB.alert_consoles)
var/obj/machinery/computer/station_alert/a = item
a.triggerAlarm("Fire", src, cameras, source)
for (var/item in GLOB.silicon_mobs)
var/mob/living/silicon/aiPlayer = item
aiPlayer.triggerAlarm("Fire", src, cameras, source)
for (var/item in GLOB.drones_list)
var/mob/living/simple_animal/drone/D = item
D.triggerAlarm("Fire", src, cameras, source)
for(var/item in GLOB.alarmdisplay)
var/datum/computer_file/program/alarm_monitor/p = item
p.triggerAlarm("Fire", src, cameras, source)
if (!(area_flags & NO_ALERTS)) //Check here instead at the start of the proc so that fire alarms can still work locally even in areas that don't send alerts
for (var/item in GLOB.alert_consoles)
var/obj/machinery/computer/station_alert/a = item
a.triggerAlarm("Fire", src, cameras, source)
for (var/item in GLOB.silicon_mobs)
var/mob/living/silicon/aiPlayer = item
aiPlayer.triggerAlarm("Fire", src, cameras, source)
for (var/item in GLOB.drones_list)
var/mob/living/simple_animal/drone/D = item
D.triggerAlarm("Fire", src, cameras, source)
for(var/item in GLOB.alarmdisplay)
var/datum/computer_file/program/alarm_monitor/p = item
p.triggerAlarm("Fire", src, cameras, source)
START_PROCESSING(SSobj, src)
@@ -441,18 +438,19 @@ GLOBAL_LIST_EMPTY(teleportlocs)
set_fire_alarm_effects(FALSE)
ModifyFiredoors(TRUE)
for (var/item in GLOB.silicon_mobs)
var/mob/living/silicon/aiPlayer = item
aiPlayer.cancelAlarm("Fire", src, source)
for (var/item in GLOB.alert_consoles)
var/obj/machinery/computer/station_alert/a = item
a.cancelAlarm("Fire", src, source)
for (var/item in GLOB.drones_list)
var/mob/living/simple_animal/drone/D = item
D.cancelAlarm("Fire", src, source)
for(var/item in GLOB.alarmdisplay)
var/datum/computer_file/program/alarm_monitor/p = item
p.cancelAlarm("Fire", src, source)
if (!(area_flags & NO_ALERTS)) //Check here instead at the start of the proc so that fire alarms can still work locally even in areas that don't send alerts
for (var/item in GLOB.silicon_mobs)
var/mob/living/silicon/aiPlayer = item
aiPlayer.cancelAlarm("Fire", src, source)
for (var/item in GLOB.alert_consoles)
var/obj/machinery/computer/station_alert/a = item
a.cancelAlarm("Fire", src, source)
for (var/item in GLOB.drones_list)
var/mob/living/simple_animal/drone/D = item
D.cancelAlarm("Fire", src, source)
for(var/item in GLOB.alarmdisplay)
var/datum/computer_file/program/alarm_monitor/p = item
p.cancelAlarm("Fire", src, source)
STOP_PROCESSING(SSobj, src)
@@ -467,7 +465,7 @@ GLOBAL_LIST_EMPTY(teleportlocs)
DOOR.lock()
/area/proc/burglaralert(obj/trigger)
if(always_unpowered) //no burglar alarms in space/asteroid
if (area_flags & NO_ALERTS)
return
//Trigger alarm effect
@@ -675,9 +673,9 @@ GLOBAL_LIST_EMPTY(teleportlocs)
power_light = FALSE
power_environ = FALSE
always_unpowered = FALSE
valid_territory = FALSE
valid_malf_hack = FALSE
blob_allowed = FALSE
area_flags &= ~VALID_TERRITORY
area_flags &= ~BLOBS_ALLOWED
addSorted()
/area/proc/update_areasize()
+6
View File
@@ -8,6 +8,7 @@ Unused icons for new areas are "awaycontent1" ~ "awaycontent30"
name = "Strange Location"
icon_state = "away"
has_gravity = STANDARD_GRAVITY
// ambience_index = AMBIENCE_AWAY
ambientsounds = AWAY_MISSION
sound_environment = SOUND_ENVIRONMENT_ROOM
@@ -27,3 +28,8 @@ Unused icons for new areas are "awaycontent1" ~ "awaycontent30"
/area/awaymission/vr
name = "Virtual Reality"
icon_state = "awaycontent1"
requires_power = FALSE
dynamic_lighting = DYNAMIC_LIGHTING_DISABLED
var/pacifist = TRUE // if when you enter this zone, you become a pacifist or not
var/death = FALSE // if when you enter this zone, you die
// network_root_id = "VR"
+20 -12
View File
@@ -1,14 +1,17 @@
// CENTCOM
// Side note, be sure to change the network_root_id of any areas that are not a part of centcom
// and just using the z space as safe harbor. It shouldn't matter much as centcom z is isolated
// from everything anyway
/area/centcom
name = "CentCom"
icon_state = "centcom"
dynamic_lighting = DYNAMIC_LIGHTING_FORCED
requires_power = FALSE
has_gravity = STANDARD_GRAVITY
noteleport = TRUE
blob_allowed = FALSE //Should go without saying, no blobs should take over centcom as a win condition.
area_flags = VALID_TERRITORY | UNIQUE_AREA | NOTELEPORT
flags_1 = NONE
/area/centcom/control
@@ -33,6 +36,7 @@
name = "VIP Zone"
dynamic_lighting = DYNAMIC_LIGHTING_DISABLED
// dear mappers who make winterball: THROW YOUR AREAS IN A DIFFERENT MAP, THIS IS DEFAULT GAME STUFF NOT EVENT STUFF
/area/centcom/winterball
name = "winterball Zone"
dynamic_lighting = DYNAMIC_LIGHTING_DISABLED
@@ -56,7 +60,7 @@
var/loading_id = ""
/area/centcom/supplypod/loading/Initialize()
. = ..()
. = ..()
if(!loading_id)
CRASH("[type] created without a loading_id")
if(GLOB.supplypod_loading_bays[loading_id])
@@ -128,17 +132,19 @@
dynamic_lighting = DYNAMIC_LIGHTING_FORCED
requires_power = FALSE
has_gravity = STANDARD_GRAVITY
noteleport = TRUE
area_flags = VALID_TERRITORY | UNIQUE_AREA | NOTELEPORT
flags_1 = NONE
// network_root_id = "MAGIC_NET"
//Abductors
/area/abductor_ship
name = "Abductor Ship"
icon_state = "yellow"
requires_power = FALSE
noteleport = TRUE
area_flags = VALID_TERRITORY | UNIQUE_AREA | NOTELEPORT
has_gravity = STANDARD_GRAVITY
flags_1 = NONE
// network_root_id = "ALIENS"
//Syndicates
/area/syndicate_mothership
@@ -146,26 +152,28 @@
icon_state = "syndie-ship"
requires_power = FALSE
has_gravity = STANDARD_GRAVITY
noteleport = TRUE
blob_allowed = FALSE //Not... entirely sure this will ever come up... but if the bus makes blobs AND ops, it shouldn't aim for the ops to win.
area_flags = VALID_TERRITORY | UNIQUE_AREA | NOTELEPORT
flags_1 = NONE
// ambience_index = AMBIENCE_DANGER
ambientsounds = HIGHSEC
// network_root_id = SYNDICATE_NETWORK_ROOT
/area/syndicate_mothership/control
name = "Syndicate Control Room"
icon_state = "syndie-control"
dynamic_lighting = DYNAMIC_LIGHTING_FORCED
// network_root_id = SYNDICATE_NETWORK_ROOT
/area/syndicate_mothership/elite_squad
name = "Syndicate Elite Squad"
icon_state = "syndie-elite"
// network_root_id = SYNDICATE_NETWORK_ROOT
/area/fabric_of_reality
name = "Tear in the Fabric of Reality"
requires_power = FALSE
has_gravity = TRUE
noteleport = TRUE
blob_allowed = FALSE
area_flags = UNIQUE_AREA | NOTELEPORT
//CAPTURE THE FLAG
@@ -174,6 +182,7 @@
icon_state = "yellow"
requires_power = FALSE
has_gravity = STANDARD_GRAVITY
flags_1 = NONE
/area/ctf/control_room
name = "Control Room A"
@@ -209,11 +218,10 @@
icon_state = "yellow"
requires_power = FALSE
has_gravity = STANDARD_GRAVITY
noteleport = TRUE
hidden = TRUE
area_flags = HIDDEN_AREA | NOTELEPORT | UNIQUE_AREA
ambientsounds = REEBE
/area/reebe/city_of_cogs
name = "City of Cogs"
icon_state = "purple"
hidden = FALSE
area_flags = NOTELEPORT | UNIQUE_AREA
+4 -3
View File
@@ -2,12 +2,13 @@
name = "Holodeck"
icon_state = "Holodeck"
dynamic_lighting = DYNAMIC_LIGHTING_DISABLED
flags_1 = 0
hidden = TRUE
flags_1 = NONE
area_flags = VALID_TERRITORY | UNIQUE_AREA
sound_environment = SOUND_ENVIRONMENT_PADDED_CELL
var/obj/machinery/computer/holodeck/linked
var/restricted = 0 // if true, program goes on emag list
var/restricted = FALSE // if true, program goes on emag list
// network_root_id = "HOLODECK"
/*
Power tracking: Use the holodeck computer's power grid
+68 -45
View File
@@ -3,44 +3,49 @@
/area/mine
icon_state = "mining"
has_gravity = STANDARD_GRAVITY
flora_allowed = TRUE
area_flags = VALID_TERRITORY | UNIQUE_AREA | FLORA_ALLOWED
/area/mine/explored
name = "Mine"
icon_state = "explored"
music = null
always_unpowered = TRUE
requires_power = TRUE
poweralm = FALSE
power_environ = FALSE
power_equip = FALSE
power_light = FALSE
outdoors = TRUE
flags_1 = NONE
// ambience_index = AMBIENCE_MINING
ambientsounds = MINING
flora_allowed = FALSE
area_flags = VALID_TERRITORY | UNIQUE_AREA | NO_ALERTS
sound_environment = SOUND_AREA_STANDARD_STATION
// min_ambience_cooldown = 70 SECONDS
// max_ambience_cooldown = 220 SECONDS
/area/mine/unexplored
name = "Mine"
icon_state = "unexplored"
music = null
always_unpowered = TRUE
requires_power = TRUE
poweralm = FALSE
power_environ = FALSE
power_equip = FALSE
power_light = FALSE
outdoors = TRUE
flags_1 = NONE
// ambience_index = AMBIENCE_MINING
ambientsounds = MINING
tunnel_allowed = TRUE
area_flags = VALID_TERRITORY | UNIQUE_AREA | NO_ALERTS | CAVES_ALLOWED | FLORA_ALLOWED | MOB_SPAWN_ALLOWED | MEGAFAUNA_SPAWN_ALLOWED
map_generator = /datum/map_generator/cave_generator
// min_ambience_cooldown = 70 SECONDS
// max_ambience_cooldown = 220 SECONDS
/area/mine/lobby
name = "Mining Station"
icon_state = "mining_lobby"
/area/mine/storage
name = "Mining Station Storage"
icon_state = "mining_storage"
/area/mine/production
name = "Mining Station Starboard Wing"
@@ -62,19 +67,27 @@
/area/mine/cafeteria
name = "Mining Station Cafeteria"
icon_state = "mining_labor_cafe"
/area/mine/hydroponics
name = "Mining Station Hydroponics"
icon_state = "mining_labor_hydro"
/area/mine/sleeper
name = "Mining Station Emergency Sleeper"
/area/mine/mechbay
name = "Mining Station Mech Bay"
icon_state = "mechbay"
/area/mine/laborcamp
name = "Labor Camp"
icon_state = "mining_labor"
/area/mine/laborcamp/security
name = "Labor Camp Security"
icon_state = "security"
// ambience_index = AMBIENCE_DANGER
ambientsounds = HIGHSEC
@@ -86,33 +99,36 @@
icon_state = "mining"
has_gravity = STANDARD_GRAVITY
flags_1 = NONE
flora_allowed = TRUE
area_flags = VALID_TERRITORY | UNIQUE_AREA | FLORA_ALLOWED
sound_environment = SOUND_AREA_LAVALAND
/area/lavaland/surface
name = "Lavaland"
icon_state = "explored"
music = null
always_unpowered = TRUE
poweralm = FALSE
power_environ = FALSE
power_equip = FALSE
power_light = FALSE
requires_power = TRUE
// ambience_index = AMBIENCE_MINING
ambientsounds = MINING
area_flags = VALID_TERRITORY | UNIQUE_AREA | FLORA_ALLOWED | NO_ALERTS
// min_ambience_cooldown = 70 SECONDS
// max_ambience_cooldown = 220 SECONDS
/area/lavaland/underground
name = "Lavaland Caves"
icon_state = "unexplored"
music = null
always_unpowered = TRUE
requires_power = TRUE
poweralm = FALSE
power_environ = FALSE
power_equip = FALSE
power_light = FALSE
// ambience_index = AMBIENCE_MINING
ambientsounds = MINING
area_flags = VALID_TERRITORY | UNIQUE_AREA | FLORA_ALLOWED | NO_ALERTS
// min_ambience_cooldown = 70 SECONDS
// max_ambience_cooldown = 220 SECONDS
/area/lavaland/surface/outdoors
name = "Lavaland Wastes"
@@ -120,16 +136,16 @@
/area/lavaland/surface/outdoors/unexplored //monsters and ruins spawn here
icon_state = "unexplored"
tunnel_allowed = TRUE
mob_spawn_allowed = TRUE
area_flags = VALID_TERRITORY | UNIQUE_AREA | CAVES_ALLOWED | FLORA_ALLOWED | MOB_SPAWN_ALLOWED | NO_ALERTS
map_generator = /datum/map_generator/cave_generator/lavaland
/area/lavaland/surface/outdoors/unexplored/danger //megafauna will also spawn here
icon_state = "danger"
megafauna_spawn_allowed = TRUE
area_flags = VALID_TERRITORY | UNIQUE_AREA | CAVES_ALLOWED | FLORA_ALLOWED | MOB_SPAWN_ALLOWED | MEGAFAUNA_SPAWN_ALLOWED | NO_ALERTS
/area/lavaland/surface/outdoors/explored
name = "Lavaland Labor Camp"
flora_allowed = FALSE
area_flags = VALID_TERRITORY | UNIQUE_AREA | NO_ALERTS
@@ -139,61 +155,68 @@
icon_state = "mining"
has_gravity = STANDARD_GRAVITY
flags_1 = NONE
flora_allowed = TRUE
blob_allowed = FALSE
area_flags = UNIQUE_AREA | FLORA_ALLOWED
sound_environment = SOUND_AREA_ICEMOON
/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
// ambience_index = AMBIENCE_MINING
ambientsounds = MINING
area_flags = UNIQUE_AREA | FLORA_ALLOWED | NO_ALERTS
// min_ambience_cooldown = 70 SECONDS
// max_ambience_cooldown = 220 SECONDS
/area/icemoon/surface/outdoors // weather happens here
name = "Icemoon Wastes"
outdoors = TRUE
/area/icemoon/surface/outdoors/labor_camp
name = "Icemoon Labor Camp"
area_flags = UNIQUE_AREA | NO_ALERTS
/area/icemoon/surface/outdoors/unexplored //monsters and ruins spawn here
icon_state = "unexplored"
area_flags = UNIQUE_AREA | FLORA_ALLOWED | MOB_SPAWN_ALLOWED | CAVES_ALLOWED | NO_ALERTS
/area/icemoon/surface/outdoors/unexplored/rivers // rivers spawn here
icon_state = "danger"
map_generator = /datum/map_generator/cave_generator/icemoon/surface
/area/icemoon/surface/outdoors/unexplored/rivers/no_monsters
area_flags = UNIQUE_AREA | FLORA_ALLOWED | CAVES_ALLOWED | NO_ALERTS
/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
// ambience_index = AMBIENCE_MINING
ambientsounds = MINING
area_flags = UNIQUE_AREA | FLORA_ALLOWED | NO_ALERTS
// min_ambience_cooldown = 70 SECONDS
// max_ambience_cooldown = 220 SECONDS
/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_flags = CAVES_ALLOWED | FLORA_ALLOWED | MOB_SPAWN_ALLOWED | MEGAFAUNA_SPAWN_ALLOWED | NO_ALERTS
/area/icemoon/underground/unexplored/rivers // rivers spawn here
icon_state = "danger"
map_generator = /datum/map_generator/cave_generator/icemoon
/area/icemoon/underground/explored
/area/icemoon/underground/unexplored/rivers/deep
map_generator = /datum/map_generator/cave_generator/icemoon/deep
/area/icemoon/underground/explored // ruins can't spawn here
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
area_flags = UNIQUE_AREA | NO_ALERTS
+51 -23
View File
@@ -2,9 +2,7 @@
/area/ruin/space
has_gravity = FALSE
blob_allowed = FALSE //Nope, no winning in space as a blob. Gotta eat the station.
outdoors = TRUE
ambientsounds = SPACE
area_flags = UNIQUE_AREA
/area/ruin/space/has_grav
has_gravity = STANDARD_GRAVITY
@@ -12,7 +10,6 @@
/area/ruin/space/has_grav/powered
requires_power = FALSE
/area/ruin/fakespace
icon_state = "space"
requires_power = TRUE
@@ -22,10 +19,8 @@
power_light = FALSE
power_equip = FALSE
power_environ = FALSE
valid_territory = FALSE
outdoors = TRUE
ambientsounds = SPACE
blob_allowed = FALSE
/////////////
@@ -133,22 +128,20 @@
/area/ruin/space/diner
name = "Space Diner"
area_flags = UNIQUE_AREA
/area/ruin/space/diner/interior
name = "Space Diner"
icon_state = "maintbar"
has_gravity = STANDARD_GRAVITY
blob_allowed = FALSE //Nope, no winning in the diner as a blob. Gotta eat the main station.
/area/ruin/space/diner/solars
requires_power = FALSE
dynamic_lighting = DYNAMIC_LIGHTING_IFSTARLIGHT
valid_territory = FALSE
blob_allowed = FALSE
flags_1 = NONE
ambientsounds = ENGINEERING
name = "Space Diner Solar Array"
icon_state = "yellow"
requires_power = FALSE
dynamic_lighting = DYNAMIC_LIGHTING_IFSTARLIGHT
flags_1 = NONE
ambientsounds = ENGINEERING
//Ruin of "Skelter" ship
@@ -257,7 +250,7 @@
//Ruin of old teleporter
/area/ruin/space/oldteleporter
name = "Old teleporter"
name = "Old Teleporter"
icon_state = "teleporter"
@@ -301,7 +294,7 @@
icon_state = "storage_wing"
/area/ruin/space/has_grav/deepstorage/dorm
name = "Deep Storage Dormory"
name = "Deep Storage Dormitory"
icon_state = "crew_quarters"
/area/ruin/space/has_grav/deepstorage/kitchen
@@ -339,7 +332,9 @@
/area/ruin/space/has_grav/ancientstation/atmo
name = "Beta Station Atmospherics"
icon_state = "red"
has_gravity = FALSE
// ambience_index = AMBIENCE_ENGI
ambientsounds = ENGINEERING
has_gravity = TRUE
/area/ruin/space/has_grav/ancientstation/betanorth
name = "Beta Station North Corridor"
@@ -349,9 +344,15 @@
name = "Station Solar Array"
icon_state = "panelsAP"
/area/ruin/space/has_grav/ancientstation/betacorridor
name = "Beta Station Main Corridor"
icon_state = "bluenew"
/area/ruin/space/has_grav/ancientstation/engi
name = "Charlie Station Engineering"
icon_state = "engine"
// ambience_index = AMBIENCE_ENGI
ambientsounds = ENGINEERING
/area/ruin/space/has_grav/ancientstation/comm
name = "Charlie Station Command"
@@ -385,6 +386,27 @@
name = "Hivebot Mothership"
icon_state = "teleporter"
/area/ruin/space/has_grav/ancientstation/deltaai
name = "Delta Station AI Core"
icon_state = "ai"
ambientsounds = list('sound/ambience/ambimalf.ogg', 'sound/ambience/ambitech.ogg', 'sound/ambience/ambitech2.ogg', 'sound/ambience/ambiatmos.ogg', 'sound/ambience/ambiatmos2.ogg')
/area/ruin/space/has_grav/ancientstation/mining
name = "Beta Station Mining Equipment"
icon_state = "mining"
/area/ruin/space/has_grav/ancientstation/medbay
name = "Beta Station Medbay"
icon_state = "medbay"
/area/ruin/space/has_grav/ancientstation/betastorage
name = "Beta Station Storage"
icon_state = "storage"
/area/solars/ancientstation
name = "Charlie Station Solar Array"
icon_state = "panelsP"
//DERELICT
/area/ruin/space/derelict
@@ -469,11 +491,11 @@
name = "Abandoned Ship"
icon_state = "yellow"
/area/solar/derelict_starboard
/area/solars/derelict_starboard
name = "Derelict Starboard Solar Array"
icon_state = "panelsS"
/area/solar/derelict_aft
/area/solars/derelict_aft
name = "Derelict Aft Solar Array"
icon_state = "yellow"
@@ -496,28 +518,24 @@
power_light = FALSE
power_environ = FALSE
//DJSTATION
/area/ruin/space/djstation
name = "Ruskie DJ Station"
icon_state = "DJ"
has_gravity = STANDARD_GRAVITY
blob_allowed = FALSE //Nope, no winning on the DJ station as a blob. Gotta eat the main station.
/area/ruin/space/djstation/solars
name = "DJ Station Solars"
icon_state = "DJ"
has_gravity = STANDARD_GRAVITY
//ABANDONED TELEPORTER
/area/ruin/space/abandoned_tele
name = "Abandoned Teleporter"
icon_state = "teleporter"
music = "signal"
ambientsounds = list('sound/ambience/ambimalf.ogg')
ambientsounds = list('sound/ambience/ambimalf.ogg', 'sound/ambience/signal.ogg')
//OLD AI SAT
@@ -561,3 +579,13 @@
/area/ruin/space/has_grav/powered/advancedlab
name = "Abductor Replication Lab"
icon_state = "yellow"
//HELL'S FACTORY OPERATING FACILITY
// /area/ruin/space/has_grav/hellfactory
// name = "Hell Factory"
// icon_state = "yellow"
// /area/ruin/space/has_grav/hellfactoryoffice
// name = "Hell Factory Office"
// icon_state = "red"
// area_flags = VALID_TERRITORY | BLOBS_ALLOWED | UNIQUE_AREA | NOTELEPORT
+45 -26
View File
@@ -8,10 +8,11 @@
dynamic_lighting = DYNAMIC_LIGHTING_FORCED
has_gravity = STANDARD_GRAVITY
always_unpowered = FALSE
valid_territory = FALSE
icon_state = "shuttle"
// Loading the same shuttle map at a different time will produce distinct area instances.
unique = FALSE
area_flags = NO_ALERTS
icon_state = "shuttle"
flags_1 = CAN_BE_DIRTY_1
// area_limited_icon_smoothing = /area/shuttle
sound_environment = SOUND_ENVIRONMENT_ROOM
/area/shuttle/Initialize()
@@ -32,7 +33,8 @@
/area/shuttle/syndicate
name = "Syndicate Infiltrator"
blob_allowed = FALSE
// ambience_index = AMBIENCE_DANGER
// area_limited_icon_smoothing = /area/shuttle/syndicate
ambientsounds = HIGHSEC
canSmoothWithAreas = /area/shuttle/syndicate
@@ -57,7 +59,6 @@
/area/shuttle/pirate
name = "Pirate Shuttle"
blob_allowed = FALSE
requires_power = TRUE
canSmoothWithAreas = /area/shuttle/pirate
@@ -65,12 +66,22 @@
name = "Pirate Shuttle Vault"
requires_power = FALSE
/area/shuttle/pirate/flying_dutchman
name = "Flying Dutchman"
requires_power = FALSE
////////////////////////////Bounty Hunter Shuttles////////////////////////////
/area/shuttle/hunter
name = "Hunter Shuttle"
dynamic_lighting = DYNAMIC_LIGHTING_DISABLED
////////////////////////////White Ship////////////////////////////
/area/shuttle/abandoned
name = "Abandoned Ship"
blob_allowed = FALSE
requires_power = TRUE
// area_limited_icon_smoothing = /area/shuttle/abandoned
canSmoothWithAreas = /area/shuttle/abandoned
/area/shuttle/abandoned/bridge
@@ -94,13 +105,6 @@
/area/shuttle/abandoned/pod
name = "Abandoned Ship Pod"
////////////////////////////Bounty Hunter Shuttles////////////////////////////
/area/shuttle/hunter
name = "Hunter Shuttle"
dynamic_lighting = DYNAMIC_LIGHTING_DISABLED
blob_allowed = FALSE
canSmoothWithAreas = /area/shuttle/hunter
////////////////////////////Single-area shuttles////////////////////////////
/area/shuttle/transit
@@ -117,44 +121,67 @@
/area/shuttle/arrival
name = "Arrival Shuttle"
unique = TRUE // SSjob refers to this area for latejoiners
area_flags = UNIQUE_AREA// SSjob refers to this area for latejoiners
/area/shuttle/pod_1
name = "Escape Pod One"
area_flags = BLOBS_ALLOWED
/area/shuttle/pod_2
name = "Escape Pod Two"
area_flags = BLOBS_ALLOWED
/area/shuttle/pod_3
name = "Escape Pod Three"
area_flags = BLOBS_ALLOWED
/area/shuttle/pod_4
name = "Escape Pod Four"
area_flags = BLOBS_ALLOWED
/area/shuttle/mining
name = "Mining Shuttle"
blob_allowed = FALSE
area_flags = NONE //Set this so it doesn't inherit NO_ALERTS
/area/shuttle/mining/large
name = "Mining Shuttle"
requires_power = TRUE
/area/shuttle/labor
name = "Labor Camp Shuttle"
blob_allowed = FALSE
area_flags = NONE //Set this so it doesn't inherit NO_ALERTS
/area/shuttle/supply
name = "Supply Shuttle"
blob_allowed = FALSE
area_flags = NOTELEPORT
/area/shuttle/escape
name = "Emergency Shuttle"
area_flags = BLOBS_ALLOWED
// area_limited_icon_smoothing = /area/shuttle/escape
canSmoothWithAreas = /area/shuttle/escape
flags_1 = CAN_BE_DIRTY_1 // | CULT_PERMITTED_1
/area/shuttle/escape/backup
name = "Backup Emergency Shuttle"
/area/shuttle/escape/brig
name = "Escape Shuttle Brig"
icon_state = "shuttlered"
/area/shuttle/escape/luxury
name = "Luxurious Emergency Shuttle"
// area_flags = NOTELEPORT
/area/shuttle/escape/simulation
name = "Medieval Reality Simulation Dome"
icon_state = "shuttlectf"
area_flags = NOTELEPORT
dynamic_lighting = DYNAMIC_LIGHTING_DISABLED
/area/shuttle/escape/arena
name = "The Arena"
noteleport = TRUE
area_flags = NOTELEPORT
/area/shuttle/escape/meteor
name = "\proper a meteor with engines strapped to it"
@@ -162,34 +189,26 @@
/area/shuttle/transport
name = "Transport Shuttle"
blob_allowed = FALSE
/area/shuttle/assault_pod
name = "Steel Rain"
blob_allowed = FALSE
/area/shuttle/sbc_starfury
name = "SBC Starfury"
blob_allowed = FALSE
/area/shuttle/sbc_fighter1
name = "SBC Fighter 1"
blob_allowed = FALSE
/area/shuttle/sbc_fighter2
name = "SBC Fighter 2"
blob_allowed = FALSE
/area/shuttle/sbc_corvette
name = "SBC corvette"
blob_allowed = FALSE
/area/shuttle/syndicate_scout
name = "Syndicate Scout"
blob_allowed = FALSE
/area/shuttle/caravan
blob_allowed = FALSE
requires_power = TRUE
/area/shuttle/caravan/syndicate1
+1 -19
View File
@@ -58,14 +58,6 @@ GLOBAL_VAR_INIT(dynamic_forced_storyteller, null)
var/threat_level = 0
/// The current antag threat. Recalculated every time a ruletype starts or ends.
var/threat = 0
/// Threat average over the course of the round, for endgame logs.
var/threat_average = 0
/// Number of times threat average has been calculated, for calculating above.
var/threat_average_weight = 0
/// Last time a threat average sample was taken. Used for weighting the rolling average.
var/last_threat_sample_time = 0
/// Maximum threat recorded so far, for cross-round chaos adjustment.
var/max_threat = 0
/// Things that cause a rolling threat adjustment to be displayed at roundend.
var/list/threat_tallies = list()
/// Running information about the threat. Can store text or datum entries.
@@ -745,17 +737,7 @@ GLOBAL_VAR_INIT(dynamic_forced_storyteller, null)
continue
if(!M.voluntary_ghosted)
current_players[CURRENT_DEAD_PLAYERS].Add(M) // Players who actually died (and admins who ghosted, would be nice to avoid counting them somehow)
threat = storyteller.calculate_threat() + added_threat
max_threat = max(max_threat,threat)
if(threat_average_weight)
var/cur_sample_weight = world.time - last_threat_sample_time
threat_average = ((threat_average * threat_average_weight) + (threat * cur_sample_weight)) / (threat_average_weight + cur_sample_weight)
threat_average_weight += cur_sample_weight
last_threat_sample_time = world.time
else
threat_average = threat
threat_average_weight++
last_threat_sample_time = world.time
threat = (SSactivity.current_threat * 0.6 + SSactivity.get_max_threat() * 0.2 + SSactivity.get_average_threat() * 0.2) + added_threat
/// Removes type from the list
/datum/game_mode/dynamic/proc/remove_from_list(list/type_list, type)
@@ -45,27 +45,6 @@ Property weights are added to the config weight of the ruleset. They are:
var/midround_injection_cooldown_middle = 0.5*(GLOB.dynamic_first_midround_delay_min + GLOB.dynamic_first_midround_delay_max)
mode.midround_injection_cooldown = round(clamp(EXP_DISTRIBUTION(midround_injection_cooldown_middle), GLOB.dynamic_first_midround_delay_min, GLOB.dynamic_first_midround_delay_max)) + world.time
/datum/dynamic_storyteller/proc/calculate_threat()
var/threat = 0
for(var/datum/antagonist/A in GLOB.antagonists)
if(A?.owner?.current && A.owner.current.stat != DEAD)
threat += A.threat()
for(var/r in SSevents.running)
var/datum/round_event/R = r
threat += R.threat()
for(var/obj/item/phylactery/P in GLOB.poi_list)
threat += 25 // can't be giving them too much of a break
for (var/mob/M in mode.current_players[CURRENT_LIVING_PLAYERS])
if (M?.mind?.assigned_role && M.stat != DEAD)
var/datum/job/J = SSjob.GetJob(M.mind.assigned_role)
if(J)
if(length(M.mind.antag_datums))
threat += J.GetThreat()
else
threat -= J.GetThreat()
threat += (mode.current_players[CURRENT_DEAD_PLAYERS].len)*dead_player_weight
return round(threat,0.1)
/datum/dynamic_storyteller/proc/do_process()
return
@@ -95,7 +74,7 @@ Property weights are added to the config weight of the ruleset. They are:
if(voters)
GLOB.dynamic_curve_centre += (mean/voters)
if(flags & USE_PREV_ROUND_WEIGHTS)
GLOB.dynamic_curve_centre += (50 - SSpersistence.average_dynamic_threat) / 10
GLOB.dynamic_curve_centre += (SSpersistence.average_threat) / 10
GLOB.dynamic_forced_threat_level = forced_threat_level
/datum/dynamic_storyteller/proc/get_midround_cooldown()
+6 -24
View File
@@ -5,28 +5,16 @@
continue
S.charge = 0
S.output_level = 0
S.output_attempt = 0
S.output_attempt = FALSE
S.update_icon()
S.power_change()
var/list/skipped_areas = list(/area/engine/engineering, /area/engine/supermatter, /area/engine/atmospherics_engine, /area/ai_monitored/turret_protected/ai)
for(var/area/A in world)
if( !A.requires_power || A.always_unpowered || A.base_area)
for(var/area/A in GLOB.the_station_areas)
if(!A.requires_power || A.always_unpowered )
continue
if(GLOB.typecache_powerfailure_safe_areas[A.type])
continue
var/skip = 0
for(var/area_type in skipped_areas)
if(istype(A,area_type))
skip = 1
break
if(A.contents)
for(var/atom/AT in A.contents)
if(!is_station_level(AT.z)) //Only check one, it's enough.
skip = 1
break
if(skip)
continue
A.power_light = FALSE
A.power_equip = FALSE
A.power_environ = FALSE
@@ -35,13 +23,7 @@
for(var/obj/machinery/power/apc/C in GLOB.apcs_list)
if(C.cell && is_station_level(C.z))
var/area/A = C.area
var/skip = 0
for(var/area_type in skipped_areas)
if(istype(A,area_type))
skip = 1
break
if(skip)
if(GLOB.typecache_powerfailure_safe_areas[A.type])
continue
C.cell.charge = 0
+1 -1
View File
@@ -420,7 +420,7 @@
for(var/mob/dead/new_player/player in players)
if(player.client && player.ready == PLAYER_READY_TO_PLAY)
if((role in player.client.prefs.be_special) && (ROLE_SYNDICATE in player.client.prefs.be_special))
if((role in player.client.prefs.be_special) && !(ROLE_NO_ANTAGONISM in player.client.prefs.be_special))
if(!jobban_isbanned(player, ROLE_SYNDICATE) && !QDELETED(player) && !jobban_isbanned(player, role) && !QDELETED(player)) //Nodrak/Carn: Antag Job-bans
if(age_check(player.client)) //Must be older than the minimum age
candidates += player.mind // Get a list of all the people who want to be the antagonist for this round
+1 -1
View File
@@ -413,7 +413,7 @@
for(var/z in SSmapping.levels_by_trait(ZTRAIT_STATION)) //First, collect all area types on the station zlevel
for(var/ar in SSmapping.areas_in_z["[z]"])
var/area/A = ar
if(!(A.type in valid_territories) && A.valid_territory)
if(!(A.type in valid_territories) && (A.area_flags & VALID_TERRITORY))
valid_territories |= A.type
return valid_territories.len
+19 -1
View File
@@ -412,6 +412,24 @@ If not set, defaults to check_completion instead. Set it. It's used by cryo.
counter++
return counter >= 8
/datum/objective/freedom
name = "freedom"
explanation_text = "Don't get captured by nanotrasen."
team_explanation_text = "Have all members of your team free of nanotrasen custody."
/datum/objective/freedom/check_completion()
var/list/datum/mind/owners = get_owners()
for(var/m in owners)
var/datum/mind/M = m
if(!considered_alive(M))
return FALSE
if(SSshuttle.emergency.mode != SHUTTLE_ENDGAME)
return FALSE
var/turf/location = get_turf(M.current)
if(!location || istype(location, /turf/open/floor/plasteel/shuttle/red) || istype(location, /turf/open/floor/mineral/plastitanium/red/brig)) // Fails if they are in the shuttle brig
return FALSE
return TRUE
/datum/objective/escape
name = "escape"
explanation_text = "Escape on the shuttle or an escape pod alive and without being in custody."
@@ -1240,7 +1258,7 @@ GLOBAL_LIST_EMPTY(possible_sabotages)
var/payout_bonus = 0
var/area/dropoff = null
var/static/list/blacklisted_areas = typecacheof(list(/area/ai_monitored/turret_protected,
/area/solar/,
/area/solars/,
/area/ruin/, //thank you station space ruins
/area/science/test_area/,
/area/shuttle/))
-64
View File
@@ -33,70 +33,6 @@
/datum/sabotage_objective/processing/check_conditions()
return won
/*
/datum/sabotage_objective/processing/power_sink
name = "Drain at least 100 megajoules of power using a power sink."
sabotage_type = "powersink"
special_equipment = list(/obj/item/sbeacondrop/powersink)
var/sink_found = FALSE
var/count = 0
/datum/sabotage_objective/processing/power_sink/check_condition_processing()
for(var/s in GLOB.power_sinks)
var/obj/item/powersink/sink = s
won = max(won,sink.power_drained/1e8)
*/
/obj/item/paper/guides/antag/supermatter_sabotage
info = "Ways to sabotage a supermatter:<br>\
<ul>\
<li>Set the air alarm's operating mode to anything that isn't 'draught' (yes, anything, though 'off' works best). Or just smash the air alarm, that works too.</li>\
<li>Wrench a pipe (the junction to the cold loop is most effective, but some setups will robust through this no issue; best to try for multiple)</li>\
<li>Pump in as much carbon dioxide, oxygen, plasma or tritium as you can find (this will likely also cause a singularity or tesla delamination, so watch out!)</li>\
<li>Unset the filters on the cooling loop, or, perhaps more insidious, set them to oxygen/plasma.</li>\
<li>Deactivate the digital valve that sends the exhaust gases to space (note: only works on box station; others you must unwrench).</li>\
<li>There are many other ways; be creative!</li>\
</ul>"
/*/datum/sabotage_objective/processing/supermatter
name = "Sabotage the supermatter so that it goes under 50% integrity. If it is delaminated, you will fail."
sabotage_type = "supermatter"
special_equipment = list(/obj/item/paper/guides/antag/supermatter_sabotage)
var/list/supermatters = list()
excludefromjob = list("Chief Engineer", "Station Engineer", "Atmospheric Technician")
/datum/sabotage_objective/processing/supermatter/check_condition_processing()
if(!supermatters.len)
supermatters = list()
for(var/obj/machinery/power/supermatter_crystal/S in GLOB.machines)
// Delaminating, not within coverage, not on a tile.
if (!isturf(S.loc) || !(is_station_level(S.z) || is_mining_level(S.z)))
continue
supermatters.Add(S)
for(var/obj/machinery/power/supermatter_crystal/S in supermatters) // you can win this with a wishgranter... lol.
won = max(1-((S.get_integrity()-50)/50),won)
return FALSE
/datum/sabotage_objective/processing/supermatter/can_run()
return (locate(/obj/machinery/power/supermatter_crystal) in GLOB.machines)
/datum/sabotage_objective/station_integrity
name = "Make sure the station is at less than 80% integrity by the end. Smash walls, windows etc. to reach this goal."
sabotage_type = "integrity"
/datum/sabotage_objective/station_integrity/check_conditions()
return 5-(max(SSticker.station_integrity*4,320)/80)
*/
/datum/sabotage_objective/cloner
name = "Destroy all Nanotrasen cloning machines."
sabotage_type = "cloner"
/datum/sabotage_objective/cloner/check_conditions()
for(var/obj/machinery/clonepod/cloner in GLOB.machines)
if(is_station_level(cloner.z))
return FALSE
return TRUE
/datum/sabotage_objective/ai_law
name = "Upload a hacked law to the AI."
sabotage_type = "ailaw"
+2
View File
@@ -519,6 +519,8 @@ Class Procs:
//called on machinery construction (i.e from frame to machinery) but not on initialization
/obj/machinery/proc/on_construction()
for(var/obj/I in contents)
I.moveToNullspace()
return
//called on deconstruction before the final deletion
+56 -16
View File
@@ -3,7 +3,7 @@
icon_state = "0"
state = 0
/obj/structure/frame/computer/attackby(obj/item/P, mob/user, params)
/obj/structure/frame/computer/attackby(obj/item/P, mob/living/user, params)
add_fingerprint(user)
switch(state)
if(0)
@@ -11,7 +11,7 @@
to_chat(user, "<span class='notice'>You start wrenching the frame into place...</span>")
if(P.use_tool(src, user, 20, volume=50))
to_chat(user, "<span class='notice'>You wrench the frame into place.</span>")
setAnchored(TRUE)
set_anchored(TRUE)
state = 1
return
if(P.tool_behaviour == TOOL_WELDER)
@@ -19,7 +19,7 @@
return
to_chat(user, "<span class='notice'>You start deconstructing the frame...</span>")
if(P.use_tool(src, user, 20, volume=50) && state == 0)
if(P.use_tool(src, user, 20, volume=50))
to_chat(user, "<span class='notice'>You deconstruct the frame.</span>")
var/obj/item/stack/sheet/metal/M = new (drop_location(), 5)
M.add_fingerprint(user)
@@ -28,15 +28,15 @@
if(1)
if(P.tool_behaviour == TOOL_WRENCH)
to_chat(user, "<span class='notice'>You start to unfasten the frame...</span>")
if(P.use_tool(src, user, 20, volume=50) && state == 1)
if(P.use_tool(src, user, 20, volume=50))
to_chat(user, "<span class='notice'>You unfasten the frame.</span>")
setAnchored(FALSE)
set_anchored(FALSE)
state = 0
return
if(istype(P, /obj/item/circuitboard/computer) && !circuit)
if(!user.transferItemToLoc(P, src))
return
playsound(src, 'sound/items/deconstruct.ogg', 50, 1)
playsound(src, 'sound/items/deconstruct.ogg', 50, TRUE)
to_chat(user, "<span class='notice'>You place [P] inside the frame.</span>")
icon_state = "1"
circuit = P
@@ -71,8 +71,10 @@
if(istype(P, /obj/item/stack/cable_coil))
if(!P.tool_start_check(user, amount=5))
return
if(state != 2)
return
to_chat(user, "<span class='notice'>You start adding cables to the frame...</span>")
if(P.use_tool(src, user, 20, 5, 50, CALLBACK(src, .proc/check_state, 2)))
if(P.use_tool(src, user, 20, volume=50, amount=5))
to_chat(user, "<span class='notice'>You add cables to the frame.</span>")
state = 3
icon_state = "3"
@@ -90,9 +92,11 @@
if(istype(P, /obj/item/stack/sheet/glass))
if(!P.tool_start_check(user, amount=2))
return
playsound(src, 'sound/items/deconstruct.ogg', 50, 1)
if(state != 3)
return
playsound(src, 'sound/items/deconstruct.ogg', 50, TRUE)
to_chat(user, "<span class='notice'>You start to put in the glass panel...</span>")
if(P.use_tool(src, user, 20, 2, 0, CALLBACK(src, .proc/check_state, 3)))
if(P.use_tool(src, user, 20, amount=2))
to_chat(user, "<span class='notice'>You put in the glass panel.</span>")
state = 4
src.icon_state = "4"
@@ -109,14 +113,51 @@
if(P.tool_behaviour == TOOL_SCREWDRIVER)
P.play_tool_sound(src)
to_chat(user, "<span class='notice'>You connect the monitor.</span>")
var/obj/B = new circuit.build_path (loc, circuit)
B.setDir(dir)
transfer_fingerprints_to(B)
var/obj/machinery/new_machine = new circuit.build_path(loc)
new_machine.setDir(dir)
transfer_fingerprints_to(new_machine)
if(istype(new_machine, /obj/machinery/computer))
var/obj/machinery/computer/new_computer = new_machine
// Machines will init with a set of default components.
// Triggering handle_atom_del will make the machine realise it has lost a component_parts and then deconstruct.
// Move to nullspace so we don't trigger handle_atom_del, then qdel.
// Finally, replace new machine's parts with this frame's parts.
if(new_computer.circuit)
// Move to nullspace and delete.
new_computer.circuit.moveToNullspace()
QDEL_NULL(new_computer.circuit)
for(var/old_part in new_computer.component_parts)
var/atom/movable/movable_part = old_part
// Move to nullspace and delete.
movable_part.moveToNullspace()
qdel(movable_part)
// Set anchor state and move the frame's parts over to the new machine.
// Then refresh parts and call on_construction().
new_computer.set_anchored(anchored)
new_computer.component_parts = list()
circuit.forceMove(new_computer)
new_computer.component_parts += circuit
new_computer.circuit = circuit
for(var/new_part in src)
var/atom/movable/movable_part = new_part
movable_part.forceMove(new_computer)
new_computer.component_parts += movable_part
new_computer.RefreshParts()
new_computer.on_construction()
qdel(src)
return
if(user.a_intent == INTENT_HARM)
return ..()
/obj/structure/frame/computer/deconstruct(disassembled = TRUE)
if(!(flags_1 & NODECONSTRUCT_1))
if(state == 4)
@@ -127,13 +168,12 @@
..()
/obj/structure/frame/computer/AltClick(mob/user)
. = ..()
if(!isliving(user) || !user.canUseTopic(src, BE_CLOSE, ismonkey(user)))
..()
if(!user.canUseTopic(src, BE_CLOSE, TRUE, FALSE))
return
if(anchored)
to_chat(usr, "<span class='warning'>You must unwrench [src] before rotating it!</span>")
return TRUE
return
setDir(turn(dir, -90))
return TRUE
+225 -304
View File
@@ -13,7 +13,7 @@
var/temp = "Inactive"
var/scantemp_ckey
var/scantemp_name
var/scantemp = "Ready to Scan"
var/scantemp = "Inactive"
var/menu = 1 //Which menu screen to display
var/datum/data/record/active_record = null
var/obj/item/disk/data/diskette = null //Mostly so the geneticist can steal everything.
@@ -132,7 +132,6 @@
src.diskette = W
to_chat(user, "<span class='notice'>You insert [W].</span>")
playsound(src, 'sound/machines/terminal_insert_disc.ogg', 50, 0)
src.updateUsrDialog()
else if(W.tool_behaviour == TOOL_MULTITOOL)
if(istype(W.buffer, clonepod_type))
if(get_area(W.buffer) != get_area(src))
@@ -151,311 +150,233 @@
else
return ..()
/obj/machinery/computer/cloning/ui_interact(mob/user)
/obj/machinery/computer/cloning/AltClick(mob/user)
. = ..()
EjectDisk(user)
updatemodules(TRUE)
/obj/machinery/computer/cloning/proc/EjectDisk(mob/user)
if(diskette)
scantemp = "Disk Ejected"
diskette.forceMove(drop_location())
usr.put_in_active_hand(diskette)
diskette = null
playsound(src, 'sound/machines/terminal_insert_disc.ogg', 50, 0)
var/dat = ""
dat += "<a href='byond://?src=[REF(src)];refresh=1'>Refresh</a>"
/obj/machinery/computer/cloning/proc/Save(mob/user, target)
var/datum/data/record/GRAB = null
for(var/datum/data/record/record in records)
if(record.fields["id"] == target)
GRAB = record
break
else
continue
if(!GRAB || !GRAB.fields)
playsound(src, 'sound/machines/terminal_prompt_deny.ogg', 50, 0)
scantemp = "Failed saving to disk: Data Corruption"
return FALSE
if(!diskette || diskette.read_only)
scantemp = !diskette ? "Failed saving to disk: No disk." : "Failed saving to disk: Disk refuses override attempt."
playsound(src, 'sound/machines/terminal_prompt_deny.ogg', 50, 0)
return
diskette.fields = GRAB.fields.Copy()
diskette.name = "data disk - '[src.diskette.fields["name"]]'"
scantemp = "Saved to disk successfully."
playsound(src, 'sound/machines/terminal_prompt_confirm.ogg', 50, 0)
/obj/machinery/computer/cloning/proc/DeleteRecord(mob/user, target)
var/datum/data/record/GRAB = null
for(var/datum/data/record/record in records)
if(record.fields["id"] == target)
GRAB = record
break
else
continue
if(!GRAB)
playsound(src, 'sound/machines/terminal_prompt_deny.ogg', 50, 0)
scantemp = "Cannot delete: Data Corrupted."
return FALSE
var/obj/item/card/id/C = usr.get_idcard(hand_first = TRUE)
if(istype(C) || istype(C, /obj/item/pda) || istype(C, /obj/item/modular_computer/tablet))
if(check_access(C))
scantemp = "[GRAB.fields["name"]] => Record deleted."
records.Remove(GRAB)
playsound(src, 'sound/machines/terminal_prompt_confirm.ogg', 50, 0)
var/obj/item/circuitboard/computer/cloning/board = circuit
board.records = records
return TRUE
scantemp = "Cannot delete: Access Denied."
playsound(src, 'sound/machines/terminal_prompt_deny.ogg', 50, 0)
/obj/machinery/computer/cloning/proc/Load(mob/user)
if(!diskette || !istype(diskette.fields) || !diskette.fields["name"] || !diskette.fields)
scantemp = "Failed loading: Load error."
playsound(src, 'sound/machines/terminal_prompt_deny.ogg', 50, 0)
return
for(var/datum/data/record/R in records)
if(R.fields["key"] == diskette.fields["key"])
scantemp = "Failed loading: Data already exists!"
return FALSE
var/datum/data/record/R = new(src)
for(var/key in diskette.fields)
R.fields[key] = diskette.fields[key]
records += R
scantemp = "Loaded into internal storage successfully."
var/obj/item/circuitboard/computer/cloning/board = circuit
board.records = records
playsound(src, 'sound/machines/terminal_prompt_confirm.ogg', 50, 0)
/obj/machinery/computer/cloning/proc/Clone(mob/user, target)
var/datum/data/record/C = find_record("id", target, records)
//Look for that player! They better be dead!
if(C)
var/obj/machinery/clonepod/pod = GetAvailablePod()
//Can't clone without someone to clone. Or a pod. Or if the pod is busy. Or full of gibs.
if(!LAZYLEN(pods))
temp = "Error: No Clonepods detected."
playsound(src, 'sound/machines/terminal_prompt_deny.ogg', 50, 0)
else if(!pod)
temp = "Error: No Clonepods available."
playsound(src, 'sound/machines/terminal_prompt_deny.ogg', 50, 0)
else if(!CONFIG_GET(flag/revival_cloning))
temp = "Error: Unable to initiate cloning cycle."
playsound(src, 'sound/machines/terminal_prompt_deny.ogg', 50, 0)
else if(pod.occupant)
temp = "Warning: Cloning cycle already in progress."
playsound(src, 'sound/machines/terminal_prompt_deny.ogg', 50, 0)
else if(pod.growclone(C.fields["ckey"], C.fields["name"], C.fields["UI"], C.fields["SE"], C.fields["mind"], C.fields["blood_type"], C.fields["mrace"], C.fields["features"], C.fields["factions"], C.fields["quirks"], C.fields["bank_account"], C.fields["traumas"]))
temp = "Notice: [C.fields["name"]] => Cloning cycle in progress..."
playsound(src, 'sound/machines/terminal_prompt_confirm.ogg', 50, 0)
records.Remove(C)
else
temp = "Error: [C.fields["name"]] => Initialisation failure."
playsound(src, 'sound/machines/terminal_prompt_deny.ogg', 50, 0)
else
temp = "Failed to clone: Data corrupted."
playsound(src, 'sound/machines/terminal_prompt_deny.ogg', 50, 0)
. = TRUE
/obj/machinery/computer/cloning/proc/Toggle_lock(mob/user)
if(!scanner.is_operational())
return
if(!scanner.locked && !scanner.occupant) //I figured out that if you're fast enough, you can lock an open pod
return
scanner.locked = !scanner.locked
playsound(src, scanner.locked ? 'sound/machines/terminal_prompt_deny.ogg' : 'sound/machines/terminal_prompt_confirm.ogg', 50, 0)
. = TRUE
/obj/machinery/computer/cloning/proc/Scan(mob/user)
if(!scanner.is_operational() || !scanner.occupant)
return
scantemp = "[scantemp_name] => Scanning..."
loading = TRUE
playsound(src, 'sound/machines/terminal_prompt.ogg', 50, 0)
say("Initiating scan...")
var/prev_locked = scanner.locked
scanner.locked = TRUE
addtimer(CALLBACK(src, .proc/finish_scan, scanner.occupant, prev_locked), 2 SECONDS)
. = TRUE
/obj/machinery/computer/cloning/proc/Toggle_autoprocess(mob/user)
autoprocess = !autoprocess
if(autoprocess)
START_PROCESSING(SSmachines, src)
playsound(src, 'sound/machines/terminal_prompt_confirm.ogg', 50, 0)
else
STOP_PROCESSING(SSmachines, src)
playsound(src, 'sound/machines/terminal_prompt_deny.ogg', 50, 0)
. = TRUE
/obj/machinery/computer/cloning/ui_data(mob/user)
var/list/data = list()
data["useRecords"] = use_records
var/list/records_to_send = list()
if(use_records)
if(scanner && HasEfficientPod() && scanner.scan_level >= AUTOCLONING_MINIMAL_LEVEL)
if(!autoprocess)
dat += "<a href='byond://?src=[REF(src)];task=autoprocess'>Autoclone</a>"
else
dat += "<a href='byond://?src=[REF(src)];task=stopautoprocess'>Stop autoclone</a>"
else
dat += "<span class='linkOff'>Autoclone</span>"
dat += "<h3>Cloning Pod Status</h3>"
dat += "<div class='statusDisplay'>[temp]&nbsp;</div>"
switch(src.menu)
if(1)
// Modules
if (isnull(src.scanner) || !LAZYLEN(pods))
dat += "<h3>Modules</h3>"
//dat += "<a href='byond://?src=[REF(src)];relmodules=1'>Reload Modules</a>"
if (isnull(src.scanner))
dat += "<font class='bad'>ERROR: No Scanner detected!</font><br>"
if (!LAZYLEN(pods))
dat += "<font class='bad'>ERROR: No Pod detected</font><br>"
// Scanner
if (!isnull(src.scanner))
var/mob/living/scanner_occupant = get_mob_or_brainmob(scanner.occupant)
dat += "<h3>Scanner Functions</h3>"
dat += "<div class='statusDisplay'>"
if(!scanner_occupant)
dat += "Scanner Unoccupied"
else if(loading)
dat += "[scanner_occupant] => Scanning..."
else
if(use_records)
if(scanner_occupant.ckey != scantemp_ckey || scanner_occupant.name != scantemp_name)
scantemp = "Ready to Scan"
scantemp_ckey = scanner_occupant.ckey
scantemp_name = scanner_occupant.name
else
scantemp = "Ready to Clone"
dat += "[scanner_occupant] => [scantemp]"
dat += "</div>"
if(scanner_occupant)
dat += "<a href='byond://?src=[REF(src)];scan=1'>[use_records ? "Start Scan" : "Clone"]</a>"
dat += "<br><a href='byond://?src=[REF(src)];lock=1'>[scanner.locked ? "Unlock Scanner" : "Lock Scanner"]</a>"
else
dat += "<span class='linkOff'>[use_records ? "Start Scan" : "Clone"]</span>"
if(use_records)
// Database
dat += "<h3>Database Functions</h3>"
if (src.records.len && src.records.len > 0)
dat += "<a href='byond://?src=[REF(src)];menu=2'>View Records ([src.records.len])</a><br>"
else
dat += "<span class='linkOff'>View Records (0)</span><br>"
if (src.diskette)
dat += "<a href='byond://?src=[REF(src)];disk=eject'>Eject Disk</a><br>"
if(2)
dat += "<h3>Current records</h3>"
dat += "<a href='byond://?src=[REF(src)];menu=1'><< Back</a><br><br>"
data["hasAutoprocess"] = TRUE
if(length(records))
for(var/datum/data/record/R in records)
dat += "<h4>[R.fields["name"]]</h4>Scan ID [R.fields["id"]] <a href='byond://?src=[REF(src)];view_rec=[R.fields["id"]]'>View Record</a>"
if(3)
dat += "<h3>Selected Record</h3>"
dat += "<a href='byond://?src=[REF(src)];menu=2'><< Back</a><br>"
if (!src.active_record)
dat += "<font class='bad'>Record not found.</font>"
else
dat += "<h4>[src.active_record.fields["name"]]</h4>"
dat += "Scan ID [src.active_record.fields["id"]] <a href='byond://?src=[REF(src)];clone=[active_record.fields["id"]]'>Clone</a><br>"
var/obj/item/implant/health/H = locate(active_record.fields["imp"])
if ((H) && (istype(H)))
dat += "<b>Health Implant Data:</b><br />[H.sensehealth()]<br><br />"
var/list/record_entry = list()
record_entry["name"] = "[R.fields["name"]]"
record_entry["id"] = "[R.fields["id"]]"
var/obj/item/implant/health/H = locate(R.fields["imp"])
if(H && istype(H))
record_entry["damages"] = H.sensehealth(TRUE)
else
dat += "<font class='bad'>Unable to locate Health Implant.</font><br /><br />"
record_entry["damages"] = FALSE
record_entry["UI"] = "[R.fields["UI"]]"
record_entry["UE"] = "[R.fields["UE"]]"
record_entry["blood_type"] = "[R.fields["blood_type"]]"
records_to_send += list(record_entry)
data["records"] = records_to_send
else
data["records"] = list()
if(diskette && diskette.fields)
var/list/disk_data = list()
disk_data["name"] = "[diskette.fields["name"]]"
disk_data["id"] = "[diskette.fields["id"]]"
disk_data["UI"] = "[diskette.fields["UI"]]"
disk_data["UE"] = "[diskette.fields["UE"]]"
disk_data["blood_type"] = "[diskette.fields["blood_type"]]"
data["diskData"] = disk_data
else
data["diskData"] = list()
else
data["hasAutoprocess"] = FALSE
data["autoprocess"] = autoprocess
var/list/lack_machine = list()
if(isnull(src.scanner))
lack_machine += "ERROR: No Scanner Detected!"
if(!LAZYLEN(pods))
lack_machine += "ERROR: No Pod Detected!"
data["lacksMachine"] = lack_machine
data["temp"] = temp
var/build_temp = null
var/mob/living/scanner_occupant = get_mob_or_brainmob(scanner?.occupant)
if(scanner_occupant?.ckey != scantemp_ckey || scanner_occupant?.name != scantemp_name)
if(use_records)
build_temp = "Ready to Scan"
scantemp_ckey = scanner_occupant?.ckey
scantemp_name = scanner_occupant?.name
else
build_temp = "Ready to Clone"
scantemp = "[scanner_occupant] => [build_temp]"
data["scanTemp"] = scantemp
data["scannerLocked"] = scanner?.locked
data["hasOccupant"] = scanner?.occupant
data["recordsLength"] = "View Records ([length(records)])"
dat += "<b>Unique Identifier:</b><br /><span class='highlight'>[src.active_record.fields["UI"]]</span><br>"
dat += "<b>Structural Enzymes:</b><br /><span class='highlight'>[src.active_record.fields["SE"]]</span><br>"
return data
if(diskette && diskette.fields)
dat += "<div class='block'>"
dat += "<h4>Inserted Disk</h4>"
dat += "<b>Contents:</b> "
var/list/L = list()
if(diskette.fields["UI"])
L += "Unique Identifier"
if(diskette.fields["UE"] && diskette.fields["name"] && diskette.fields["blood_type"])
L += "Unique Enzymes"
if(diskette.fields["SE"])
L += "Structural Enzymes"
dat += english_list(L, "Empty", " + ", " + ")
dat += "<br /><a href='byond://?src=[REF(src)];disk=load'>Load from Disk</a>"
dat += "<br /><a href='byond://?src=[REF(src)];disk=save'>Save to Disk</a>"
dat += "</div>"
dat += "<font size=1><a href='byond://?src=[REF(src)];del_rec=1'>Delete Record</a></font>"
if(4)
if (!src.active_record)
src.menu = 2
dat = "[src.temp]<br>"
dat += "<h3>Confirm Record Deletion</h3>"
dat += "<b><a href='byond://?src=[REF(src)];del_rec=1'>Scan card to confirm.</a></b><br>"
dat += "<b><a href='byond://?src=[REF(src)];menu=3'>Cancel</a></b>"
var/datum/browser/popup = new(user, "cloning", "Cloning System Control")
popup.set_content(dat)
popup.open()
/obj/machinery/computer/cloning/Topic(href, href_list)
/obj/machinery/computer/cloning/ui_act(action, params)
if(..())
return
switch(action)
if("toggle_autoprocess")
Toggle_autoprocess(usr)
if("scan")
Scan(usr)
if("toggle_lock")
Toggle_lock(usr)
if("clone")
Clone(usr, params["target"])
if("delrecord")
DeleteRecord(usr, params["target"])
if("save")
Save(usr, params["target"])
if("load")
Load(usr)
if("eject")
EjectDisk(usr)
if(loading)
/obj/machinery/computer/cloning/ui_interact(mob/user, datum/tgui/ui)
if(..())
return
if(href_list["task"])
switch(href_list["task"])
if("autoprocess")
if(scanner && HasEfficientPod() && scanner.scan_level >= AUTOCLONING_MINIMAL_LEVEL)
autoprocess = TRUE
START_PROCESSING(SSmachines, src)
playsound(src, 'sound/machines/terminal_prompt_confirm.ogg', 50, 0)
if("stopautoprocess")
autoprocess = FALSE
STOP_PROCESSING(SSmachines, src)
playsound(src, 'sound/machines/terminal_prompt_deny.ogg', 50, 0)
src.updateUsrDialog()
. = TRUE
else if ((href_list["scan"]) && !isnull(scanner) && scanner.is_operational())
scantemp = ""
loading = TRUE
playsound(src, 'sound/machines/terminal_prompt.ogg', 50, 0)
say("Initiating scan...")
var/prev_locked = scanner.locked
scanner.locked = TRUE
src.updateUsrDialog()
addtimer(CALLBACK(src, .proc/finish_scan, scanner.occupant, prev_locked), 2 SECONDS)
. = TRUE
//No locking an open scanner.
else if ((href_list["lock"]) && !isnull(scanner) && scanner.is_operational())
if ((!scanner.locked) && (scanner.occupant))
scanner.locked = TRUE
playsound(src, 'sound/machines/terminal_prompt_deny.ogg', 50, 0)
else
scanner.locked = FALSE
playsound(src, 'sound/machines/terminal_prompt_confirm.ogg', 50, 0)
src.updateUsrDialog()
. = TRUE
else if (href_list["refresh"])
src.updateUsrDialog()
playsound(src, "terminal_type", 25, 0)
. = TRUE
if(. || !use_records)
return
if(href_list["view_rec"])
playsound(src, "terminal_type", 25, 0)
src.active_record = find_record("id", href_list["view_rec"], records)
if(active_record)
if(!active_record.fields["ckey"])
records -= active_record
active_record = null
src.temp = "<font class='bad'>Record Corrupt</font>"
else
src.menu = 3
else
src.temp = "Record missing."
src.updateUsrDialog()
. = TRUE
else if (href_list["del_rec"])
if ((!src.active_record) || (src.menu < 3))
return
if (src.menu == 3) //If we are viewing a record, confirm deletion
src.temp = "Delete record?"
src.menu = 4
src.updateUsrDialog()
playsound(src, 'sound/machines/terminal_prompt.ogg', 50, 0)
else if (src.menu == 4)
var/obj/item/card/id/C = usr.get_active_held_item()
if (istype(C)||istype(C, /obj/item/pda))
if(src.check_access(C))
src.temp = "[src.active_record.fields["name"]] => Record deleted."
src.records.Remove(active_record)
active_record = null
src.updateUsrDialog()
playsound(src, 'sound/machines/terminal_prompt_confirm.ogg', 50, 0)
src.menu = 2
var/obj/item/circuitboard/computer/cloning/board = circuit
board.records = records
else
src.temp = "<font class='bad'>Access Denied.</font>"
src.updateUsrDialog()
playsound(src, 'sound/machines/terminal_prompt_deny.ogg', 50, 0)
. = TRUE
else if (href_list["disk"] && use_records) //Load or eject.
switch(href_list["disk"])
if("load")
if (!diskette || !istype(diskette.fields) || !diskette.fields["name"] || !diskette.fields)
src.temp = "<font class='bad'>Load error.</font>"
src.updateUsrDialog()
playsound(src, 'sound/machines/terminal_prompt_deny.ogg', 50, 0)
return
if (!src.active_record)
src.temp = "<font class='bad'>Record error.</font>"
src.menu = 1
src.updateUsrDialog()
playsound(src, 'sound/machines/terminal_prompt_deny.ogg', 50, 0)
return
for(var/key in diskette.fields)
src.active_record.fields[key] = diskette.fields[key]
src.temp = "Load successful."
src.updateUsrDialog()
var/obj/item/circuitboard/computer/cloning/board = circuit
board.records = records
playsound(src, 'sound/machines/terminal_prompt_confirm.ogg', 50, 0)
if("eject")
if(src.diskette)
src.diskette.forceMove(drop_location())
src.diskette = null
playsound(src, 'sound/machines/terminal_insert_disc.ogg', 50, 0)
if("save")
if(!diskette || diskette.read_only || !active_record || !active_record.fields)
src.temp = "<font class='bad'>Save error.</font>"
src.updateUsrDialog()
playsound(src, 'sound/machines/terminal_prompt_deny.ogg', 50, 0)
return
diskette.fields = active_record.fields.Copy()
diskette.name = "data disk - '[src.diskette.fields["name"]]'"
src.temp = "Save successful."
src.updateUsrDialog()
playsound(src, 'sound/machines/terminal_prompt_confirm.ogg', 50, 0)
. = TRUE
else if (href_list["clone"])
var/datum/data/record/C = find_record("id", href_list["clone"], records)
//Look for that player! They better be dead!
if(C)
var/obj/machinery/clonepod/pod = GetAvailablePod()
//Can't clone without someone to clone. Or a pod. Or if the pod is busy. Or full of gibs.
if(!LAZYLEN(pods))
temp = "<font class='bad'>No Clonepods detected.</font>"
playsound(src, 'sound/machines/terminal_prompt_deny.ogg', 50, 0)
else if(!pod)
temp = "<font class='bad'>No Clonepods available.</font>"
playsound(src, 'sound/machines/terminal_prompt_deny.ogg', 50, 0)
else if(!CONFIG_GET(flag/revival_cloning))
temp = "<font class='bad'>Unable to initiate cloning cycle.</font>"
playsound(src, 'sound/machines/terminal_prompt_deny.ogg', 50, 0)
else if(pod.occupant)
temp = "<font class='bad'>Cloning cycle already in progress.</font>"
playsound(src, 'sound/machines/terminal_prompt_deny.ogg', 50, 0)
else if(pod.growclone(C.fields["ckey"], C.fields["name"], C.fields["UI"], C.fields["SE"], C.fields["mind"], C.fields["blood_type"], C.fields["mrace"], C.fields["features"], C.fields["factions"], C.fields["quirks"], C.fields["bank_account"], C.fields["traumas"]))
temp = "[C.fields["name"]] => <font class='good'>Cloning cycle in progress...</font>"
playsound(src, 'sound/machines/terminal_prompt_confirm.ogg', 50, 0)
records.Remove(C)
if(active_record == C)
active_record = null
menu = 1
src.updateUsrDialog()
else
temp = "[C.fields["name"]] => <font class='bad'>Initialisation failure.</font>"
src.updateUsrDialog()
playsound(src, 'sound/machines/terminal_prompt_deny.ogg', 50, 0)
else
temp = "<font class='bad'>Data corruption.</font>"
src.updateUsrDialog()
playsound(src, 'sound/machines/terminal_prompt_deny.ogg', 50, 0)
. = TRUE
else if (href_list["menu"] && use_records)
menu = text2num(href_list["menu"])
src.updateUsrDialog()
playsound(src, "terminal_type", 25, 0)
. = TRUE
updatemodules(TRUE)
ui = SStgui.try_update_ui(user, src, ui)
if(!ui)
ui = new(user, src, "CloningConsole", "Cloning System Control")
ui.open()
/obj/machinery/computer/cloning/proc/finish_scan(mob/living/L, prev_locked)
if(!scanner || !L)
@@ -469,7 +390,6 @@
loading = FALSE
scanner.locked = prev_locked
src.updateUsrDialog()
playsound(src, 'sound/machines/terminal_prompt_confirm.ogg', 50, 0)
@@ -568,44 +488,44 @@
var/obj/machinery/clonepod/pod = GetAvailablePod()
//Can't clone without someone to clone. Or a pod. Or if the pod is busy. Or full of gibs.
if(!LAZYLEN(pods))
temp = "<font class='bad'>No Clonepods detected.</font>"
temp = "No Clonepods detected."
playsound(src, 'sound/machines/terminal_prompt_deny.ogg', 50, 0)
else if(!pod)
temp = "<font class='bad'>No Clonepods available.</font>"
temp = "No Clonepods available."
playsound(src, 'sound/machines/terminal_prompt_deny.ogg', 50, 0)
else if(pod.occupant)
temp = "<font class='bad'>Cloning cycle already in progress.</font>"
temp = "Cloning cycle already in progress."
playsound(src, 'sound/machines/terminal_prompt_deny.ogg', 50, 0)
else
pod.growclone(null, mob_occupant.real_name, dna.uni_identity, dna.mutation_index, null, dna.blood_type, clone_species, dna.features, mob_occupant.faction)
temp = "[mob_occupant.real_name] => <font class='good'>Cloning data sent to pod.</font>"
temp = "[mob_occupant.real_name] => Cloning data sent to pod."
playsound(src, 'sound/machines/terminal_prompt_confirm.ogg', 50, 0)
/obj/machinery/computer/cloning/proc/can_scan(datum/dna/dna, mob/living/mob_occupant, experimental = FALSE, datum/bank_account/account)
if(!istype(dna))
scantemp = "<font class='bad'>Unable to locate valid genetic data.</font>"
scantemp = "Unable to locate valid genetic data."
playsound(src, 'sound/machines/terminal_prompt_deny.ogg', 50, 0)
return
if(!experimental)
if(mob_occupant.suiciding || mob_occupant.hellbound)
scantemp = "<font class='bad'>Subject's brain is not responding to scanning stimuli.</font>"
scantemp = "Subject's brain is not responding to scanning stimuli."
playsound(src, 'sound/machines/terminal_prompt_deny.ogg', 50, 0)
return
if((HAS_TRAIT(mob_occupant, TRAIT_NOCLONE)) && (src.scanner.scan_level < 2))
scantemp = "<font class='bad'>Subject no longer contains the fundamental materials required to create a living clone.</font>"
scantemp = "Subject no longer contains the fundamental materials required to create a living clone."
playsound(src, 'sound/machines/terminal_alert.ogg', 50, 0)
return
if (!experimental)
if(!mob_occupant.ckey || !mob_occupant.client)
scantemp = "<font class='bad'>Mental interface failure.</font>"
scantemp = "Mental interface failure."
playsound(src, 'sound/machines/terminal_prompt_deny.ogg', 50, 0)
return
if (find_record("ckey", mob_occupant.ckey, records))
scantemp = "<font class='average'>Subject already in database.</font>"
scantemp = "Subject already in database."
playsound(src, 'sound/machines/terminal_prompt_deny.ogg', 50, 0)
return
if(SSeconomy.full_ancap && !account)
scantemp = "<font class='average'>Subject is either missing an ID card with a bank account on it, or does not have an account to begin with. Please ensure the ID card is on the body before attempting to scan.</font>"
scantemp = "Subject is either missing an ID card with a bank account on it, or does not have an account to begin with. Please ensure the ID card is on the body before attempting to scan."
playsound(src, 'sound/machines/terminal_prompt_deny.ogg', 50, 0)
return
return TRUE
@@ -618,3 +538,4 @@
icon_keyboard = "med_key"
circuit = /obj/item/circuitboard/computer/cloning/prototype
clonepod_type = /obj/machinery/clonepod/experimental
use_records = FALSE //Wait, so you tell me it lacks records but you never set it as false?
+21 -6
View File
@@ -51,6 +51,11 @@
return FALSE
return ACCESS_CAPTAIN in authorize_access
/obj/machinery/computer/communications/proc/authenticated_as_non_silicon_command(mob/user)
if (issilicon(user))
return FALSE
return ACCESS_HEADS in authorize_access //Should always be the case if authorized as it usually needs head access to log in, buut lets be sure.
/// Are we a silicon, OR we're logged in as the captain?
/obj/machinery/computer/communications/proc/authenticated_as_silicon_or_captain(mob/user)
if (issilicon(user))
@@ -97,8 +102,14 @@
if ("answerMessage")
if (!authenticated(usr))
return
var/answer_index = text2num(params["answer"])
var/message_index = text2num(params["message"])
var/answer_index = params["answer"]
var/message_index = params["message"]
// If either of these aren't numbers, then bad voodoo.
if(!isnum(answer_index) || !isnum(message_index))
message_admins("[ADMIN_LOOKUPFLW(usr)] provided an invalid index type when replying to a message on [src] [ADMIN_JMP(src)]. This should not happen. Please check with a maintainer and/or consult tgui logs.")
CRASH("Non-numeric index provided when answering comms console message.")
if (!answer_index || !message_index || answer_index < 1 || message_index < 1)
return
var/datum/comm_message/message = messages[message_index]
@@ -151,7 +162,11 @@
if ("deleteMessage")
if (!authenticated(usr))
return
var/message_index = text2num(params["message"])
var/message_index = params["message"]
if(!isnum(message_index))
message_admins("[ADMIN_LOOKUPFLW(usr)] provided an invalid index type when deleting a message on [src] [ADMIN_JMP(src)]. This should not happen. Please check with a maintainer and/or consult tgui logs.")
CRASH("Non-numeric index provided when deleting comms console message.")
if (!message_index)
return
LAZYREMOVE(messages, LAZYACCESS(messages, message_index))
@@ -160,7 +175,7 @@
return
make_announcement(usr)
if ("messageAssociates")
if (!authenticated_as_non_silicon_captain(usr))
if (!authenticated_as_non_silicon_command(usr))
return
if (!COOLDOWN_FINISHED(src, important_action_cooldown))
return
@@ -361,9 +376,9 @@
data["shuttleCanEvacOrFailReason"] = SSshuttle.canEvac(user, TRUE)
if (authenticated_as_non_silicon_captain(user))
data["canMessageAssociates"] = TRUE
data["canRequestNuke"] = TRUE
if (authenticated_as_non_silicon_command(user))
data["canMessageAssociates"] = TRUE
if (can_send_messages_to_other_sectors(user))
data["canSendToSectors"] = TRUE
+1 -1
View File
@@ -200,6 +200,6 @@
if(is_centcom_level(T.z) || is_away_level(T.z))
return FALSE
var/area/A = get_area(T)
if(!A || A.noteleport)
if(!A || (A.area_flags & NOTELEPORT))
return FALSE
return TRUE
@@ -217,6 +217,8 @@
new_machine.RefreshParts()
new_machine.on_construction()
// TODO: make sleepers not shit out parts PROPERLY THIS TIME.
new_machine.circuit.moveToNullspace()
qdel(src)
return
+4 -1
View File
@@ -409,7 +409,10 @@
visible_message("<span class='notice'>\The [src] hums and hisses as it moves [mob_occupant.real_name] into storage.</span>")
// Ghost and delete the mob.
if(!mob_occupant.get_ghost(1))
var/mob/dead/observer/G = mob_occupant.get_ghost(TRUE)
if(G)
G.voluntary_ghosted = TRUE
else
mob_occupant.ghostize(FALSE, penalize = TRUE, voluntary = TRUE, cryo = TRUE)
QDEL_NULL(occupant)
+235 -195
View File
@@ -1,9 +1,5 @@
#define LIMBGROWER_MAIN_MENU 1
#define LIMBGROWER_CATEGORY_MENU 2
#define LIMBGROWER_CHEMICAL_MENU 3
//use these for the menu system
/// The limbgrower. Makes organd and limbs with synthflesh and chems.
/// See [limbgrower_designs.dm] for everything we can make.
/obj/machinery/limbgrower
name = "limb grower"
desc = "It grows new limbs using Synthflesh."
@@ -15,161 +11,235 @@
active_power_usage = 100
circuit = /obj/item/circuitboard/machine/limbgrower
var/operating = FALSE
var/disabled = FALSE
/// The category of limbs we're browing in our UI.
var/selected_category = "human"
/// If we're currently printing something.
var/busy = FALSE
var/prod_coeff = 1
/// How efficient our machine is. Better parts = less chemicals used and less power used. Range of 1 to 0.25.
var/production_coefficient = 1
/// How long it takes for us to print a limb. Affected by production_coefficient.
var/production_speed = 3 SECONDS
/// The design we're printing currently.
var/datum/design/being_built
/// Our internal techweb for limbgrower designs.
var/datum/techweb/stored_research
var/selected_category
var/screen = 1
/// All the categories of organs we can print.
var/list/categories = list(
"human" = /datum/species/human,
"lizard" = /datum/species/lizard,
"mammal" = /datum/species/mammal,
"insect" = /datum/species/insect,
"fly" = /datum/species/fly,
"plasmaman" = /datum/species/plasmaman,
"xeno" = /datum/species/xeno,
"other" = /datum/species,
)
var/list/stored_species = list()
"human",
"lizard",
"mammal",
"insect",
"fly",
"plasmaman",
"xeno",
"other",
)
var/obj/item/disk/data/dna_disk
/obj/machinery/limbgrower/Initialize()
create_reagents(100, OPENCONTAINER)
stored_research = new /datum/techweb/specialized/autounlocking/limbgrower
for(var/i in categories)
var/species = categories[i]
stored_species[i] = new species()
. = ..()
AddComponent(/datum/component/plumbing/simple_demand)
AddComponent(/datum/component/simple_rotation, ROTATION_WRENCH | ROTATION_CLOCKWISE, null, CALLBACK(src, .proc/can_be_rotated))
/obj/machinery/limbgrower/ui_interact(mob/user)
/obj/machinery/limbgrower/ui_interact(mob/user, datum/tgui/ui)
. = ..()
if(!is_operational())
return
ui = SStgui.try_update_ui(user, src, ui)
if(!ui)
ui = new(user, src, "Limbgrower", src)
ui.open()
var/dat = main_win(user)
/obj/machinery/limbgrower/ui_data(mob/user)
var/list/data = list()
switch(screen)
if(LIMBGROWER_MAIN_MENU)
dat = main_win(user)
if(LIMBGROWER_CATEGORY_MENU)
dat = category_win(user,selected_category)
if(LIMBGROWER_CHEMICAL_MENU)
dat = chemical_win(user)
for(var/datum/reagent/reagent_id in reagents.reagent_list)
var/list/reagent_data = list(
reagent_name = reagent_id.name,
reagent_amount = reagent_id.volume,
reagent_type = reagent_id.type
)
data["reagents"] += list(reagent_data)
var/datum/browser/popup = new(user, "Limb Grower", name, 400, 500)
popup.set_content(dat)
popup.open()
data["total_reagents"] = reagents.total_volume
data["max_reagents"] = reagents.maximum_volume
data["busy"] = busy
var/list/disk_data = list()
disk_data["disk"] = dna_disk //Do i, the machine, have a disk?
disk_data["name"] = dna_disk?.fields["name"] //Name for the human saved if there is one
data["disk"] = disk_data
return data
/obj/machinery/limbgrower/ui_static_data(mob/user)
var/list/data = list()
data["categories"] = list()
var/species_categories = categories.Copy()
for(var/species in species_categories)
species_categories[species] = list()
for(var/design_id in stored_research.researched_designs)
var/datum/design/limb_design = SSresearch.techweb_design_by_id(design_id)
for(var/found_category in species_categories)
if(found_category in limb_design.category)
species_categories[found_category] += limb_design
for(var/category in species_categories)
var/list/category_data = list(
name = category,
designs = list(),
)
for(var/datum/design/found_design in species_categories[category])
var/list/all_reagents = list()
for(var/reagent_typepath in found_design.reagents_list)
var/datum/reagent/reagent_id = find_reagent_object_from_type(reagent_typepath)
var/list/reagent_data = list(
name = reagent_id.name,
amount = (found_design.reagents_list[reagent_typepath] * production_coefficient),
)
all_reagents += list(reagent_data)
category_data["designs"] += list(list(
parent_category = category,
name = found_design.name,
id = found_design.id,
needed_reagents = all_reagents,
))
data["categories"] += list(category_data)
return data
/obj/machinery/limbgrower/on_deconstruction()
for(var/obj/item/reagent_containers/glass/G in component_parts)
reagents.trans_to(G, G.reagents.maximum_volume)
for(var/obj/item/reagent_containers/glass/our_beaker in component_parts)
reagents.trans_to(our_beaker, our_beaker.reagents.maximum_volume)
..()
/obj/machinery/limbgrower/attackby(obj/item/O, mob/user, params)
if(busy)
/obj/machinery/limbgrower/attackby(obj/item/user_item, mob/living/user, params)
if (busy)
to_chat(user, "<span class=\"alert\">\The [src] is busy. Please wait for completion of previous operation.</span>")
return
if(default_deconstruction_screwdriver(user, "limbgrower_panelopen", "limbgrower_idleoff", O))
updateUsrDialog()
if(default_deconstruction_screwdriver(user, "limbgrower_panelopen", "limbgrower_idleoff", user_item))
ui_close(user)
return
if(panel_open && default_deconstruction_crowbar(O))
return
if(user.a_intent == INTENT_HARM) //so we can hit the machine
if(user_item.tool_behaviour == TOOL_WRENCH && panel_open)
return ..()
if(istype(O, /obj/item/disk))
if(panel_open && default_deconstruction_crowbar(user_item))
return
if(istype(user_item, /obj/item/disk))
if(dna_disk)
to_chat(user, "<span class='warning'>\The [src] already has a dna disk, take it out first!</span>")
return
else
O.forceMove(src)
dna_disk = O
to_chat(user, "<span class='notice'>You insert \the [O] into \the [src].</span>")
user_item.forceMove(src)
dna_disk = user_item
to_chat(user, "<span class='notice'>You insert \the [user_item] into \the [src].</span>")
playsound(src, 'sound/machines/terminal_insert_disc.ogg', 50, 0)
return
/obj/machinery/limbgrower/Topic(href, href_list)
if(..())
if(user.a_intent != INTENT_HELP)
return ..()
/obj/machinery/limbgrower/proc/can_be_rotated()
if(panel_open)
return TRUE
return FALSE
/obj/machinery/limbgrower/ui_act(action, list/params)
. = ..()
if(.)
return
if (!busy)
if(href_list["menu"])
screen = text2num(href_list["menu"])
if(href_list["category"])
selected_category = href_list["category"]
if (busy)
to_chat(usr, "<span class='danger'>\The [src] is busy. Please wait for completion of previous operation.</span>")
return
if(href_list["disposeI"]) //Get rid of a reagent incase you add the wrong one by mistake
reagents.del_reagent(text2path(href_list["disposeI"]))
switch(action)
if(href_list["make"])
if("empty_reagent")
reagents.del_reagent(text2path(params["reagent_type"]))
. = TRUE
/////////////////
//href protection
being_built = stored_research.isDesignResearchedID(href_list["make"]) //check if it's a valid design
if("eject_disk")
eject_disk(usr)
if("make_limb")
being_built = stored_research.isDesignResearchedID(params["design_id"])
if(!being_built)
return
CRASH("[src] was passed an invalid design id!")
/// All the reagents we're using to make our organ.
var/list/consumed_reagents_list = being_built.reagents_list.Copy()
/// The amount of power we're going to use, based on how much reagent we use.
var/power = 0
var/synth_cost = being_built.reagents_list[/datum/reagent/medicine/synthflesh]*prod_coeff
var/power = max(2000, synth_cost/5)
for(var/reagent_id in consumed_reagents_list)
consumed_reagents_list[reagent_id] *= production_coefficient
if(!reagents.has_reagent(reagent_id, consumed_reagents_list[reagent_id]))
audible_message("<span class='notice'>\The [src] buzzes.</span>")
playsound(src, 'sound/machines/buzz-sigh.ogg', 50, FALSE)
return
if(reagents.has_reagent(/datum/reagent/medicine/synthflesh, being_built.reagents_list[/datum/reagent/medicine/synthflesh]*prod_coeff))
busy = TRUE
use_power(power)
flick("limbgrower_fill",src)
icon_state = "limbgrower_idleon"
addtimer(CALLBACK(src, .proc/build_item),32*prod_coeff)
power = max(2000, (power + consumed_reagents_list[reagent_id]))
if(href_list["dna_disk"])
var/mob/living/carbon/user = usr
if(istype(user))
if(!dna_disk)
var/obj/item/disk/diskette = user.get_active_held_item()
if(istype(diskette))
diskette.forceMove(src)
dna_disk = diskette
to_chat(user, "<span class='notice'>You insert \the [diskette] into \the [src].</span>")
else
dna_disk.forceMove(src.loc)
user.put_in_active_hand(dna_disk)
to_chat(user, "<span class='notice'>You remove \the [dna_disk] from \the [src].</span>")
dna_disk = null
else
to_chat(user, "<span class='warning'>You are unable to grasp \the [dna_disk] disk from \the [src].</span>")
else
to_chat(usr, "<span class=\"alert\">\The [src] is busy. Please wait for completion of previous operation.</span>")
busy = TRUE
use_power(power)
flick("limbgrower_fill",src)
icon_state = "limbgrower_idleon"
selected_category = params["active_tab"]
addtimer(CALLBACK(src, .proc/build_item, consumed_reagents_list), production_speed * production_coefficient)
. = TRUE
updateUsrDialog()
return
/obj/machinery/limbgrower/proc/build_item()
if(reagents.has_reagent(/datum/reagent/medicine/synthflesh, being_built.reagents_list[/datum/reagent/medicine/synthflesh]*prod_coeff)) //sanity check, if this happens we are in big trouble
reagents.remove_reagent(/datum/reagent/medicine/synthflesh, being_built.reagents_list[/datum/reagent/medicine/synthflesh]*prod_coeff)
var/buildpath = being_built.build_path
if(ispath(buildpath, /obj/item/bodypart)) //This feels like spaghetti code, but i need to initiliaze a limb somehow
build_limb(buildpath)
else if(ispath(buildpath, /obj/item/organ/genital)) //genitals are uhh... customizable
build_genital(buildpath)
else
//Just build whatever it is
new buildpath(loc)
else
src.visible_message("<span class=\"error\"> Something went very wrong and there isnt enough synthflesh anymore!</span>")
busy = FALSE
flick("limbgrower_unfill",src)
icon_state = "limbgrower_idleoff"
updateUsrDialog()
/*
* The process of beginning to build a limb or organ.
* Goes through and sanity checks that we actually have enough reagent to build our item.
* Then, remove those reagents from our reagents datum.
*
* After the reagents are handled, we can proceede with making the limb or organ. (Limbs are handled in a separate proc)
*
* modified_consumed_reagents_list - the list of reagents we will consume on build, modified by the production coefficient.
*/
/obj/machinery/limbgrower/proc/build_item(list/modified_consumed_reagents_list)
for(var/reagent_id in modified_consumed_reagents_list)
if(!reagents.has_reagent(reagent_id, modified_consumed_reagents_list[reagent_id]))
audible_message("<span class='notice'>\The [src] buzzes.</span>")
playsound(src, 'sound/machines/buzz-sigh.ogg', 50, FALSE)
break
/obj/machinery/limbgrower/proc/build_limb(buildpath)
reagents.remove_reagent(reagent_id, modified_consumed_reagents_list[reagent_id])
var/built_typepath = being_built.build_path
// If we have a bodypart, we need to initialize the limb on its own. Otherwise we can build it here.
if(ispath(built_typepath, /obj/item/bodypart))
build_limb(built_typepath)
else if(ispath(built_typepath, /obj/item/organ/genital)) //genitals are uhh... customizable
build_genital(built_typepath)
else
new built_typepath(loc)
busy = FALSE
flick("limbgrower_unfill", src)
icon_state = "limbgrower_idleoff"
/*
* The process of putting together a limb.
* This is called from after we remove the reagents, so this proc is just initializing the limb type.
*
* This proc handles skin / mutant color, greyscaling, names and descriptions, and various other limb creation steps.
*
* built_typepath - the path of the bodypart we're building.
*/
/obj/machinery/limbgrower/proc/build_limb(built_typepath)
//i need to create a body part manually using a set icon (otherwise it doesnt appear)
var/obj/item/bodypart/limb
var/datum/species/selected = stored_species[selected_category]
limb = new buildpath(loc)
var/datum/species/selected = GLOB.species_datums[selected_category]
limb = new built_typepath(loc)
limb.base_bp_icon = selected.icon_limbs || DEFAULT_BODYPART_ICON_ORGANIC
limb.species_id = selected.limbs_id
limb.color_src = (MUTCOLORS in selected.species_traits ? MUTCOLORS : (selected.use_skintones ? SKINTONE : FALSE))
@@ -178,6 +248,7 @@
limb.update_icon_dropped()
limb.name = "\improper synthetic [lowertext(selected.name)] [limb.name]"
limb.desc = "A synthetic [selected_category] limb that will morph on its first use in surgery. This one is for the [parse_zone(limb.body_zone)]."
limb.forcereplace = TRUE
for(var/obj/item/bodypart/BP in limb)
BP.base_bp_icon = selected.icon_limbs || DEFAULT_BODYPART_ICON_ORGANIC
BP.species_id = selected.limbs_id
@@ -188,135 +259,103 @@
BP.name = "\improper synthetic [lowertext(selected.name)] [limb.name]"
BP.desc = "A synthetic [selected_category] limb that will morph on its first use in surgery. This one is for the [parse_zone(limb.body_zone)]."
/obj/machinery/limbgrower/proc/build_genital(buildpath)
/*
* Builds genitals, modifies to be the same
* as the person's cloning data on the data disk
*/
/obj/machinery/limbgrower/proc/build_genital(built_typepath)
//i needed to create a way to customize gene tools using dna
var/list/features = dna_disk?.fields["features"]
if(length(features))
switch(buildpath)
switch(built_typepath)
if(/obj/item/organ/genital/penis)
var/obj/item/organ/genital/penis/penis = new(loc)
if(features["has_cock"])
penis.shape = features["cock_shape"]
penis.length = features["cock_shape"]
penis.diameter_ratio = features["cock_diameter_ratio"]
penis.color = sanitize_hexcolor(features["cock_color"], 6)
penis.update_icon()
penis.color = sanitize_hexcolor(features["cock_color"], 6, TRUE)
penis.update()
if(/obj/item/organ/genital/testicles)
var/obj/item/organ/genital/testicles/balls = new(loc)
if(features["has_balls"])
balls.color = sanitize_hexcolor(features["balls_color"], 6)
balls.color = sanitize_hexcolor(features["balls_color"], 6, TRUE)
balls.shape = features["balls_shape"]
balls.size = features["balls_size"]
balls.fluid_rate = features["balls_cum_rate"]
balls.fluid_mult = features["balls_cum_mult"]
balls.fluid_efficiency = features["balls_efficiency"]
balls.update()
if(/obj/item/organ/genital/vagina)
var/obj/item/organ/genital/vagina/vegana = new(loc)
if(features["has_vagina"])
vegana.color = sanitize_hexcolor(features["vag_color"], 6)
if(features["has_vag"])
vegana.color = sanitize_hexcolor(features["vag_color"], 6, TRUE)
vegana.shape = features["vag_shape"]
vegana.update()
if(/obj/item/organ/genital/breasts)
var/obj/item/organ/genital/breasts/boobs = new(loc)
if(features["has_breasts"])
boobs.color = sanitize_hexcolor(features["breasts_color"], 6)
boobs.color = sanitize_hexcolor(features["breasts_color"], 6, TRUE)
boobs.size = features["breasts_size"]
boobs.shape = features["breasts_shape"]
if(!features["breasts_producing"])
boobs.genital_flags &= ~(GENITAL_FUID_PRODUCTION|CAN_CLIMAX_WITH|CAN_MASTURBATE_WITH)
boobs.update()
else
new buildpath(loc)
new built_typepath(loc)
else
new buildpath(loc)
new built_typepath(loc)
/obj/machinery/limbgrower/RefreshParts()
reagents.maximum_volume = 0
for(var/obj/item/reagent_containers/glass/G in component_parts)
reagents.maximum_volume += G.volume
G.reagents.trans_to(src, G.reagents.total_volume)
var/T=1.2
for(var/obj/item/stock_parts/manipulator/M in component_parts)
T -= M.rating*0.2
prod_coeff = min(1,max(0,T)) // Coeff going 1 -> 0,8 -> 0,6 -> 0,4
for(var/obj/item/reagent_containers/glass/our_beaker in component_parts)
reagents.maximum_volume += our_beaker.volume
our_beaker.reagents.trans_to(src, our_beaker.reagents.total_volume)
production_coefficient = 1.2
for(var/obj/item/stock_parts/manipulator/our_manipulator in component_parts)
production_coefficient -= our_manipulator.rating * 0.2
production_coefficient = clamp(production_coefficient, 0, 1) // coefficient goes from 1 -> 0.8 -> 0.6 -> 0.4
/obj/machinery/limbgrower/examine(mob/user)
. = ..()
if(!panel_open)
. += "<span class='notice'>It looks like as if the panel were open you could rotate it with a <b>wrench</b>.</span>"
else
. += "<span class='notice'>The panel is open.</span>"
if(in_range(user, src) || isobserver(user))
. += "<span class='notice'>The status display reads: Storing up to <b>[reagents.maximum_volume]u</b> of synthflesh.<br>Synthflesh consumption at <b>[prod_coeff*100]%</b>.<span>"
. += "<span class='notice'>The status display reads: Storing up to <b>[reagents.maximum_volume]u</b> of reagents.<br>Reagent consumption rate at <b>[production_coefficient * 100]%</b>.</span>"
/obj/machinery/limbgrower/proc/main_win(mob/user)
var/dat = "<div class='statusDisplay'><h3>[src] Menu:</h3><br>"
dat += "<A href='?src=[REF(src)];dna_disk=1'>[dna_disk ? "Remove" : "Insert"] cloning data disk</A>"
dat += "<hr>"
dat += "<A href='?src=[REF(src)];menu=[LIMBGROWER_CHEMICAL_MENU]'>Chemical Storage</A>"
dat += materials_printout()
dat += "<table style='width:100%' align='center'><tr>"
for(var/C in categories)
dat += "<td><A href='?src=[REF(src)];category=[C];menu=[LIMBGROWER_CATEGORY_MENU]'>[C]</A></td>"
dat += "</tr><tr>"
//one category per line
dat += "</tr></table></div>"
return dat
/obj/machinery/limbgrower/proc/category_win(mob/user,selected_category)
var/dat = "<A href='?src=[REF(src)];menu=[LIMBGROWER_MAIN_MENU]'>Return to main menu</A>"
dat += "<div class='statusDisplay'><h3>Browsing [selected_category]:</h3><br>"
dat += materials_printout()
for(var/v in stored_research.researched_designs)
var/datum/design/D = SSresearch.techweb_design_by_id(v)
if(!(selected_category in D.category))
continue
if(disabled || !can_build(D))
dat += "<span class='linkOff'>[D.name]</span>"
else
dat += "<a href='?src=[REF(src)];make=[D.id];multiplier=1'>[D.name]</a>"
dat += "[get_design_cost(D)]<br>"
dat += "</div>"
return dat
/obj/machinery/limbgrower/proc/chemical_win(mob/user)
var/dat = "<A href='?src=[REF(src)];menu=[LIMBGROWER_MAIN_MENU]'>Return to main menu</A>"
dat += "<div class='statusDisplay'><h3>Browsing Chemical Storage:</h3><br>"
dat += materials_printout()
for(var/datum/reagent/R in reagents.reagent_list)
dat += "[R.name]: [R.volume]"
dat += "<A href='?src=[REF(src)];disposeI=[R]'>Purge</A><BR>"
dat += "</div>"
return dat
/obj/machinery/limbgrower/proc/materials_printout()
var/dat = "<b>Total amount:></b> [reagents.total_volume] / [reagents.maximum_volume] cm<sup>3</sup><br>"
return dat
/obj/machinery/limbgrower/proc/can_build(datum/design/D)
return (reagents.has_reagent(/datum/reagent/medicine/synthflesh, D.reagents_list[/datum/reagent/medicine/synthflesh]*prod_coeff)) //Return whether the machine has enough synthflesh to produce the design
/obj/machinery/limbgrower/proc/get_design_cost(datum/design/D)
var/dat
if(D.reagents_list[/datum/reagent/medicine/synthflesh])
dat += "[D.reagents_list[/datum/reagent/medicine/synthflesh] * prod_coeff] Synthetic flesh "
return dat
/*
* Checks our reagent list to see if a design can be built.
*
* limb_design - the design we're checking for buildability.
*
* returns TRUE if we have enough reagent to build it. Returns FALSE if we do not.
*/
/obj/machinery/limbgrower/proc/can_build(datum/design/limb_design)
for(var/datum/reagent/reagent_id in limb_design.reagents_list)
if(!reagents.has_reagent(reagent_id, limb_design.reagents_list[reagent_id] * production_coefficient))
return FALSE
return TRUE
/// Emagging a limbgrower allows you to build synthetic armblades.
/obj/machinery/limbgrower/emag_act(mob/user)
. = ..()
if(obj_flags & EMAGGED)
return
for(var/id in SSresearch.techweb_designs)
var/datum/design/D = SSresearch.techweb_design_by_id(id)
if((D.build_type & LIMBGROWER) && ("emagged" in D.category))
stored_research.add_design(D)
for(var/design_id in SSresearch.techweb_designs)
var/datum/design/found_design = SSresearch.techweb_design_by_id(design_id)
if((found_design.build_type & LIMBGROWER) && ("emagged" in found_design.category))
stored_research.add_design(found_design)
to_chat(user, "<span class='warning'>A warning flashes onto the screen, stating that safety overrides have been deactivated!</span>")
obj_flags |= EMAGGED
return TRUE
update_static_data(user)
/obj/machinery/limbgrower/AltClick(mob/living/user)
. = ..()
eject_disk(user)
/obj/machinery/limbgrower/proc/eject_disk(mob/user)
if(istype(user) && user.canUseTopic(src, BE_CLOSE, FALSE, NO_TK))
if(busy)
to_chat(user, "<span class=\"alert\">\The [src] is busy. Please wait for completion of previous operation.</span>")
@@ -325,6 +364,7 @@
dna_disk.forceMove(src.loc)
user.put_in_active_hand(dna_disk)
to_chat(user, "<span class='notice'>You remove \the [dna_disk] from \the [src].</span>")
playsound(src, 'sound/machines/terminal_insert_disc.ogg', 50, 0)
dna_disk = null
else
to_chat(user, "<span class='warning'>\The [src] has doesn't have a disk on it!")
+20
View File
@@ -21,6 +21,7 @@ Buildable meters
level = 2
var/piping_layer = PIPING_LAYER_DEFAULT
var/RPD_type
var/disposable = TRUE
/obj/item/pipe/directional
RPD_type = PIPE_UNARY
@@ -236,3 +237,22 @@ Buildable meters
/obj/item/pipe_meter/proc/setAttachLayer(new_layer = PIPING_LAYER_DEFAULT)
piping_layer = new_layer
PIPING_LAYER_DOUBLE_SHIFT(src, piping_layer)
/obj/item/pipe/bluespace
pipe_type = /obj/machinery/atmospherics/pipe/bluespace
var/bluespace_network_name = "default"
icon_state = "bluespace"
disposable = FALSE
/obj/item/pipe/bluespace/attack_self(mob/user)
var/new_name = input(user, "Enter identifier for bluespace pipe network", "bluespace pipe", bluespace_network_name) as text|null
if(!isnull(new_name))
bluespace_network_name = new_name
/obj/item/pipe/bluespace/make_from_existing(obj/machinery/atmospherics/pipe/bluespace/make_from)
bluespace_network_name = make_from.bluespace_network_name
return ..()
/obj/item/pipe/bluespace/build_pipe(obj/machinery/atmospherics/pipe/bluespace/A)
A.bluespace_network_name = bluespace_network_name
return ..()
+1 -1
View File
@@ -140,7 +140,7 @@
if (. & EMP_PROTECT_SELF)
return
if(get_charge())
use_power(cell.charge*severity/100)
use_power((cell.charge/3)*(severity*0.005))
take_damage(severity/3, BURN, "energy", 1)
mecha_log_message("EMP detected", color="red")
+8 -6
View File
@@ -375,12 +375,14 @@ GLOBAL_LIST_INIT(fluid_duct_recipes, list(
. = TRUE
if((mode & DESTROY_MODE) && istype(A, /obj/item/pipe) || istype(A, /obj/structure/disposalconstruct) || istype(A, /obj/structure/c_transit_tube) || istype(A, /obj/structure/c_transit_tube_pod) || istype(A, /obj/item/pipe_meter))
to_chat(user, "<span class='notice'>You start destroying a pipe...</span>")
playsound(get_turf(src), 'sound/machines/click.ogg', 50, 1)
if(do_after(user, destroy_speed, target = A))
activate()
qdel(A)
return
var/obj/item/pipe/P = A
if(!istype(P) || P.disposable)
to_chat(user, "<span class='notice'>You start destroying a pipe...</span>")
playsound(get_turf(src), 'sound/machines/click.ogg', 50, 1)
if(do_after(user, destroy_speed, target = A))
activate()
qdel(A)
return
if((mode & PAINT_MODE))
if(istype(A, /obj/machinery/atmospherics/pipe) && !istype(A, /obj/machinery/atmospherics/pipe/layer_manifold))
+7 -1
View File
@@ -157,7 +157,7 @@
to_chat(user, "<span class='notice'>You need to get closer!</span>")
return
if(use_paint(user) && isturf(F))
F.AddElement(/datum/element/decal, 'icons/turf/decals.dmi', stored_decal_total, turn(stored_dir, -dir2angle(F.dir)), CLEAN_STRONG, color, null, null, alpha)
F.AddElement(/datum/element/decal, 'icons/turf/decals.dmi', stored_decal_total, stored_dir, CLEAN_STRONG, color, null, null, alpha)
/obj/item/airlock_painter/decal/attack_self(mob/user)
if((ink) && (ink.charges >= 1))
@@ -180,6 +180,11 @@
stored_decal_total = "[stored_decal][yellow_fix][stored_color]"
return
/obj/item/airlock_painter/decal/ui_assets(mob/user)
return list(
get_asset_datum(/datum/asset/spritesheet/decals)
)
/obj/item/airlock_painter/decal/ui_interact(mob/user, datum/tgui/ui)
ui = SStgui.try_update_ui(user, src, ui)
if(!ui)
@@ -189,6 +194,7 @@
/obj/item/airlock_painter/decal/ui_data(mob/user)
var/list/data = list()
data["decal_direction"] = stored_dir
data["decal_dir_text"] = dir2text(stored_dir)
data["decal_color"] = stored_color
data["decal_style"] = stored_decal
data["decal_list"] = list()
-15
View File
@@ -75,18 +75,3 @@
desc = "A chromosome that reduces action based mutation cooldowns by by 50%."
icon_state = "energy"
energy_coeff = 0.5
/obj/item/chromosome/reinforcer
name = "reinforcement chromosome"
desc = "A chromosome that renders mutations immune to mutadone."
icon_state = "reinforcer"
weight = 3
/obj/item/chromosome/reinforcer/can_apply(datum/mutation/human/HM)
if(!HM || !(HM.can_chromosome == CHROMOSOME_NONE))
return FALSE
return !HM.mutadone_proof
/obj/item/chromosome/reinforcer/apply(datum/mutation/human/HM)
HM.mutadone_proof = TRUE
..()
+1 -1
View File
@@ -443,7 +443,7 @@
// Check area validity.
// Reject space, player-created areas, and non-station z-levels.
var/area/A = get_base_area(target)
if(!A || (!is_station_level(A.z)) || !A.valid_territory)
if(!A || (!is_station_level(A.z)) || !(A.area_flags & VALID_TERRITORY))
to_chat(user, "<span class='warning'>[A] is unsuitable for tagging.</span>")
return FALSE
@@ -69,8 +69,7 @@ effective or pretty fucking useless.
*/
/obj/item/healthanalyzer/rad_laser
custom_materials = list(/datum/material/iron=400)
var/irradiate = 1
var/irradiate = TRUE
var/intensity = 10 // how much damage the radiation does
var/wavelength = 10 // time it takes for the radiation to kick in, in seconds
var/used = 0 // is it cooling down?
@@ -92,16 +91,16 @@ effective or pretty fucking useless.
addtimer(VARSET_CALLBACK(src, used, FALSE), cooldown)
addtimer(VARSET_CALLBACK(src, icon_state, "health"), cooldown)
to_chat(user, "<span class='warning'>Successfully irradiated [M].</span>")
addtimer(CALLBACK(src, .proc/radiation_aftereffect, M), (wavelength+(intensity*4))*5)
addtimer(CALLBACK(src, .proc/radiation_aftereffect, M, intensity), (wavelength+(intensity*4))*5)
else
to_chat(user, "<span class='warning'>The radioactive microlaser is still recharging.</span>")
/obj/item/healthanalyzer/rad_laser/proc/radiation_aftereffect(mob/living/M)
if(QDELETED(M))
/obj/item/healthanalyzer/rad_laser/proc/radiation_aftereffect(mob/living/M, passed_intensity)
if(QDELETED(M) || !ishuman(M) || HAS_TRAIT(M, TRAIT_RADIMMUNE))
return
if(intensity >= 5)
M.apply_effect(round(intensity/0.075), EFFECT_UNCONSCIOUS)
M.rad_act(intensity*10)
if(passed_intensity >= 5)
M.apply_effect(round(passed_intensity/0.075), EFFECT_UNCONSCIOUS) //to save you some math, this is a round(intensity * (4/3)) second long knockout
M.rad_act(passed_intensity*10)
/obj/item/healthanalyzer/rad_laser/proc/get_cooldown()
return round(max(10, (stealth*30 + intensity*5 - wavelength/4)))
+2 -4
View File
@@ -210,8 +210,7 @@
target.apply_effect(EFFECT_STUTTER, stunforce)
SEND_SIGNAL(target, COMSIG_LIVING_MINOR_SHOCK)
if(user)
target.lastattacker = user.real_name
target.lastattackerckey = user.ckey
target.set_last_attacker(user)
target.visible_message("<span class='danger'>[user] has shocked [target] with [src]!</span>", \
"<span class='userdanger'>[user] has shocked you with [src]!</span>")
log_combat(user, target, "stunned with an electrostaff")
@@ -237,8 +236,7 @@
target.adjustFireLoss(lethal_force) //good against ointment spam
SEND_SIGNAL(target, COMSIG_LIVING_MINOR_SHOCK)
if(user)
target.lastattacker = user.real_name
target.lastattackerckey = user.ckey
target.set_last_attacker(user)
target.visible_message("<span class='danger'>[user] has seared [target] with [src]!</span>", \
"<span class='userdanger'>[user] has seared you with [src]!</span>")
log_combat(user, target, "burned with an electrostaff")
+1 -1
View File
@@ -312,7 +312,7 @@
trap_damage = 0
item_flags = DROPDEL
flags_1 = NONE
breakouttime = 50
breakouttime = 25
/obj/item/restraints/legcuffs/beartrap/energy/New()
..()
@@ -0,0 +1,74 @@
/datum/deathrattle_group
var/name
var/list/datum/weakref/implant_refs = list()
/datum/deathrattle_group/New()
// Give the group a unique name for debugging, and possible future
// use for making custom linked groups.
name = "[rand(100,999)] [pick(GLOB.phonetic_alphabet)]"
/datum/deathrattle_group/proc/rattle(obj/item/implant/deathrattle/origin, mob/living/owner)
var/name = owner.mind ? owner.mind.name : owner.real_name
var/area = get_area_name(get_turf(owner))
for(var/r in implant_refs)
var/datum/weakref/R = r
var/obj/item/implant/deathrattle/implant = R.resolve()
if(!implant || implant == origin)
continue
// Not all the implants may be actually implanted in people.
if(!implant.imp_in)
continue
// Deliberately the same message framing as nanite message + ghost deathrattle
var/mob/living/recipient = implant.imp_in
to_chat(recipient, "<i>You hear a strange, robotic voice in your head...</i> \"<span class='robot'><b>[name]</b> has died at <b>[area]</b>.</span>\"")
SEND_SOUND(recipient, pick(
'sound/items/knell1.ogg',
'sound/items/knell2.ogg',
'sound/items/knell3.ogg',
'sound/items/knell4.ogg',
))
/datum/deathrattle_group/proc/register(obj/item/implant/deathrattle/implant)
implant.group = src
implant_refs += WEAKREF(implant)
/obj/item/implant/deathrattle
name = "deathrattle implant"
desc = "Hope no one else dies, prepare for when they do."
activated = FALSE
var/datum/deathrattle_group/group = null
/obj/item/implant/deathrattle/Destroy()
group = null
return ..()
/obj/item/implant/deathrattle/can_be_implanted_in(mob/living/target)
// Can be implanted in anything that's a mob. Syndicate cyborgs, talking fish, humans...
return TRUE
/obj/item/implant/deathrattle/proc/on_predeath(datum/source, gibbed)
SIGNAL_HANDLER
if(group)
group.rattle(origin = src, owner = source)
/obj/item/implant/deathrattle/implant(mob/living/target, mob/user, silent = FALSE, force = FALSE)
. = ..()
if(.)
RegisterSignal(target, COMSIG_LIVING_PREDEATH, .proc/on_predeath)
if(!group)
to_chat(target, "<i>You hear a strange, robotic voice in your head...</i> \"<span class='robot'>Warning: No other linked implants detected.</span>\"")
/obj/item/implantcase/deathrattle
name = "implant case - 'Deathrattle'"
desc = "A glass case containing a deathrattle implant."
imp_type = /obj/item/implant/deathrattle
@@ -139,14 +139,25 @@
name = "health implant"
activated = 0
var/healthstring = ""
var/list/raw_data = list()
/obj/item/implant/health/proc/sensehealth()
/obj/item/implant/health/proc/sensehealth(get_list = FALSE)
if (!imp_in)
return "ERROR"
else
if(isliving(imp_in))
var/mob/living/L = imp_in
healthstring = "<small>Oxygen Deprivation Damage => [round(L.getOxyLoss())]<br />Fire Damage => [round(L.getFireLoss())]<br />Toxin Damage => [round(L.getToxLoss())]<br />Brute Force Damage => [round(L.getBruteLoss())]</small>"
if (!healthstring)
raw_data = list() //Reset list
raw_data["oxy"] = list("[round(L.getOxyLoss())]") //Suffocation
raw_data["burn"] = list("[round(L.getFireLoss())]") //Burn
raw_data["tox"] = list("[round(L.getToxLoss())]") //Tox
raw_data["brute"] = list("[round(L.getBruteLoss())]") //Brute
if(!healthstring) //I have no idea who made it go this order but okay.
healthstring = "ERROR"
return healthstring
if(!length(raw_data))
raw_data = list("ERROR")
if(!get_list)
return healthstring
else
return raw_data
+12
View File
@@ -271,11 +271,14 @@
var/force_on // Damage when on - not stunning
var/force_off // Damage when off - not stunning
var/weight_class_on // What is the new size class when turned on
var/sword_point = TRUE
wound_bonus = 15
/obj/item/melee/classic_baton/Initialize()
. = ..()
if(sword_point)
AddElement(/datum/element/sword_point)
// Description for trying to stun when still on cooldown.
/obj/item/melee/classic_baton/proc/get_wait_description()
@@ -402,6 +405,8 @@
weight_class_on = WEIGHT_CLASS_BULKY
total_mass = TOTAL_MASS_NORMAL_ITEM
bare_wound_bonus = 5
sword_point = FALSE
var/silent = FALSE
/obj/item/melee/classic_baton/telescopic/suicide_act(mob/user)
var/mob/living/carbon/human/H = user
@@ -431,6 +436,9 @@
w_class = weight_class_on
force = force_on
attack_verb = list("smacked", "struck", "cracked", "beaten")
AddElement(/datum/element/sword_point)
if(!silent)
user?.visible_message("<span class='warning'>[user] extends [src] with a flick of their wrist!</span>")
else
to_chat(user, desc["local_off"])
icon_state = off_icon_state
@@ -439,6 +447,9 @@
w_class = WEIGHT_CLASS_SMALL
force = force_off
attack_verb = list("hit", "poked")
RemoveElement(/datum/element/sword_point)
if(!silent)
user?.visible_message("<span class='warning'>[user] collapses [src] back down!</span>")
playsound(src.loc, on_sound, 50, 1)
add_fingerprint(user)
@@ -465,6 +476,7 @@
force_on = 16
force_off = 5
weight_class_on = WEIGHT_CLASS_NORMAL
silent = TRUE
/obj/item/melee/classic_baton/telescopic/contractor_baton/get_wait_description()
return "<span class='danger'>The baton is still charging!</span>"
+2 -2
View File
@@ -135,8 +135,8 @@
/obj/item/organ/cyberimp/arm/toolset,
/obj/item/organ/cyberimp/arm/surgery,
/obj/item/organ/cyberimp/chest/thrusters,
/obj/item/organ/lungs/cybernetic,
/obj/item/organ/liver/cybernetic) //cyberimplants range from a nice bonus to fucking broken bullshit so no subtypesof
/obj/item/organ/lungs/cybernetic/tier3,
/obj/item/organ/liver/cybernetic/tier3) //cyberimplants range from a nice bonus to fucking broken bullshit so no subtypesof
for(var/V in templist)
var/atom/A = V
augment_list[initial(A.name)] = A
+138 -22
View File
@@ -174,6 +174,10 @@
var/atom/movable/AM = object
if(CHECK_BITFIELD(shield_flags, SHIELD_TRANSPARENT) && (AM.pass_flags & PASSGLASS))
return BLOCK_NONE
if(CHECK_BITFIELD(shield_flags, SHIELD_NO_RANGED) && (attack_type & ATTACK_TYPE_PROJECTILE))
return BLOCK_NONE
if(CHECK_BITFIELD(shield_flags, SHIELD_NO_MELEE) && (attack_type & ATTACK_TYPE_MELEE))
return BLOCK_NONE
if(attack_type & ATTACK_TYPE_THROWN)
final_block_chance += 30
if(attack_type & ATTACK_TYPE_TACKLE)
@@ -238,30 +242,75 @@
new /obj/item/shard((get_turf(src)))
/obj/item/shield/riot/on_shield_block(mob/living/owner, atom/object, damage, attack_text, attack_type, armour_penetration, mob/attacker, def_zone, final_block_chance, list/block_return)
var/final_damage = damage
if(attack_type & ATTACK_TYPE_MELEE)
var/obj/hittingthing = object
if(hittingthing.damtype == BURN)
if(CHECK_BITFIELD(shield_flags, SHIELD_ENERGY_WEAK))
final_damage *= 2
else if(CHECK_BITFIELD(shield_flags, SHIELD_ENERGY_STRONG))
final_damage *= 0.5
if(hittingthing.damtype == BRUTE)
if(CHECK_BITFIELD(shield_flags, SHIELD_KINETIC_WEAK))
final_damage *= 2
else if(CHECK_BITFIELD(shield_flags, SHIELD_KINETIC_STRONG))
final_damage *= 0.5
if(hittingthing.damtype == STAMINA || hittingthing.damtype == TOX || hittingthing.damtype == CLONE || hittingthing.damtype == BRAIN || hittingthing.damtype == OXY)
final_damage = 0
if(attack_type & ATTACK_TYPE_PROJECTILE)
var/obj/item/projectile/shootingthing = object
if(is_energy_reflectable_projectile(shootingthing))
if(CHECK_BITFIELD(shield_flags, SHIELD_ENERGY_WEAK))
final_damage *= 2
else if(CHECK_BITFIELD(shield_flags, SHIELD_ENERGY_STRONG))
final_damage *= 0.5
if(!is_energy_reflectable_projectile(object))
if(CHECK_BITFIELD(shield_flags, SHIELD_KINETIC_WEAK))
final_damage *= 2
else if(CHECK_BITFIELD(shield_flags, SHIELD_KINETIC_STRONG))
final_damage *= 0.5
if(shootingthing.damage_type == STAMINA)
if(CHECK_BITFIELD(shield_flags, SHIELD_DISABLER_DISRUPTED))
final_damage *= 3 //disablers melt these kinds of shields. Really meant more for holoshields.
else
final_damage = 0
if(shootingthing.damage_type == TOX || shootingthing.damage_type == CLONE || shootingthing.damage_type == BRAIN || shootingthing.damage_type == OXY)
final_damage = 0
if(can_shatter && (obj_integrity <= damage))
var/turf/T = get_turf(owner)
T.visible_message("<span class='warning'>[attack_text] destroys [src]!</span>")
shatter(owner)
qdel(src)
return FALSE
take_damage(damage)
take_damage(final_damage)
return ..()
/obj/item/shield/riot/laser_proof
name = "laser resistant shield"
desc = "A far more frail shield made of dark glass meant to block lasers but suffers from being being weak to ballistic projectiles."
/obj/item/shield/riot/energy_proof
name = "energy resistant shield"
desc = "An ablative shield designed to absorb and disperse energy attacks. This comes at significant cost to its ability to withstand ballistics and kinetics, breaking apart easily."
armor = list("melee" = 30, "bullet" = -10, "laser" = 80, "energy" = 80, "bomb" = -40, "bio" = 0, "rad" = 0, "fire" = 0, "acid" = 50)
icon_state = "riot_laser"
item_state = "riot_laser"
lefthand_file = 'icons/mob/inhands/equipment/shields_lefthand.dmi'
righthand_file = 'icons/mob/inhands/equipment/shields_righthand.dmi'
shield_flags = SHIELD_FLAGS_DEFAULT
shield_flags = SHIELD_FLAGS_DEFAULT | SHIELD_ENERGY_STRONG | SHIELD_KINETIC_WEAK
max_integrity = 300
/obj/item/shield/riot/bullet_proof
name = "bullet resistant shield"
desc = "A far more frail shield made of resistant plastics and kevlar meant to block ballistics."
/obj/item/shield/riot/kinetic_proof
name = "kinetic resistant shield"
desc = "A polymer and ceramic shield designed to absorb ballistic projectiles and kinetic force. It doesn't do very well into energy attacks, especially from weapons that inflict burns."
armor = list("melee" = 30, "bullet" = 80, "laser" = 0, "energy" = 0, "bomb" = -40, "bio" = 0, "rad" = 0, "fire" = 0, "acid" = 50)
icon_state = "riot_bullet"
item_state = "riot_bullet"
shield_flags = SHIELD_FLAGS_DEFAULT | SHIELD_KINETIC_STRONG | SHIELD_ENERGY_WEAK
max_integrity = 300
/obj/item/shield/riot/roman
@@ -277,8 +326,8 @@
/obj/item/shield/riot/roman/fake
desc = "Bears an inscription on the inside: <i>\"Romanes venio domus\"</i>. It appears to be a bit flimsy."
block_chance = 0
armor = list("melee" = 0, "bullet" = 0, "laser" = 0, "energy" = 0, "bomb" = 0, "bio" = 0, "rad" = 0, "fire" = 0, "acid" = 0)
shield_flags = SHIELD_ENERGY_WEAK | SHIELD_KINETIC_WEAK | SHIELD_NO_RANGED
max_integrity = 40
/obj/item/shield/riot/roman/shatter(mob/living/carbon/human/owner)
@@ -295,14 +344,80 @@
custom_materials = list(/datum/material/wood = MINERAL_MATERIAL_AMOUNT * 10)
resistance_flags = FLAMMABLE
repair_material = /obj/item/stack/sheet/mineral/wood
block_chance = 30
shield_flags = SHIELD_FLAGS_DEFAULT
shield_flags = SHIELD_FLAGS_DEFAULT | SHIELD_ENERGY_WEAK
max_integrity = 150
/obj/item/shield/riot/buckler/shatter(mob/living/carbon/human/owner)
playsound(owner, 'sound/effects/bang.ogg', 50)
new /obj/item/stack/sheet/mineral/wood(get_turf(src))
/obj/item/shield/riot/flash
name = "strobe shield"
desc = "A shield with a built in, high intensity light capable of blinding and disorienting suspects. Takes regular handheld flashes as bulbs."
icon_state = "flashshield"
item_state = "flashshield"
var/obj/item/assembly/flash/handheld/embedded_flash
/obj/item/shield/riot/flash/Initialize()
. = ..()
embedded_flash = new(src)
/obj/item/shield/riot/flash/ComponentInitialize()
. = .. ()
AddElement(/datum/element/update_icon_updates_onmob)
/obj/item/shield/riot/flash/attack(mob/living/M, mob/user)
. = embedded_flash.attack(M, user)
update_icon()
/obj/item/shield/riot/flash/attack_self(mob/living/carbon/user)
. = embedded_flash.attack_self(user)
update_icon()
/obj/item/shield/riot/flash/on_shield_block(mob/living/owner, atom/object, damage, attack_text, attack_type, armour_penetration, mob/attacker, def_zone, final_block_chance, list/block_return)
. = ..()
if (. && !embedded_flash.crit_fail)
embedded_flash.activate()
update_icon()
/obj/item/shield/riot/flash/attackby(obj/item/W, mob/user)
if(istype(W, /obj/item/assembly/flash/handheld))
var/obj/item/assembly/flash/handheld/flash = W
if(flash.crit_fail)
to_chat(user, "<span class='warning'>No sense replacing it with a broken bulb!</span>")
return
else
to_chat(user, "<span class='notice'>You begin to replace the bulb...</span>")
if(do_after(user, 20, target = user))
if(flash.crit_fail || !flash || QDELETED(flash))
return
playsound(src, 'sound/items/deconstruct.ogg', 50, TRUE)
qdel(embedded_flash)
embedded_flash = flash
flash.forceMove(src)
update_icon()
return
..()
/obj/item/shield/riot/flash/emp_act(severity)
. = ..()
embedded_flash.emp_act(severity)
update_icon()
/obj/item/shield/riot/flash/update_icon_state()
if(!embedded_flash || embedded_flash.crit_fail)
icon_state = "riot"
item_state = "riot"
else
icon_state = "flashshield"
item_state = "flashshield"
/obj/item/shield/riot/flash/examine(mob/user)
. = ..()
if (embedded_flash?.crit_fail)
. += "<span class='info'>The mounted bulb has burnt out. You can try replacing it with a new one.</span>"
/obj/item/shield/riot/tele
name = "telescopic shield"
desc = "An advanced riot shield made of lightweight materials that collapses for easy storage."
@@ -348,7 +463,7 @@
/obj/item/shield/makeshift
name = "metal shield"
desc = "A large shield made of wired and welded sheets of metal. The handle is made of cloth and leather making it unwieldy."
desc = "A large shield made of wired and welded sheets of metal. The handle is made of cloth and leather, making it unwieldy."
armor = list("melee" = 25, "bullet" = 25, "laser" = 5, "energy" = 0, "bomb" = 30, "bio" = 0, "rad" = 0, "fire" = 70, "acid" = 80)
lefthand_file = 'icons/mob/inhands/equipment/shields_lefthand.dmi'
righthand_file = 'icons/mob/inhands/equipment/shields_righthand.dmi'
@@ -362,33 +477,34 @@
/obj/item/shield/riot/tower
name = "tower shield"
desc = "A massive shield that can block a lot of attacks, can take a lot of abuse before braking."
desc = "An immense tower shield. Designed to ensure maximum protection to the user, at the expense of mobility."
armor = list("melee" = 95, "bullet" = 95, "laser" = 75, "energy" = 60, "bomb" = 90, "bio" = 90, "rad" = 0, "fire" = 90, "acid" = 10) //Armor for the item, dosnt transfer to user
item_state = "metal"
icon_state = "metal"
force = 16
slowdown = 2
throwforce = 15 //Massive pice of metal
throwforce = 15 //Massive piece of metal
max_integrity = 600
w_class = WEIGHT_CLASS_HUGE
item_flags = SLOWS_WHILE_IN_HAND
item_flags = SLOWS_WHILE_IN_HAND | ITEM_CAN_BLOCK
shield_flags = SHIELD_FLAGS_DEFAULT
/obj/item/shield/riot/tower/swat
name = "swat shield"
desc = "A massive, heavy shield that can block a lot of attacks, can take a lot of abuse before breaking."
max_integrity = 250
/obj/item/shield/riot/implant
name = "telescoping shield implant"
desc = "A compact, arm-mounted telescopic shield. While nigh-indestructible when powered by a host user, it will eventually overload from damage. Recharges while inside its implant."
item_state = "metal"
icon_state = "metal"
name = "hardlight shield implant"
desc = "A hardlight plane of force projected from the implant. While it is capable of withstanding immense amounts of abuse, it will eventually overload from sustained impacts, especially against energy attacks. Recharges while retracted."
item_state = "holoshield"
icon_state = "holoshield"
slowdown = 1
shield_flags = SHIELD_FLAGS_DEFAULT
max_integrity = 100
obj_integrity = 100
can_shatter = FALSE
item_flags = SLOWS_WHILE_IN_HAND | ITEM_CAN_BLOCK
item_flags = ITEM_CAN_BLOCK
shield_flags = SHIELD_FLAGS_DEFAULT | SHIELD_KINETIC_STRONG | SHIELD_DISABLER_DISRUPTED
var/recharge_timerid
var/recharge_delay = 15 SECONDS
@@ -400,7 +516,7 @@
if(obj_integrity == 0)
if(ismob(loc))
var/mob/living/L = loc
playsound(src, 'sound/effects/glassbr3.ogg', 100)
playsound(src, "sparks", 100, TRUE)
L.visible_message("<span class='boldwarning'>[src] overloads from the damage sustained!</span>")
L.dropItemToGround(src) //implant component catch hook will grab it.
@@ -272,7 +272,7 @@ GLOBAL_LIST_INIT(plastitaniumglass_recipes, list(
. = ..()
. += GLOB.plastitaniumglass_recipes
/obj/item/stack/sheet/titaniumglass/on_solar_construction(obj/machinery/power/solar/S)
/obj/item/stack/sheet/plastitaniumglass/on_solar_construction(obj/machinery/power/solar/S)
S.max_integrity *= 2
S.efficiency *= 2
@@ -117,8 +117,8 @@ GLOBAL_LIST_INIT(diamond_recipes, list ( \
new/datum/stack_recipe("Captain Statue", /obj/structure/statue/diamond/captain, 5, one_per_turf = 1, on_floor = 1), \
new/datum/stack_recipe("AI Hologram Statue", /obj/structure/statue/diamond/ai1, 5, one_per_turf = 1, on_floor = 1), \
new/datum/stack_recipe("AI Core Statue", /obj/structure/statue/diamond/ai2, 5, one_per_turf = 1, on_floor = 1), \
// new/datum/stack_recipe("diamond brick", /obj/item/ingot/diamond, 6, time = 100), \ not yet
))
new/datum/stack_recipe("diamond ingot", /obj/item/ingot/diamond, 6, time = 100), \
))
/obj/item/stack/sheet/mineral/diamond/get_main_recipes()
. = ..()
@@ -592,7 +592,7 @@ GLOBAL_LIST_INIT(runed_metal_recipes, list ( \
return
var/turf/T = get_turf(user) //we may have moved. adjust as needed...
var/area/A = get_area(user)
if((!is_station_level(T.z) && !is_mining_level(T.z)) || (A && !A.blob_allowed))
if((!is_station_level(T.z) && !is_mining_level(T.z)) || (A && !(A.flags_1 & CULT_PERMITTED_1)))
to_chat(user, "<span class='warning'>The veil is not weak enough here.</span>")
return FALSE
return ..()
+69
View File
@@ -351,6 +351,75 @@
if(!contents.len)
. += "[icon_state]_empty"
//Derringer "Cigarettes"//
/obj/item/storage/fancy/cigarettes/derringer
name = "\improper Robust packet"
desc = "Smoked by the robust."
icon_state = "robust"
spawn_type = /obj/item/gun/ballistic/derringer/traitor
/obj/item/storage/fancy/cigarettes/derringer/ComponentInitialize()
. = ..()
var/datum/component/storage/STR = GetComponent(/datum/component/storage)
STR.max_items = 6
STR.can_hold = typecacheof(list(/obj/item/clothing/mask/cigarette, /obj/item/lighter, /obj/item/gun/ballistic/derringer, /obj/item/ammo_casing/c38, /obj/item/ammo_casing/a357, /obj/item/ammo_casing/g4570))
/obj/item/storage/fancy/cigarettes/derringer/AltClick(mob/living/carbon/user)
if(!istype(user) || !user.canUseTopic(src, BE_CLOSE, ismonkey(user)))
return
var/obj/item/W = (locate(/obj/item/ammo_casing/a357) in contents) || (locate(/obj/item/clothing/mask/cigarette) in contents) || locate(/obj/item/ammo_casing/g4570) //Easy access smokes and bullets
if(W && contents.len > 0)
SEND_SIGNAL(src, COMSIG_TRY_STORAGE_TAKE, W, user)
user.put_in_hands(W)
contents -= W
to_chat(user, "<span class='notice'>You take \a [W] out of the pack.</span>")
else
to_chat(user, "<span class='notice'>There are no items left in the pack.</span>")
/obj/item/storage/fancy/cigarettes/derringer/PopulateContents()
new spawn_type(src)
new /obj/item/ammo_casing/a357(src)
new /obj/item/ammo_casing/a357(src)
new /obj/item/ammo_casing/a357(src)
new /obj/item/ammo_casing/a357(src)
new /obj/item/clothing/mask/cigarette/syndicate(src)
//For traitors with luck/class
/obj/item/storage/fancy/cigarettes/derringer/gold
name = "\improper Robust Gold packet"
desc = "Smoked by the truly robust."
icon_state = "robustg"
spawn_type = /obj/item/gun/ballistic/derringer/gold
//For operatives, bound in a ka-tet.
/obj/item/storage/fancy/cigarettes/derringer/midworld
name = "\improper Midworld's Lime Bend"
desc = "The wheel of Ka turns, Gunslinger."
icon_state = "slime"
spawn_type = /obj/item/gun/ballistic/derringer/nukeop
/obj/item/storage/fancy/cigarettes/derringer/midworld/PopulateContents()
new spawn_type(src)
new /obj/item/ammo_casing/g4570(src)
new /obj/item/ammo_casing/g4570(src)
new /obj/item/ammo_casing/g4570(src)
new /obj/item/ammo_casing/g4570(src)
new /obj/item/clothing/mask/cigarette/xeno(src)
//For Cargomen, looking for a good deal on arms, with no quarrels as to where they're from.
/obj/item/storage/fancy/cigarettes/derringer/smuggled
name = "\improper Shady Jim's Super Slims packet"
desc = "If you get caught with this, we don't know you, capiche?"
icon_state = "shadyjim"
spawn_type = /obj/item/gun/ballistic/derringer
/obj/item/storage/fancy/cigarettes/derringer/smuggled/PopulateContents()
new spawn_type(src)
new /obj/item/ammo_casing/c38/lethal(src)
new /obj/item/ammo_casing/c38/lethal(src)
new /obj/item/ammo_casing/c38/lethal(src)
new /obj/item/ammo_casing/c38/lethal(src)
new /obj/item/clothing/mask/cigarette/shadyjims (src)
/////////////
//CIGAR BOX//
/////////////
+3 -3
View File
@@ -394,15 +394,15 @@
desc = "You want penis enlargement pills?"
/obj/item/storage/pill_bottle/penis_enlargement/PopulateContents()
for(var/i in 1 to 7)
for(var/i in 1 to 10)
new /obj/item/reagent_containers/pill/penis_enlargement(src)
/obj/item/storage/pill_bottle/breast_enlargement
name = "breast enlargement pills"
desc = "Made by Fermichem - They have a woman with breasts larger than she is on them. The warming states not to take more than 10u at a time."
desc = "Made by Fermichem - The bottle shows a woman with breasts larger than she is on them. The warning states to not take more than 10 units at a time."
/obj/item/storage/pill_bottle/breast_enlargement/PopulateContents()
for(var/i in 1 to 7)
for(var/i in 1 to 10)
new /obj/item/reagent_containers/pill/breast_enlargement(src)
/obj/item/storage/pill_bottle/neurine
+35 -2
View File
@@ -1,7 +1,7 @@
/obj/item/storage/box/syndicate
/obj/item/storage/box/syndicate/PopulateContents()
switch (pickweight(list("bloodyspai" = 3, "stealth" = 2, "bond" = 2, "screwed" = 2, "sabotage" = 3, "guns" = 2, "murder" = 2, "baseball" = 1, "implant" = 1, "hacker" = 3, "darklord" = 1, "sniper" = 1, "metaops" = 1, "ninja" = 1)))
switch (pickweight(list("bloodyspai" = 3, "stealth" = 2, "bond" = 2, "screwed" = 2, "sabotage" = 3, "guns" = 2, "murder" = 2, "baseball" = 1, "implant" = 1, "hacker" = 3, "darklord" = 1, "sniper" = 1, "metaops" = 1, "ninja" = 1, "ancient" = 1)))
if("bloodyspai") // 30 tc now this is more right
new /obj/item/clothing/under/chameleon(src) // 2 tc since it's not the full set
new /obj/item/clothing/mask/chameleon(src) // Goes with above
@@ -62,7 +62,7 @@
new /obj/item/clothing/glasses/phantomthief/syndicate(src)
new /obj/item/reagent_containers/syringe/stimulants(src)
if("baseball") // 42~ tc
if("baseball") // 44~ tc
new /obj/item/melee/baseball_bat/ablative/syndi(src) //Lets say 12 tc, lesser sleeping carp
new /obj/item/clothing/glasses/sunglasses/garb(src) //Lets say 2 tc
new /obj/item/card/emag(src) //6 tc
@@ -72,6 +72,7 @@
new /obj/item/clothing/under/syndicate/baseball(src) //3tc
new /obj/item/clothing/head/soft/baseball(src) //Lets say 4 tc
new /obj/item/reagent_containers/hypospray/medipen/stimulants/baseball(src) //lets say 5tc
new /obj/item/melee/baseball_bat/telescopic(src) // 2 tc
if("implant") // 67+ tc holy shit what the fuck this is a lottery disguised as fun boxes isn't it?
new /obj/item/implanter/freedom(src)
@@ -155,6 +156,20 @@
new /obj/item/card/id/syndicate(src) // 2 tc
new /obj/item/chameleon(src) // 7 tc
if("ancient") //A kit so old, it's probably older than you. //This bundle is filled with the entire unlink contents traitors had access to in 2006, from OpenSS13. Notably the esword was not a choice but existed in code.
new /obj/item/storage/toolbox/emergency/old/ancientbundle(src) //Items fit neatly into a classic toolbox just to remind you what the theme is.
/obj/item/storage/toolbox/emergency/old/ancientbundle //So the subtype works
/obj/item/storage/toolbox/emergency/old/ancientbundle/PopulateContents()
new /obj/item/card/emag(src)
new /obj/item/pen/sleepy(src)
new /obj/item/reagent_containers/pill/cyanide(src)
new /obj/item/chameleon(src) //its not the original cloaking device, but it will do.
new /obj/item/gun/ballistic/revolver(src)
new /obj/item/implanter/freedom(src)
new /obj/item/stack/telecrystal(src) //The failsafe/self destruct isn't an item we can physically include in the kit, but 1 TC is technically enough to buy the equivalent.
/obj/item/storage/box/syndie_kit
name = "box"
desc = "A sleek, sturdy box."
@@ -531,3 +546,21 @@
. = ..()
new /obj/item/cardpack/syndicate(src)
new /obj/item/cardpack/syndicate(src)
/obj/item/storage/box/syndie_kit/imp_deathrattle
name = "deathrattle implant box"
desc = "Contains eight linked deathrattle implants."
/obj/item/storage/box/syndie_kit/imp_deathrattle/PopulateContents()
new /obj/item/implanter(src)
var/datum/deathrattle_group/group = new
var/implants = list()
for(var/j in 1 to 8)
var/obj/item/implantcase/deathrattle/case = new (src)
implants += case.imp
for(var/i in implants)
group.register(i)
desc += " The implants are registered to the \"[group.name]\" group."
+2 -1
View File
@@ -46,7 +46,8 @@
/obj/item/instrument/harmonica,
/obj/item/mining_voucher,
/obj/item/suit_voucher,
/obj/item/reagent_containers/pill))
/obj/item/reagent_containers/pill,
/obj/item/gun/ballistic/derringer))
/obj/item/storage/wallet/Exited(atom/movable/AM)
. = ..()
+57 -30
View File
@@ -16,17 +16,21 @@
armor = list("melee" = 0, "bullet" = 0, "laser" = 0, "energy" = 0, "bomb" = 50, "bio" = 0, "rad" = 0, "fire" = 80, "acid" = 80)
attack_speed = CLICK_CD_MELEE
var/stamforce = 35
var/stamina_loss_amount = 35
var/turned_on = FALSE
var/knockdown = TRUE
var/obj/item/stock_parts/cell/cell
var/hitcost = 750
var/throw_hit_chance = 35
var/preload_cell_type //if not empty the baton starts with this type of cell
var/cooldown_duration = 5 SECONDS //How long our baton rightclick goes on cooldown for after applying a knockdown
var/status_duration = 5 SECONDS //how long our status effects last for otherwise
COOLDOWN_DECLARE(shove_cooldown)
/obj/item/melee/baton/examine(mob/user)
. = ..()
. += "<span class='notice'>Right click attack while in combat mode to disarm instead of stun.</span>"
. += "<span class='notice'>Right click attack while in combat mode to knockdown, but only once per [cooldown_duration / 10] seconds.</span>"
. += "<span class='notice'>This knockdown will also put them off balance for [status_duration / 20] seconds, allowing you to shove a weapon out of their hand with a right click in Disarm intent.</span>"
/obj/item/melee/baton/get_cell()
. = cell
@@ -53,8 +57,8 @@
/obj/item/melee/baton/throw_impact(atom/hit_atom, datum/thrownthing/throwingdatum)
..()
//Only mob/living types have stun handling
if(turned_on && prob(throw_hit_chance) && iscarbon(hit_atom))
baton_stun(hit_atom)
if(turned_on && prob(throw_hit_chance) && iscarbon(hit_atom) && thrownby)
baton_stun(hit_atom, thrownby, shoving = TRUE)
/obj/item/melee/baton/loaded //this one starts with a cell pre-installed.
preload_cell_type = /obj/item/stock_parts/cell/high/plus
@@ -74,6 +78,16 @@
//we're below minimum, turn off
switch_status(FALSE)
///Check for our cell to determine how much penetration our weapon does.
/obj/item/melee/baton/proc/get_cell_zap_pen()
var/obj/item/stock_parts/cell/copper_top = get_cell()
if(copper_top)
var/chargepower = copper_top.maxcharge
var/zap_penetration = (chargepower/1000) //This is our effective penetration. Every 1000 max charge, we get 1 pen power. A high capacity cell is equal to 10 armor pen, as an example.
return zap_penetration
else
return 0
/obj/item/melee/baton/proc/switch_status(new_status = FALSE, silent = FALSE)
if(turned_on != new_status)
turned_on = new_status
@@ -101,6 +115,7 @@
var/obj/item/stock_parts/cell/copper_top = get_cell()
if(copper_top)
. += "<span class='notice'>\The [src] is [round(copper_top.percent())]% charged.</span>"
. += "<span class='notice'>\The [src] currently can penetrate [round(copper_top.maxcharge/1000)]% of enemy armor thanks to it's loaded cell.</span>"
else
. += "<span class='warning'>\The [src] does not have a power source installed.</span>"
@@ -150,10 +165,10 @@
/obj/item/melee/baton/alt_pre_attack(atom/A, mob/living/user, params)
if(!user.CheckActionCooldown(CLICK_CD_MELEE))
return
. = common_baton_melee(A, user, TRUE) //return true (attackchain interrupt) if this also returns true. no harm-disarming.
. = common_baton_melee(A, user, TRUE) //return true (attackchain interrupt) if this also returns true. no harm-shoving.
//return TRUE to interrupt attack chain.
/obj/item/melee/baton/proc/common_baton_melee(mob/M, mob/living/user, disarming = FALSE)
/obj/item/melee/baton/proc/common_baton_melee(mob/M, mob/living/user, shoving = FALSE)
if(iscyborg(M) || !isliving(M)) //can't baton cyborgs
return FALSE
if(turned_on && HAS_TRAIT(user, TRAIT_CLUMSY) && prob(50))
@@ -167,21 +182,26 @@
if(check_martial_counter(L, user))
return TRUE
if(turned_on)
if(baton_stun(M, user, disarming))
if(baton_stun(M, user, shoving))
user.do_attack_animation(M)
else if(user.a_intent != INTENT_HARM) //they'll try to bash in the last proc.
M.visible_message("<span class='warning'>[user] has prodded [M] with [src]. Luckily it was off.</span>", \
"<span class='warning'>[user] has prodded you with [src]. Luckily it was off</span>")
return disarming || (user.a_intent != INTENT_HARM)
return shoving || (user.a_intent != INTENT_HARM)
/obj/item/melee/baton/proc/baton_stun(mob/living/L, mob/living/user, disarming = FALSE)
/obj/item/melee/baton/proc/baton_stun(mob/living/L, mob/living/user, shoving = FALSE)
var/list/return_list = list()
if(L.mob_run_block(src, 0, "[user]'s [name]", ATTACK_TYPE_MELEE, 0, user, null, return_list) & BLOCK_SUCCESS) //No message; check_shields() handles that
playsound(L, 'sound/weapons/genhit.ogg', 50, 1)
return FALSE
var/stunpwr = stamforce
stunpwr = block_calculate_resultant_damage(stunpwr, return_list)
var/final_stamina_loss_amount = stamina_loss_amount //Our stunning power for the baton
var/shoved = FALSE //Did we succeed on knocking our target over?
var/zap_penetration = get_cell_zap_pen() //Find out what kind of cell we have, and calculating the resultant armor pen we get from it
var/zap_block = L.run_armor_check(BODY_ZONE_CHEST, "melee", null, null, zap_penetration) //armor check, including calculation for armor penetration, for our attack
final_stamina_loss_amount = block_calculate_resultant_damage(final_stamina_loss_amount, return_list)
var/obj/item/stock_parts/cell/our_cell = get_cell()
if(!our_cell)
switch_status(FALSE)
return FALSE
@@ -194,26 +214,31 @@
L.visible_message("<span class='warning'>[user] has prodded [L] with [src]. Luckily it was out of charge.</span>", \
"<span class='warning'>[user] has prodded you with [src]. Luckily it was out of charge.</span>")
return FALSE
stunpwr *= round(stuncharge/hitcost, 0.1)
final_stamina_loss_amount *= round(stuncharge/hitcost, 0.1)
if(user && !user.UseStaminaBuffer(getweight(user, STAM_COST_BATON_MOB_MULT), warn = TRUE))
return FALSE
if(!disarming)
if(knockdown)
L.DefaultCombatKnockdown(50, override_stamdmg = 0) //knockdown
L.adjustStaminaLoss(stunpwr)
else
L.drop_all_held_items() //no knockdown/stamina damage, instead disarm.
if(shoving && COOLDOWN_FINISHED(src, shove_cooldown) && !HAS_TRAIT(L, TRAIT_IWASBATONED)) //Rightclicking applies a knockdown, but only once every couple of seconds, based on the cooldown_duration var. If they were recently knocked down, they can't be knocked down again by a baton.
L.DefaultCombatKnockdown(50, override_stamdmg = 0)
L.apply_status_effect(STATUS_EFFECT_TASED_WEAK, status_duration) //Even if they shove themselves up, they're still slowed.
L.apply_status_effect(STATUS_EFFECT_OFF_BALANCE, status_duration) //They're very likely to drop items if shoved briefly after a knockdown.
shoved = TRUE
COOLDOWN_START(src, shove_cooldown, cooldown_duration)
ADD_TRAIT(L, TRAIT_IWASBATONED, STATUS_EFFECT_TRAIT) //Prevents swapping to a new baton to avoid the cooldown by just acquiring more batons
addtimer(TRAIT_CALLBACK_REMOVE(L, TRAIT_IWASBATONED, STATUS_EFFECT_TRAIT), cooldown_duration)
playsound(loc, 'sound/weapons/zapbang.ogg', 50, 1, -1)
else //If we cannot/don't knock down the target, we apply a stagger, which keeps them from just running off
L.apply_status_effect(STATUS_EFFECT_STAGGERED, status_duration)
L.apply_effect(EFFECT_STUTTER, stamforce)
L.apply_damage (final_stamina_loss_amount, STAMINA, BODY_ZONE_CHEST, zap_block)
L.apply_effect(EFFECT_STUTTER, stamina_loss_amount)
SEND_SIGNAL(L, COMSIG_LIVING_MINOR_SHOCK)
if(user)
L.lastattacker = user.real_name
L.lastattackerckey = user.ckey
L.visible_message("<span class='danger'>[user] has [disarming? "disarmed" : "stunned"] [L] with [src]!</span>", \
"<span class='userdanger'>[user] has [disarming? "disarmed" : "stunned"] you with [src]!</span>")
log_combat(user, L, disarming? "disarmed" : "stunned")
L.set_last_attacker(user)
L.visible_message("<span class='danger'>[user] has [shoved ? "brutally stunned" : "stunned"] [L] with [src]!</span>", \
"<span class='userdanger'>[user] has [shoved ? "brutally stunnned" : "stunned"] you with [src]!</span>")
log_combat(user, L, shoved ? "stunned and attempted knockdown" : "stunned")
playsound(loc, 'sound/weapons/egloves.ogg', 50, 1, -1)
@@ -228,7 +253,7 @@
user.visible_message("<span class='danger'>[user] accidentally hits [user.p_them()]self with [src]!</span>", \
"<span class='userdanger'>You accidentally hit yourself with [src]!</span>")
SEND_SIGNAL(user, COMSIG_LIVING_MINOR_SHOCK)
user.DefaultCombatKnockdown(stamforce*6)
user.DefaultCombatKnockdown(stamina_loss_amount*6)
playsound(loc, 'sound/weapons/egloves.ogg', 50, 1, -1)
deductcharge(hitcost)
@@ -306,18 +331,20 @@
w_class = WEIGHT_CLASS_BULKY
force = 3
throwforce = 5
stamforce = 25
stamina_loss_amount = 25
hitcost = 1000
throw_hit_chance = 10
slot_flags = ITEM_SLOT_BACK
cooldown_duration = 7 SECONDS //It's a little on the weak side
status_duration = 3 //Slows someone for a tiny bit
var/obj/item/assembly/igniter/sparkler
/obj/item/melee/baton/cattleprod/Initialize()
. = ..()
sparkler = new (src)
sparkler.activate_cooldown = 5
sparkler.activate_cooldown = 7 //Helps visualize the knockdown
/obj/item/melee/baton/cattleprod/baton_stun()
/obj/item/melee/baton/cattleprod/baton_stun(mob/living/L, mob/living/carbon/user, shoving = FALSE)
sparkler?.activate()
. = ..()
@@ -344,8 +371,8 @@
/obj/item/melee/baton/boomerang/throw_impact(atom/hit_atom, datum/thrownthing/throwingdatum)
if(turned_on)
var/caught = hit_atom.hitby(src, FALSE, FALSE, throwingdatum=throwingdatum)
if(ishuman(hit_atom) && !caught && prob(throw_hit_chance))//if they are a carbon and they didn't catch it
baton_stun(hit_atom)
if(ishuman(hit_atom) && !caught && prob(throw_hit_chance) && thrownby)//if they are a carbon and they didn't catch it
baton_stun(hit_atom, thrownby, shoving = TRUE)
if(thrownby && !caught)
sleep(1)
if(!QDELETED(src))
+6 -6
View File
@@ -139,14 +139,14 @@
/obj/item/hand_tele/attack_self(mob/user)
var/turf/current_location = get_turf(user)//What turf is the user on?
var/area/current_area = current_location.loc
if(!current_location || current_area.noteleport || is_away_level(current_location.z) || !isturf(user.loc))//If turf was not found or they're on z level 2 or >7 which does not currently exist. or if user is not located on a turf
if(!current_location || (current_area.area_flags & NOTELEPORT) || is_away_level(current_location.z) || !isturf(user.loc))//If turf was not found or they're on z level 2 or >7 which does not currently exist. or if user is not located on a turf
to_chat(user, "<span class='notice'>\The [src] is malfunctioning.</span>")
return
var/list/L = list( )
for(var/obj/machinery/computer/teleporter/com in GLOB.machines)
if(com.target)
var/area/A = get_area(com.target)
if(!A || A.noteleport)
if(!A || (A.area_flags & NOTELEPORT))
continue
if(com.power_station && com.power_station.teleporter_hub && com.power_station.engaged)
L["[get_area(com.target)] (Active)"] = com.target
@@ -159,7 +159,7 @@
if(T.y>world.maxy-8 || T.y<8)
continue
var/area/A = T.loc
if(A.noteleport)
if(A.area_flags & NOTELEPORT)
continue
turfs += T
if(turfs.len)
@@ -172,12 +172,12 @@
return
var/atom/T = L[t1]
var/area/A = get_area(T)
if(A.noteleport)
to_chat(user, "<span class='notice'>\The [src] is malfunctioning.</span>")
if (A.area_flags & NOTELEPORT)
to_chat(user, "<span class='notice'>[src] is malfunctioning.</span>")
return
current_location = get_turf(user) //Recheck.
current_area = current_location.loc
if(!current_location || current_area.noteleport || is_away_level(current_location.z) || !isturf(user.loc))//If turf was not found or they're on z level 2 or >7 which does not currently exist. or if user is not located on a turf
if (!current_location || (current_area.area_flags & NOTELEPORT) || is_away_level(current_location.z) || !isturf(user.loc))
to_chat(user, "<span class='notice'>\The [src] is malfunctioning.</span>")
return
user.show_message("<span class='notice'>Locked In.</span>", MSG_AUDIBLE)
+2 -2
View File
@@ -6,7 +6,7 @@
item_state = "teleprod"
slot_flags = null
/obj/item/melee/baton/cattleprod/teleprod/baton_stun(mob/living/L, mob/living/carbon/user)//handles making things teleport when hit
/obj/item/melee/baton/cattleprod/teleprod/baton_stun(mob/living/L, mob/living/carbon/user, shoving = FALSE)//handles making things teleport when hit
. = ..()
if(!. || L.anchored)
return
@@ -16,7 +16,7 @@
user.visible_message("<span class='danger'>[user] accidentally hits [user.p_them()]self with [src]!</span>", \
"<span class='userdanger'>You accidentally hit yourself with [src]!</span>")
SEND_SIGNAL(user, COMSIG_LIVING_MINOR_SHOCK)
user.DefaultCombatKnockdown(stamforce * 6)
user.DefaultCombatKnockdown(stamina_loss_amount * 6)
playsound(loc, 'sound/weapons/egloves.ogg', 50, 1, -1)
if(do_teleport(user, get_turf(user), 50, channel = TELEPORT_CHANNEL_BLUESPACE))
deductcharge(hitcost)
+62
View File
@@ -911,6 +911,16 @@ for further reading, please see: https://github.com/tgstation/tgstation/pull/301
var/homerun_ready = 0
var/homerun_able = 0
total_mass = 2.7 //a regular wooden major league baseball bat weighs somewhere between 2 to 3.4 pounds, according to google
var/on_sound
var/on = TRUE // Are we on or off
var/on_icon_state // What is our sprite when turned on
var/off_icon_state // What is our sprite when turned off
var/on_item_state // What is our in-hand sprite when turned on
var/force_on // Damage when on
var/force_off // Damage when off
var/throwforce_on // Damage when on
var/throwforce_off // Damage when off
var/weight_class_on // What is the new size class when turned on
/obj/item/melee/baseball_bat/Initialize()
. = ..()
@@ -992,6 +1002,58 @@ for further reading, please see: https://github.com/tgstation/tgstation/pull/301
force = 18 //Spear damage...
throwforce = 30
/obj/item/melee/baseball_bat/proc/get_on_description()
. = list()
.["local_on"] = "<span class ='warning'>You extend the bat.</span>"
.["local_off"] = "<span class ='notice'>You collapse the bat.</span>"
return .
/obj/item/melee/baseball_bat/telescopic
name = "telescopic baseball bat"
desc = "A stealthy telescopic bat that can fit in a pocket when collapsed."
icon = 'icons/obj/items_and_weapons.dmi'
icon_state = "baseball_bat_telescopic_0"
lefthand_file = 'icons/mob/inhands/weapons/melee_lefthand.dmi'
righthand_file = 'icons/mob/inhands/weapons/melee_righthand.dmi'
item_state = null
w_class = WEIGHT_CLASS_SMALL
item_flags = NONE
force = 5
throwforce = 10
on = FALSE
on_sound = 'sound/weapons/batonextend.ogg'
on_icon_state = "baseball_bat_telescopic_1"
off_icon_state = "baseball_bat_telescopic_0"
on_item_state = "baseball_bat_telescopic"
force_on = 15
force_off = 5
throwforce_on = 20
throwforce_off = 10
weight_class_on = WEIGHT_CLASS_HUGE
total_mass = TOTAL_MASS_NORMAL_ITEM
/obj/item/melee/baseball_bat/telescopic/attack_self(mob/user)
on = !on
var/list/desc = get_on_description()
if(on)
to_chat(user, desc["local_on"])
icon_state = on_icon_state
item_state = on_item_state
w_class = weight_class_on
force = force_on
throwforce = throwforce_on
attack_verb = list("beat", "smacked")
else
to_chat(user, desc["local_off"])
icon_state = off_icon_state
item_state = null //no sprite for concealment even when in hand
w_class = WEIGHT_CLASS_SMALL
force = force_off
throwforce = throwforce_off
attack_verb = list("drubbed", "beaned")
playsound(src.loc, on_sound, 50, 1)
add_fingerprint(user)
/obj/item/melee/flyswatter
name = "flyswatter"
desc = "Useful for killing pests of all sizes."
+1 -1
View File
@@ -50,7 +50,7 @@
return FALSE
var/turf/T = get_turf(src)
var/area/A = get_area(src)
if(!A.blob_allowed)
if(!(A.area_flags & BLOBS_ALLOWED))
return FALSE
if(!A.powered(EQUIP))
return FALSE
@@ -275,16 +275,15 @@
/obj/structure/closet/proc/tool_interact(obj/item/W, mob/living/user)//returns TRUE if attackBy call shouldn't be continued (because tool was used/closet was of wrong type), FALSE if otherwise
. = TRUE
if(opened)
if(istype(W, /obj/item/weldingtool))
if(W.tool_behaviour == TOOL_WELDER)
// eigen check
if(eigen_teleport)
to_chat(user, "<span class='notice'>The unstable nature of \the [src] makes it impossible to deconstruct!</span>")
return
if(W.tool_behaviour == cutting_tool)
// eigen check
if(eigen_teleport)
to_chat(user, "<span class='notice'>The unstable nature of \the [src] makes it impossible to deconstruct!</span>")
return
if(W.tool_behaviour == TOOL_WELDER)
if(!W.tool_start_check(user, amount=0))
return
to_chat(user, "<span class='notice'>You begin cutting \the [src] apart...</span>")
if(W.use_tool(src, user, 40, volume=50))
if(!opened)
@@ -294,13 +293,29 @@
"<span class='hear'>You hear welding.</span>")
deconstruct(TRUE)
return
else // for example cardboard box is cut with wirecutters
else if(W.tool_behaviour == TOOL_WIRECUTTER)
W.use_tool(src, user, 40, volume=50)
user.visible_message("<span class='notice'>[user] cut apart \the [src].</span>", \
"<span class='notice'>You cut \the [src] apart with \the [W].</span>")
deconstruct(TRUE)
return
W.use_tool(src, user, 40, volume=50)
user.visible_message("<span class='notice'>[user] deconstructed \the [src].</span>", \
"<span class='notice'>You deconstructed \the [src] with \the [W].</span>")
deconstruct(TRUE) //Honestly by this point, if all checks were right and this is the cutting tool, just cut it
return
if(user.transferItemToLoc(W, drop_location())) // so we put in unlit welder too
return
else if(!opened && user.a_intent == INTENT_HELP)
var/item_is_id = W.GetID()
if(!item_is_id)
if(!open(user))
togglelock(user)
return
return
if(item_is_id || !toggle(user))
togglelock(user)
return
else if(W.tool_behaviour == TOOL_WELDER && can_weld_shut)
// eigen check
if(eigen_teleport)
@@ -328,12 +343,6 @@
user.visible_message("<span class='notice'>[user] [anchored ? "anchored" : "unanchored"] \the [src] [anchored ? "to" : "from"] the ground.</span>", \
"<span class='notice'>You [anchored ? "anchored" : "unanchored"] \the [src] [anchored ? "to" : "from"] the ground.</span>", \
"<span class='hear'>You hear a ratchet.</span>")
else if(user.a_intent != INTENT_HARM && !(W.item_flags & NOBLUDGEON))
var/item_is_id = W.GetID()
if(!item_is_id)
return FALSE
if(item_is_id || !toggle(user))
togglelock(user)
// cit addons
else if(istype(W, /obj/item/electronics/airlock))
handle_lock_addition(user, W)
@@ -19,3 +19,50 @@
desc = "A sturdier card-locked storage unit used for bulky shipments."
max_integrity = 500 // Same as crates.
melee_min_damage = 25 // Idem.
/obj/structure/closet/secure_closet/goodies/owned
name = "private locker"
desc = "A locker designed to only open for who purchased its contents."
///Account of the person buying the crate if private purchasing.
var/datum/bank_account/buyer_account
///Department of the person buying the crate if buying via the NIRN app.
var/datum/bank_account/department/department_account
///Is the secure crate opened or closed?
var/privacy_lock = TRUE
///Is the crate being bought by a person, or a budget card?
var/department_purchase = FALSE
/obj/structure/closet/secure_closet/goodies/owned/examine(mob/user)
. = ..()
. += "<span class='notice'>It's locked with a privacy lock, and can only be unlocked by the buyer's ID.</span>"
/obj/structure/closet/secure_closet/goodies/owned/Initialize(mapload, datum/bank_account/_buyer_account)
. = ..()
buyer_account = _buyer_account
if(istype(buyer_account, /datum/bank_account/department))
department_purchase = TRUE
department_account = buyer_account
/obj/structure/closet/secure_closet/goodies/owned/togglelock(mob/living/user, silent)
if(privacy_lock)
if(!broken)
var/obj/item/card/id/id_card = user.get_idcard(TRUE)
if(id_card)
if(id_card.registered_account)
if(id_card.registered_account == buyer_account || (department_purchase && (id_card.registered_account?.account_job?.paycheck_department) == (department_account.department_id)))
if(iscarbon(user))
add_fingerprint(user)
locked = !locked
user.visible_message("<span class='notice'>[user] unlocks [src]'s privacy lock.</span>",
"<span class='notice'>You unlock [src]'s privacy lock.</span>")
privacy_lock = FALSE
update_icon()
else if(!silent)
to_chat(user, "<span class='notice'>Bank account does not match with buyer!</span>")
else if(!silent)
to_chat(user, "<span class='notice'>No linked bank account detected!</span>")
else if(!silent)
to_chat(user, "<span class='notice'>No ID detected!</span>")
else if(!silent)
to_chat(user, "<span class='warning'>[src] is broken!</span>")
else ..()
@@ -590,7 +590,7 @@
/obj/effect/mob_spawn/human/pirate
name = "space pirate sleeper"
desc = "A cryo sleeper smelling faintly of rum."
desc = "A cryo sleeper smelling faintly of rum. The sleeper looks unstable. <i>Perhaps the pirate within can be killed with the right tools...</i>"
job_description = "Space Pirate"
random = TRUE
icon = 'icons/obj/machines/sleeper.dmi'
@@ -608,6 +608,54 @@
assignedrole = "Space Pirate"
var/rank = "Mate"
/obj/effect/mob_spawn/human/pirate/on_attack_hand(mob/living/user, act_intent = user.a_intent, unarmed_attack_flags)
. = ..()
if(.)
return
if(user.mind.has_antag_datum(/datum/antagonist/pirate))
to_chat(user, "<span class='notice'>Your shipmate sails within their dreams for now. Perhaps they may wake up eventually.</span>")
else
to_chat(user, "<span class='notice'>If you want to kill the pirate off, something to pry open the sleeper might be the best way to do it.</span>")
/obj/effect/mob_spawn/human/pirate/attackby(obj/item/W, mob/user, params)
if(W.tool_behaviour == TOOL_CROWBAR && user.a_intent != INTENT_HARM)
if(user.mind.has_antag_datum(/datum/antagonist/pirate))
to_chat(user,"<span class='warning'>Why would you want to do that to your shipmate? That'd kill them.</span>")
return
user.visible_message("<span class='warning'>[user] start to pry open [src]...</span>",
"<span class='notice'>You start to pry open [src]...</span>",
"<span class='italics'>You hear prying...</span>")
W.play_tool_sound(src)
if(do_after(user, 100*W.toolspeed, target = src))
user.visible_message("<span class='warning'>[user] pries open [src], disrupting the sleep of the pirate within and killing them.</span>",
"<span class='notice'>You pry open [src], disrupting the sleep of the pirate within and killing them.</span>",
"<span class='italics'>You hear prying, followed by the death rattling of bones.</span>")
log_game("[key_name(user)] has successfully pried open [src] and disabled a space pirate spawner.")
W.play_tool_sound(src)
playsound(src.loc, 'modular_citadel/sound/voice/scream_skeleton.ogg', 50, 1, 4, 1.2)
if(rank == "Captain")
new /obj/effect/mob_spawn/human/pirate/corpse/captain(get_turf(src))
else
new /obj/effect/mob_spawn/human/pirate/corpse(get_turf(src))
qdel(src)
else
..()
/obj/effect/mob_spawn/human/pirate/corpse //occurs when someone pries a pirate out of their sleeper.
mob_name = "Dead Space Pirate"
death = TRUE
instant = TRUE
random = FALSE
/obj/effect/mob_spawn/human/pirate/corpse/Destroy()
return ..()
/obj/effect/mob_spawn/human/pirate/corpse/captain
rank = "Captain"
mob_name = "Dead Space Pirate Captain"
outfit = /datum/outfit/pirate/space/captain
/obj/effect/mob_spawn/human/pirate/special(mob/living/new_spawn)
new_spawn.fully_replace_character_name(new_spawn.real_name,generate_pirate_name())
new_spawn.mind.add_antag_datum(/datum/antagonist/pirate)
@@ -662,6 +710,72 @@
to_chat(M,"<span class='notice'>You're once again longer hearing deadchat.</span>")
/datum/action/disguise
name = "Disguise"
button_icon_state = "ling_transform"
icon_icon = 'icons/mob/actions/actions_changeling.dmi'
background_icon_state = "bg_mime"
var/currently_disguised = FALSE
var/static/list/mob_blacklist = typecacheof(list(
/mob/living/simple_animal/pet,
/mob/living/simple_animal/hostile/retaliate/goose,
/mob/living/simple_animal/hostile/poison,
/mob/living/simple_animal/hostile/retaliate/goat,
/mob/living/simple_animal/cow,
/mob/living/simple_animal/chick,
/mob/living/simple_animal/chicken,
/mob/living/simple_animal/kiwi,
/mob/living/simple_animal/babyKiwi,
/mob/living/simple_animal/deer,
/mob/living/simple_animal/parrot,
/mob/living/simple_animal/hostile/lizard,
/mob/living/simple_animal/crab,
/mob/living/simple_animal/cockroach,
/mob/living/simple_animal/butterfly,
/mob/living/simple_animal/mouse,
/mob/living/simple_animal/sloth,
/mob/living/simple_animal/opossum,
/mob/living/simple_animal/hostile/bear,
/mob/living/simple_animal/hostile/asteroid/polarbear,
/mob/living/simple_animal/hostile/asteroid/wolf,
/mob/living/carbon/monkey,
/mob/living/simple_animal/hostile/gorilla,
/mob/living/carbon/alien/larva,
/mob/living/simple_animal/hostile/retaliate/frog
))
/datum/action/disguise/Trigger()
var/mob/living/carbon/human/H = owner
if(!currently_disguised)
var/user_object_type = input(H, "Disguising as OBJECT or MOB?") as null|anything in list("OBJECT", "MOB")
if(user_object_type)
var/search_term = stripped_input(H, "Enter the search term")
if(search_term)
var/list_to_search
if(user_object_type == "MOB")
list_to_search = subtypesof(/mob) - mob_blacklist
else
list_to_search = subtypesof(/obj)
var/list/filtered_results = list()
for(var/some_search_item in list_to_search)
if(findtext("[some_search_item]", search_term))
filtered_results += some_search_item
if(!length(filtered_results))
to_chat(H, "Nothing matched your search query!")
else
var/disguise_selection = input("Select item to disguise as") as null|anything in filtered_results
if(disguise_selection)
var/atom/disguise_item = disguise_selection
var/image/I = image(icon = initial(disguise_item.icon), icon_state = initial(disguise_item.icon_state), loc = H)
I.override = TRUE
I.layer = ABOVE_MOB_LAYER
H.add_alt_appearance(/datum/atom_hud/alternate_appearance/basic/everyone, "ghost_cafe_disguise", I)
currently_disguised = TRUE
else
H.remove_alt_appearance("ghost_cafe_disguise")
currently_disguised = FALSE
/obj/effect/mob_spawn/human/ghostcafe/special(mob/living/carbon/human/new_spawn)
if(new_spawn.client)
new_spawn.client.prefs.copy_to(new_spawn)
@@ -679,6 +793,8 @@
to_chat(new_spawn,"<span class='boldwarning'>Ghosting is free!</span>")
var/datum/action/toggle_dead_chat_mob/D = new(new_spawn)
D.Grant(new_spawn)
var/datum/action/disguise/disguise_action = new(new_spawn)
disguise_action.Grant(new_spawn)
/datum/outfit/ghostcafe
name = "ID, jumpsuit and shoes"
@@ -199,8 +199,7 @@
return TRUE
/obj/item/gun_control/attack(mob/living/M, mob/living/user)
M.lastattacker = user.real_name
M.lastattackerckey = user.ckey
M.set_last_attacker(user)
M.attacked_by(src, user)
add_fingerprint(user)
+7 -7
View File
@@ -3,7 +3,7 @@
#define STAIR_TERMINATOR_YES 2
// dir determines the direction of travel to go upwards (due to lack of sprites, currently only 1 and 2 make sense)
// stairs require /turf/open/transparent/openspace as the tile above them to work
// stairs require /turf/open/openspace as the tile above them to work
// multiple stair objects can be chained together; the Z level transition will happen on the final stair object in the chain
/obj/structure/stairs
@@ -12,7 +12,7 @@
icon_state = "stairs"
anchored = TRUE
var/force_open_above = FALSE // replaces the turf above this stair obj with /turf/open/transparent/openspace
var/force_open_above = FALSE // replaces the turf above this stair obj with /turf/open/openspace
var/terminator_mode = STAIR_TERMINATOR_AUTOMATIC
var/turf/listeningTo
@@ -107,23 +107,23 @@
/obj/structure/stairs/proc/build_signal_listener()
if(listeningTo)
UnregisterSignal(listeningTo, COMSIG_TURF_MULTIZ_NEW)
var/turf/open/transparent/openspace/T = get_step_multiz(get_turf(src), UP)
var/turf/open/openspace/T = get_step_multiz(get_turf(src), UP)
RegisterSignal(T, COMSIG_TURF_MULTIZ_NEW, .proc/on_multiz_new)
listeningTo = T
/obj/structure/stairs/proc/force_open_above()
var/turf/open/transparent/openspace/T = get_step_multiz(get_turf(src), UP)
var/turf/open/openspace/T = get_step_multiz(get_turf(src), UP)
if(T && !istype(T))
T.ChangeTurf(/turf/open/transparent/openspace, flags = CHANGETURF_INHERIT_AIR)
T.ChangeTurf(/turf/open/openspace, flags = CHANGETURF_INHERIT_AIR)
/obj/structure/stairs/proc/on_multiz_new(turf/source, dir)
//SIGNAL_HANDLER
SHOULD_NOT_SLEEP(TRUE) //the same thing.
if(dir == UP)
var/turf/open/transparent/openspace/T = get_step_multiz(get_turf(src), UP)
var/turf/open/openspace/T = get_step_multiz(get_turf(src), UP)
if(T && !istype(T))
T.ChangeTurf(/turf/open/transparent/openspace, flags = CHANGETURF_INHERIT_AIR)
T.ChangeTurf(/turf/open/openspace, flags = CHANGETURF_INHERIT_AIR)
/obj/structure/stairs/intercept_zImpact(atom/movable/AM, levels = 1)
. = ..()
@@ -93,6 +93,9 @@
user.stop_pulling()
return ..()
/obj/structure/table/attack_robot(mob/user)
on_attack_hand(user)
/obj/structure/table/attack_tk()
return FALSE
@@ -67,6 +67,9 @@
to_chat(user, "<span class='notice'>You put [I] in [src].</span>")
update_icon()
/obj/structure/tank_dispenser/attack_robot(mob/user)
return _try_interact(user)
/obj/structure/tank_dispenser/ui_state(mob/user)
return GLOB.physical_state
+1 -1
View File
@@ -554,7 +554,7 @@
if(B.cell)
if(B.cell.charge > 0 && B.turned_on)
flick("baton_active", src)
var/stunforce = B.stamforce
var/stunforce = B.stamina_loss_amount
user.DefaultCombatKnockdown(stunforce * 2)
user.stuttering = stunforce/20
B.deductcharge(B.hitcost)
-100
View File
@@ -1,100 +0,0 @@
/turf/open/transparent
baseturfs = /turf/open/transparent/openspace
intact = FALSE //this means wires go on top
/turf/open/transparent/Initialize() // handle plane and layer here so that they don't cover other obs/turfs in Dream Maker
. = ..()
plane = OPENSPACE_PLANE
layer = OPENSPACE_LAYER
return INITIALIZE_HINT_LATELOAD
/turf/open/transparent/LateInitialize()
update_multiz(TRUE, TRUE)
/turf/open/transparent/Destroy()
vis_contents.len = 0
return ..()
/turf/open/transparent/update_multiz(prune_on_fail = FALSE, init = FALSE)
. = ..()
var/turf/T = below()
if(!T)
vis_contents.len = 0
if(!show_bottom_level() && prune_on_fail) //If we cant show whats below, and we prune on fail, change the turf to plating as a fallback
ChangeTurf(/turf/open/floor/plating, flags = CHANGETURF_INHERIT_AIR)
return FALSE
if(init)
vis_contents += T
return TRUE
/turf/open/transparent/multiz_turf_del(turf/T, dir)
if(dir != DOWN)
return
update_multiz()
/turf/open/transparent/multiz_turf_new(turf/T, dir)
if(dir != DOWN)
return
update_multiz()
///Called when there is no real turf below this turf
/turf/open/transparent/proc/show_bottom_level()
var/turf/path = SSmapping.level_trait(z, ZTRAIT_BASETURF) || /turf/open/space
if(!ispath(path))
path = text2path(path)
if(!ispath(path))
warning("Z-level [z] has invalid baseturf '[SSmapping.level_trait(z, ZTRAIT_BASETURF)]'")
path = /turf/open/space
var/mutable_appearance/underlay_appearance = mutable_appearance(initial(path.icon), initial(path.icon_state), layer = TURF_LAYER, plane = PLANE_SPACE)
underlays += underlay_appearance
return TRUE
/turf/open/transparent/glass
name = "Glass floor"
desc = "Dont jump on it, or do, I'm not your mom."
icon = 'icons/turf/floors/glass.dmi'
icon_state = "floor_glass"
smooth = SMOOTH_MORE
var/floor_tile = /obj/item/stack/sheet/glass
canSmoothWith = list(/turf/open/transparent/glass, /turf/open/transparent/glass/reinforced)
footstep = FOOTSTEP_PLATING
barefootstep = FOOTSTEP_HARD_BAREFOOT
clawfootstep = FOOTSTEP_HARD_CLAW
heavyfootstep = FOOTSTEP_GENERIC_HEAVY
/turf/open/transparent/glass/Initialize()
icon_state = "" //Prevent the normal icon from appearing behind the smooth overlays
..()
return INITIALIZE_HINT_LATELOAD
/turf/open/floor/glass/LateInitialize()
. = ..()
// AddElement(/datum/element/turf_z_transparency, TRUE)
/turf/open/transparent/glass/wrench_act(mob/living/user, obj/item/I)
to_chat(user, "<span class='notice'>You begin removing glass...</span>")
if(I.use_tool(src, user, 30, volume=80))
if(!istype(src, /turf/open/transparent/glass))
return TRUE
if(floor_tile)
new floor_tile(src, 2)
ScrapeAway(flags = CHANGETURF_INHERIT_AIR)
return TRUE
/turf/open/transparent/glass/reinforced
name = "Reinforced glass floor"
desc = "Do jump on it, it can take it."
icon = 'icons/turf/floors/reinf_glass.dmi'
floor_tile = /obj/item/stack/sheet/rglass
/turf/open/transparent/glass/reinforced/wrench_act(mob/living/user, obj/item/I)
to_chat(user, "<span class='notice'>You begin removing reinforced glass...</span>")
if(I.use_tool(src, user, 30, volume=80))
if(!istype(src, /turf/open/transparent/glass/reinforced))
return TRUE
if(floor_tile)
new floor_tile(src, 2)
ScrapeAway(flags = CHANGETURF_INHERIT_AIR)
return TRUE
+21 -19
View File
@@ -8,12 +8,10 @@
//Making the station dirty, one tile at a time. Called by master controller's setup_objects
/turf/open/floor/proc/MakeDirty()
// We start with a 1/3 chance of having this proc called by Initialize()
if(CONFIG_GET(flag/persistent_debris_only))
return
if(prob(66)) //fastest possible exit 2/3 of the time
return
if(!(flags_1 & CAN_BE_DIRTY_1))
return
@@ -31,22 +29,23 @@
var/static/list/high_dirt_areas = typecacheof(list(/area/science/test_area,
/area/mine/production,
/area/mine/living_quarters,
/area/commons/vacant_room/office,
/area/ruin/space))
if(is_type_in_typecache(A, high_dirt_areas))
new /obj/effect/decal/cleanable/dirt(src) //vanilla, but it works
new /obj/effect/decal/cleanable/dirt(src) //vanilla, but it works
return
if(prob(80)) //mid dirt - 1/15
if(prob(80)) //mid dirt - 1/15
return
//Construction zones. Blood, sweat, and oil. Oh, and dirt.
var/static/list/engine_dirt_areas = typecacheof(list(/area/engine,
/area/crew_quarters/heads/chief,
/area/ruin/space/derelict/assembly_line,
var/static/list/engine_dirt_areas = typecacheof(list(/area/engineering,
/area/command/heads_quarters/ce,
/area/science/robotics,
/area/maintenance,
/area/construction,
/area/commons/vacant_room/commissary,
/area/survivalpod))
if(is_type_in_typecache(A, engine_dirt_areas))
if(prob(3))
@@ -62,7 +61,7 @@
return
//Bathrooms. Blood, vomit, and shavings in the sinks.
var/static/list/bathroom_dirt_areas = typecacheof(list( /area/crew_quarters/toilet,
var/static/list/bathroom_dirt_areas = typecacheof(list( /area/commons/toilet,
/area/awaymission/research/interior/bathroom))
if(is_type_in_typecache(A, bathroom_dirt_areas))
if(prob(40))
@@ -72,21 +71,24 @@
new /obj/effect/decal/cleanable/blood/old(src)
return
//Hangars and pods covered in oil.
var/static/list/oily_areas = typecacheof(/area/quartermaster)
// Cargo bays covered in oil.
var/static/list/oily_areas = typecacheof(/area/cargo)
if(is_type_in_typecache(A, oily_areas))
if(prob(25))
new /obj/effect/decal/cleanable/oil(src)
// else if(prob(20))
// // or occasionally the signs of opened packages
// new /obj/effect/decal/cleanable/wrapping(src)
return
if(prob(75)) //low dirt - 1/60
if(prob(75)) //low dirt - 1/60
return
//Areas where gibs will be present. Robusting probably happened some time ago.
var/static/list/gib_covered_areas = typecacheof(list(/area/ai_monitored/turret_protected,
/area/security,
/area/crew_quarters/heads/hos))
/area/command/heads_quarters/hos))
if(is_type_in_typecache(A, gib_covered_areas))
if(prob(20))
if(prob(5))
@@ -96,8 +98,8 @@
return
//Kitchen areas. Broken eggs, flour, spilled milk (no crying allowed.)
var/static/list/kitchen_dirt_areas = typecacheof(list(/area/crew_quarters/kitchen,
/area/crew_quarters/cafeteria))
var/static/list/kitchen_dirt_areas = typecacheof(list(/area/service/kitchen,
/area/service/cafeteria))
if(is_type_in_typecache(A, kitchen_dirt_areas))
if(prob(60))
if(prob(50))
@@ -108,7 +110,7 @@
//Medical areas. Mostly clean by space-OSHA standards, but has some blood and oil spread about.
var/static/list/medical_dirt_areas = typecacheof(list(/area/medical,
/area/crew_quarters/heads/cmo))
/area/command/heads_quarters/cmo))
if(is_type_in_typecache(A, medical_dirt_areas))
if(prob(66))
if(prob(5))
@@ -124,10 +126,10 @@
//Science messes. Mostly green glowy stuff -WHICH YOU SHOULD NOT INJEST-.
var/static/list/science_dirt_areas = typecacheof(list(/area/science,
/area/crew_quarters/heads/hor))
if(is_type_in_typecache(A, medical_dirt_areas))
/area/command/heads_quarters/rd))
if(is_type_in_typecache(A, science_dirt_areas))
if(prob(20))
new /obj/effect/decal/cleanable/greenglow(src) //this cleans itself up but it might startle you when you see it.
new /obj/effect/decal/cleanable/greenglow(src) //this cleans itself up but it might startle you when you see it.
return
return TRUE
+1 -1
View File
@@ -56,7 +56,7 @@
icon_regular_floor = "floor"
else
icon_regular_floor = icon_state
if(mapload)
if(mapload && prob(66)) // 2/3 instead of 1/3 (default)
MakeDirty()
/turf/open/floor/ex_act(severity, target)
+4 -4
View File
@@ -80,11 +80,11 @@
else
to_chat(user, "<span class='notice'>You begin adding glass to the floor...</span>")
if(do_after(user, 5, target = src))
if (G.get_amount() >= 2 && !istype(src, /turf/open/transparent/glass))
if (G.get_amount() >= 2 && !istype(src, /turf/open/floor/glass))
for(var/obj/effect/decal/cleanable/decal in src)
if(decal.wiped_by_floor_change)
qdel(decal)
PlaceOnTop(/turf/open/transparent/glass, flags = CHANGETURF_INHERIT_AIR)
PlaceOnTop(/turf/open/floor/glass, flags = CHANGETURF_INHERIT_AIR)
playsound(src, 'sound/items/deconstruct.ogg', 80, 1)
G.use(2)
to_chat(user, "<span class='notice'>You add glass to the floor.</span>")
@@ -100,11 +100,11 @@
else
to_chat(user, "<span class='notice'>You begin adding reinforced glass to the floor...</span>")
if(do_after(user, 10, target = src))
if (RG.get_amount() >= 2 && !istype(src, /turf/open/transparent/glass/reinforced))
if (RG.get_amount() >= 2 && !istype(src, /turf/open/floor/glass/reinforced))
for(var/obj/effect/decal/cleanable/decal in src)
if(decal.wiped_by_floor_change)
qdel(decal)
PlaceOnTop(/turf/open/transparent/glass/reinforced, flags = CHANGETURF_INHERIT_AIR)
PlaceOnTop(/turf/open/floor/glass/reinforced, flags = CHANGETURF_INHERIT_AIR)
playsound(src, 'sound/items/deconstruct.ogg', 80, 1)
RG.use(2)
to_chat(user, "<span class='notice'>You add reinforced glass to the floor.</span>")
@@ -8,7 +8,6 @@
icon = 'icons/turf/floors.dmi'
icon_state = "asteroid"
icon_plating = "asteroid"
postdig_icon_change = TRUE
footstep = FOOTSTEP_SAND
barefootstep = FOOTSTEP_SAND
clawfootstep = FOOTSTEP_SAND
@@ -16,13 +15,19 @@
/// 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
/// Probability the floor has a different icon state
var/turf_type = /turf/open/floor/plating/asteroid
/// Probability floor has a different icon state
var/floor_variance = 20
attachment_holes = FALSE
/// Itemstack to drop when dug by a shovel
var/obj/item/stack/digResult = /obj/item/stack/ore/glass/basalt
/// Whether the turf has been dug or not
var/dug
/// Whether to change the turf's icon_state to "[base_icon_state]_dug" when its dugged up
postdig_icon_change = TRUE
// /turf/open/floor/plating/asteroid/setup_broken_states()
// return list("asteroid_dug")
/turf/open/floor/plating/asteroid/Initialize()
var/proper_name = name
@@ -33,19 +38,18 @@
/// Drops itemstack when dug and changes icon
/turf/open/floor/plating/asteroid/proc/getDug()
dug = TRUE
new digResult(src, 5)
if(postdig_icon_change)
if(!postdig_icon)
icon_plating = "[environment_type]_dug"
icon_state = "[environment_type]_dug"
dug = TRUE
icon_plating = "[environment_type]_dug"
icon_state = "[environment_type]_dug"
/// If the user can dig the turf
/turf/open/floor/plating/asteroid/proc/can_dig(mob/user)
if(!dug)
return TRUE
if(user)
to_chat(user, "<span class='notice'>Looks like someone has dug here already.</span>")
to_chat(user, "<span class='warning'>Looks like someone has dug here already!</span>")
/turf/open/floor/plating/asteroid/try_replace_tile(obj/item/stack/tile/T, mob/user, params)
return
@@ -59,6 +63,9 @@
/turf/open/floor/plating/asteroid/MakeDry()
return
// /turf/open/floor/plating/asteroid/crush()
// return
/turf/open/floor/plating/asteroid/attackby(obj/item/W, mob/user, params)
. = ..()
if(!.)
@@ -99,6 +106,9 @@
floor_variance = 15
digResult = /obj/item/stack/ore/glass/basalt
// /turf/open/floor/plating/asteroid/basalt/setup_broken_states()
// return list("basalt_dug")
/turf/open/floor/plating/asteroid/basalt/lava //lava underneath
baseturfs = /turf/open/lava/smooth
@@ -128,280 +138,16 @@
planetary_atmos = TRUE
baseturfs = /turf/open/lava/smooth/lava_land_surface
// /turf/open/floor/plating/asteroid/lowpressure
// initial_gas_mix = OPENTURF_LOW_PRESSURE
// baseturfs = /turf/open/floor/plating/asteroid/lowpressure
// turf_type = /turf/open/floor/plating/asteroid/lowpressure
/turf/open/floor/plating/asteroid/airless
initial_gas_mix = AIRLESS_ATMOS
baseturfs = /turf/open/floor/plating/asteroid/airless
turf_type = /turf/open/floor/plating/asteroid/airless
#define SPAWN_MEGAFAUNA "bluh bluh huge boss"
#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
//terrain to spawn weighted list
var/list/terrain_spawn_list
/// Turf type to choose when spawning in tunnel at 1% chance, weighted list
var/list/choose_turf_type
/// if the tunnel should keep being created
var/sanity = 1
/// Cave direction to move
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
has_data = TRUE
/turf/open/floor/plating/asteroid/airless/cave/volcanic
mob_spawn_list = list(/mob/living/simple_animal/hostile/asteroid/goliath/beast/random = 50, /obj/structure/spawner/lavaland/goliath = 3, \
/mob/living/simple_animal/hostile/asteroid/basilisk/watcher/random = 40, /obj/structure/spawner/lavaland = 2, \
/mob/living/simple_animal/hostile/asteroid/hivelord/legion/random = 30, /obj/structure/spawner/lavaland/legion = 3, \
SPAWN_MEGAFAUNA = 6, /mob/living/simple_animal/hostile/asteroid/goldgrub = 10)
data_having_type = /turf/open/floor/plating/asteroid/airless/cave/volcanic/has_data
turf_type = /turf/open/floor/plating/asteroid/basalt/lava_land_surface
initial_gas_mix = LAVALAND_DEFAULT_ATMOS
/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, \
/mob/living/simple_animal/hostile/asteroid/lobstrosity = 15)
flora_spawn_list = list(/obj/structure/flora/tree/pine = 2, /obj/structure/flora/grass/both = 12, /obj/structure/flora/rock/icy = 6, /obj/structure/flora/rock/pile/icy = 6)
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)
if (!megafauna_spawn_list)
megafauna_spawn_list = list(/mob/living/simple_animal/hostile/megafauna/dragon = 4, /mob/living/simple_animal/hostile/megafauna/colossus = 2, /mob/living/simple_animal/hostile/megafauna/bubblegum = SPAWN_BUBBLEGUM)
if (!flora_spawn_list)
flora_spawn_list = list(/obj/structure/flora/ash/leaf_shroom = 2 , /obj/structure/flora/ash/cap_shroom = 2 , /obj/structure/flora/ash/stem_shroom = 2 , /obj/structure/flora/ash/cacti = 1, /obj/structure/flora/ash/tall_shroom = 2)
if(!terrain_spawn_list)
terrain_spawn_list = list(/obj/structure/geyser/random = 1)
. = ..()
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)
length = rand(25, 50)
else
length = set_length
// Get our directiosn
forward_cave_dir = pick(GLOB.alldirs - exclude_dir)
// 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
make_tunnel(forward_cave_dir)
if(going_backwards)
make_tunnel(backward_cave_dir)
// 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
var/list/L = list(45)
if(ISODD(dir2angle(dir))) // We're going at an angle and we want thick angled tunnels.
L += -45
// Expand the edges of our tunnel
for(var/edge_angle in L)
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
// Move our tunnel forward
tunnel = get_step(tunnel, dir)
if(istype(tunnel))
// Small chance to have forks in our tunnel; otherwise dig our tunnel.
if(i > 3 && prob(20))
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)
else
SpawnFloor(tunnel)
else //if(!istype(tunnel, parent)) // We hit space/normal/wall, stop our tunnel.
break
// Chance to change our direction left or right.
if(i > 2 && prob(33))
// We can't go a full loop though
next_angle = -next_angle
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)
var/area/A = T.loc
if(!A.tunnel_allowed)
sanity = 0
return
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)
SpawnTerrain(T)
T.ChangeTurf(turf_type, null, CHANGETURF_IGNORE_AIR)
/turf/open/floor/plating/asteroid/airless/cave/proc/SpawnTerrain(turf/T)
if(prob(1))
if(istype(loc, /area/mine/explored) || istype(loc, /area/lavaland/surface/outdoors/explored))
return
var/randumb = pickweight(terrain_spawn_list)
for(var/obj/structure/geyser/F in range(7, T))
if(istype(F, randumb))
return
new randumb(T)
/// 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(!A.mob_spawn_allowed)
return
var/randumb = pickweight(mob_spawn_list)
if(!randumb)
return
while(randumb == SPAWN_MEGAFAUNA)
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
if(ispath(maybe_boss, /mob/living/simple_animal/hostile/megafauna/bubblegum)) //there can be only one bubblegum, so don't waste spawns on it
megafauna_spawn_list[maybe_boss] = 0
else //this is not danger, don't spawn a boss, spawn something else
randumb = pickweight(mob_spawn_list)
for(var/mob/living/simple_animal/hostile/H in urange(12,T)) //prevents mob clumps
if((ispath(randumb, /mob/living/simple_animal/hostile/megafauna) || ismegafauna(H)) && get_dist(src, H) <= 7)
return //if there's a megafauna within standard view don't spawn anything at all
if(ispath(randumb, /mob/living/simple_animal/hostile/asteroid) || istype(H, /mob/living/simple_animal/hostile/asteroid))
return //if the random is a standard mob, avoid spawning if there's another one within 12 tiles
if((ispath(randumb, /obj/structure/spawner/lavaland) || istype(H, /obj/structure/spawner/lavaland)) && get_dist(src, H) <= 2)
return //prevents tendrils spawning in each other's collapse range
new randumb(T)
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(isarea(loc))
var/area/A = loc
if(!A.flora_allowed)
return
var/randumb = pickweight(flora_spawn_list)
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
name = "snow"
@@ -420,6 +166,9 @@
bullet_bounce_sound = null
digResult = /obj/item/stack/sheet/mineral/snow
// /turf/open/floor/plating/asteroid/snow/setup_broken_states()
// return list("snow_dug")
/turf/open/floor/plating/asteroid/snow/burn_tile()
if(!burnt)
visible_message("<span class='danger'>[src] melts away!.</span>")
@@ -430,8 +179,9 @@
return FALSE
/turf/open/floor/plating/asteroid/snow/icemoon
baseturfs = /turf/open/floor/plating/asteroid/snow/icemoon
baseturfs = /turf/open/openspace/icemoon
initial_gas_mix = ICEMOON_DEFAULT_ATMOS
slowdown = 0
/turf/open/lava/plasma/ice_moon
initial_gas_mix = ICEMOON_DEFAULT_ATMOS
@@ -442,24 +192,22 @@
name = "icy snow"
desc = "Looks colder."
baseturfs = /turf/open/floor/plating/asteroid/snow/ice
initial_gas_mix = "o2=0;n2=82;plasma=24;TEMP=120"
initial_gas_mix = "n2=82;plasma=24;TEMP=120"
floor_variance = 0
icon_state = "snow-ice"
icon_plating = "snow-ice"
environment_type = "snow_cavern"
environment_type = "snow-ice"
footstep = FOOTSTEP_FLOOR
barefootstep = FOOTSTEP_HARD_BAREFOOT
clawfootstep = FOOTSTEP_HARD_CLAW
heavyfootstep = FOOTSTEP_GENERIC_HEAVY
// /turf/open/floor/plating/asteroid/snow/ice/setup_broken_states()
// return list("snow-ice")
/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"
slowdown = 0
/turf/open/floor/plating/asteroid/snow/ice/burn_tile()
return FALSE
+61
View File
@@ -0,0 +1,61 @@
/turf/open/floor/glass
name = "Glass floor"
desc = "Dont jump on it, or do, I'm not your mom."
icon = 'icons/turf/floors/glass.dmi'
icon_state = "floor_glass"
baseturfs = /turf/open/openspace
intact = FALSE //this means wires go on top
smooth = SMOOTH_MORE
canSmoothWith = list(/turf/open/floor/glass, /turf/open/floor/glass/reinforced)
footstep = FOOTSTEP_PLATING
barefootstep = FOOTSTEP_HARD_BAREFOOT
clawfootstep = FOOTSTEP_HARD_CLAW
heavyfootstep = FOOTSTEP_GENERIC_HEAVY
floor_tile = /obj/item/stack/sheet/glass
// /turf/open/floor/glass/setup_broken_states()
// return list("glass-damaged1", "glass-damaged2", "glass-damaged3")
/turf/open/floor/glass/Initialize()
icon_state = "" //Prevent the normal icon from appearing behind the smooth overlays
..()
return INITIALIZE_HINT_LATELOAD
/turf/open/floor/glass/LateInitialize()
. = ..()
AddElement(/datum/element/turf_z_transparency, TRUE)
/// n(omegalul)
/turf/open/floor/glass/crowbar_act(mob/living/user, obj/item/I)
return TRUE
/turf/open/floor/glass/wrench_act(mob/living/user, obj/item/I)
to_chat(user, "<span class='notice'>You begin removing glass...</span>")
if(I.use_tool(src, user, 30, volume=80))
if(!istype(src, /turf/open/floor/glass))
return TRUE
if(floor_tile)
new floor_tile(src, 2)
ScrapeAway(flags = CHANGETURF_INHERIT_AIR)
return TRUE
/turf/open/floor/glass/reinforced
name = "Reinforced glass floor"
desc = "Do jump on it, it can take it."
icon = 'icons/turf/floors/reinf_glass.dmi'
icon_state = "floor_glass"
// base_icon_state = "reinf_glass"
// /turf/open/floor/glass/reinforced/setup_broken_states()
// return list("reinf_glass-damaged1", "reinf_glass-damaged2", "reinf_glass-damaged3")
/turf/open/floor/glass/reinforced/wrench_act(mob/living/user, obj/item/I)
to_chat(user, "<span class='notice'>You begin removing reinforced glass...</span>")
if(I.use_tool(src, user, 30, volume=80))
if(!istype(src, /turf/open/floor/glass/reinforced))
return TRUE
if(floor_tile)
new floor_tile(src, 2)
ScrapeAway(flags = CHANGETURF_INHERIT_AIR)
return TRUE
+186 -417
View File
@@ -1,43 +1,59 @@
#define MINING_MESSAGE_COOLDOWN 20
/**********************Mineral deposits**************************/
/turf/closed/mineral //wall piece
name = "rock"
icon = 'icons/turf/mining.dmi'
icon_state = "rock"
var/smooth_icon = 'icons/turf/smoothrocks.dmi'
smooth = SMOOTH_MORE|SMOOTH_BORDER
canSmoothWith = null
baseturfs = /turf/open/floor/plating/asteroid/airless
initial_gas_mix = AIRLESS_ATMOS
opacity = 1
opacity = TRUE
density = TRUE
blocks_air = 1
blocks_air = TRUE
layer = EDGED_TURF_LAYER
// base_icon_state = "smoothrocks"
temperature = TCMB
var/smooth_icon = 'icons/turf/smoothrocks.dmi'
var/environment_type = "asteroid"
var/turf/open/floor/plating/turf_type = /turf/open/floor/plating/asteroid/airless
var/mineralType = null
var/obj/item/stack/ore/mineralType = null
var/mineralAmt = 3
var/spread = 0 //will the seam spread?
var/spreadChance = 0 //the percentual chance of an ore spreading to the neighbouring tiles
var/last_act = 0
var/scan_state = "" //Holder for the image we display when we're pinged by a mining scanner
var/defer_change = 0
// If true you can mine the mineral turf with your hands
var/weak_turf = FALSE
/turf/closed/mineral/Initialize()
if (!canSmoothWith)
canSmoothWith = list(/turf/closed/mineral, /turf/closed/indestructible)
. = ..()
var/matrix/M = new
M.Translate(-4, -4)
transform = M
icon = smooth_icon
. = ..()
if (mineralType && mineralAmt && spread && spreadChance)
/turf/closed/mineral/proc/Spread_Vein()
var/spreadChance = initial(mineralType.spreadChance)
if(spreadChance)
for(var/dir in GLOB.cardinals)
if(prob(spreadChance))
var/turf/T = get_step(src, dir)
if(istype(T, /turf/closed/mineral/random))
Spread(T)
var/turf/closed/mineral/random/M = T
if(istype(M) && !M.mineralType)
M.Change_Ore(mineralType)
/turf/closed/mineral/proc/Change_Ore(ore_type, random = 0)
if(random)
mineralAmt = rand(1, 5)
if(ispath(ore_type, /obj/item/stack/ore)) //If it has a scan_state, switch to it
var/obj/item/stack/ore/the_ore = ore_type
scan_state = initial(the_ore.scan_state) // I SAID. SWITCH. TO. IT.
mineralType = ore_type // Everything else assumes that this is typed correctly so don't set it to non-ores thanks.
/turf/closed/mineral/get_smooth_underlay_icon(mutable_appearance/underlay_appearance, turf/asking_turf, adjacency_dir)
if(turf_type)
@@ -48,7 +64,6 @@
/turf/closed/mineral/attackby(obj/item/pickaxe/I, mob/user, params)
var/stored_dir = user.dir
if (!user.IsAdvancedToolUser())
to_chat(usr, "<span class='warning'>You don't have the dexterity to do this!</span>")
return
@@ -69,7 +84,7 @@
if(ismineralturf(src))
if(I.digrange > 0)
for(var/turf/closed/mineral/M in range(user,range))
if(get_dir(user,M)&stored_dir)
if(get_dir(user,M) & user.dir)
M.gets_drilled(user)
dug_tiles += M
to_chat(user, "<span class='notice'>You finish cutting into the rock.</span>")
@@ -79,30 +94,63 @@
else
return attack_hand(user)
/turf/closed/mineral/proc/gets_drilled()
/turf/closed/mineral/attack_hand(mob/user)
if(!weak_turf)
return ..()
var/turf/user_turf = user.loc
if (!isturf(user_turf))
return
if(last_act + MINING_MESSAGE_COOLDOWN > world.time)//prevents message spam
return
last_act = world.time
to_chat(user, "<span class='notice'>You start pulling out pieces of [src] with your hands...</span>")
if(!do_after(user, 15 SECONDS, target = src))
return
if(ismineralturf(src))
to_chat(user, "<span class='notice'>You finish pulling apart [src].</span>")
gets_drilled(user)
/turf/closed/mineral/proc/gets_drilled(user, give_exp = FALSE)
if (mineralType && (mineralAmt > 0))
new mineralType(src, mineralAmt)
SSblackbox.record_feedback("tally", "ore_mined", mineralAmt, mineralType)
// if(ishuman(user))
// var/mob/living/carbon/human/H = user
// if(give_exp)
// if (mineralType && (mineralAmt > 0))
// H.mind.adjust_experience(/datum/skill/mining, initial(mineralType.mine_experience) * mineralAmt)
// else
// H.mind.adjust_experience(/datum/skill/mining, 4)
for(var/obj/effect/temp_visual/mining_overlay/M in src)
qdel(M)
var/flags = NONE
if(defer_change) // TODO: make the defer change var a var for any changeturf flag
flags = CHANGETURF_DEFER_CHANGE
ScrapeAway(null, flags)
var/turf/open/mined = ScrapeAway(null, flags)
addtimer(CALLBACK(src, .proc/AfterChange), 1, TIMER_UNIQUE)
playsound(src, 'sound/effects/break_stone.ogg', 50, 1) //beautiful destruction
playsound(src, 'sound/effects/break_stone.ogg', 50, TRUE) //beautiful destruction
mined.update_visuals()
/turf/closed/mineral/attack_animal(mob/living/simple_animal/user)
/turf/closed/mineral/attack_animal(mob/living/simple_animal/user, list/modifiers)
if((user.environment_smash & ENVIRONMENT_SMASH_WALLS) || (user.environment_smash & ENVIRONMENT_SMASH_RWALLS))
gets_drilled()
gets_drilled(user)
..()
/turf/closed/mineral/attack_alien(mob/living/carbon/alien/M)
to_chat(M, "<span class='notice'>You start digging into the rock...</span>")
playsound(src, 'sound/effects/break_stone.ogg', 50, 1)
if(do_after(M, 40, target = src))
to_chat(M, "<span class='notice'>You tunnel into the rock.</span>")
gets_drilled(M)
/turf/closed/mineral/attack_alien(mob/living/carbon/alien/user, list/modifiers)
to_chat(user, "<span class='notice'>You start digging into the rock...</span>")
playsound(src, 'sound/effects/break_stone.ogg', 50, TRUE)
if(do_after(user, 4 SECONDS, target = src))
to_chat(user, "<span class='notice'>You tunnel into the rock.</span>")
gets_drilled(user)
/turf/closed/mineral/attack_hulk(mob/living/carbon/human/H)
..()
if(do_after(H, 50, target = src))
playsound(src, 'sound/effects/meteorimpact.ogg', 100, TRUE)
H.say(pick(";RAAAAAAAARGH!", ";HNNNNNNNNNGGGGGGH!", ";GWAAAAAAAARRRHHH!", "NNNNNNNNGGGGGGGGHH!", ";AAAAAAARRRGH!" ), forced = "hulk")
gets_drilled(H)
return TRUE
/turf/closed/mineral/Bumped(atom/movable/AM)
..()
@@ -128,72 +176,57 @@
switch(severity)
if(3)
if (prob(75))
gets_drilled(null, 1)
gets_drilled(null, FALSE)
if(2)
if (prob(90))
gets_drilled(null, 1)
gets_drilled(null, FALSE)
if(1)
gets_drilled(null, 1)
gets_drilled(null, FALSE)
return
/turf/closed/mineral/Spread(turf/T)
T.ChangeTurf(type)
/turf/closed/mineral/random
var/list/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 = 2, /turf/closed/mineral/bscrystal = 1)
var/list/mineralSpawnChanceList = list(/obj/item/stack/ore/uranium = 5, /obj/item/stack/ore/diamond = 1, /obj/item/stack/ore/gold = 10,
/obj/item/stack/ore/silver = 12, /obj/item/stack/ore/plasma = 20, /obj/item/stack/ore/iron = 40, /obj/item/stack/ore/titanium = 11,
/turf/closed/mineral/gibtonite = 4, /obj/item/stack/ore/bluespace_crystal = 1)
//Currently, Adamantine won't spawn as it has no uses. -Durandan
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)
if (display_icon_state)
icon_state = display_icon_state
. = ..()
if (prob(mineralChance))
var/path = pickweight(mineralSpawnChanceList)
var/turf/T = ChangeTurf(path,null,CHANGETURF_IGNORE_AIR)
if(ispath(path, /turf))
var/stored_flags = 0
if(flags_1 & NO_RUINS_1)
stored_flags |= NO_RUINS_1
var/turf/T = ChangeTurf(path,null,CHANGETURF_IGNORE_AIR)
T.flags_1 |= stored_flags
if(T && ismineralturf(T))
var/turf/closed/mineral/M = T
M.mineralAmt = rand(1, 5)
M.environment_type = src.environment_type
M.turf_type = src.turf_type
M.baseturfs = src.baseturfs
src = M
M.levelupdate()
T.baseturfs = src.baseturfs
if(ismineralturf(T))
var/turf/closed/mineral/M = T
M.turf_type = src.turf_type
M.mineralAmt = rand(1, 5)
M.environment_type = src.environment_type
src = M
M.levelupdate()
else
src = T
T.levelupdate()
/turf/closed/mineral/random/no_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/closed/mineral/bscrystal = 1)
/turf/closed/mineral/random/no_caves/earth_like
icon_state = "rock_oxy"
turf_type = /turf/open/floor/plating/asteroid
baseturfs = /turf/open/floor/plating/asteroid
mineralSpawnChanceList = list(/turf/closed/mineral/uranium/earth_like = 5, /turf/closed/mineral/diamond/earth_like = 1, /turf/closed/mineral/gold/earth_like = 10,
/turf/closed/mineral/silver/earth_like = 12, /turf/closed/mineral/plasma/earth_like = 20, /turf/closed/mineral/iron/earth_like = 40,
/turf/closed/mineral/titanium/earth_like = 11, /turf/closed/mineral/gibtonite/earth_like = 4, /turf/closed/mineral/bscrystal/earth_like = 1)
initial_gas_mix = OPENTURF_DEFAULT_ATMOS
defer_change = TRUE
else
Change_Ore(path, 1)
Spread_Vein(path)
/turf/closed/mineral/random/high_chance
icon_state = "rock_highchance"
mineralChance = 25
mineralSpawnChanceList = list(
/turf/closed/mineral/uranium = 35, /turf/closed/mineral/diamond = 30, /turf/closed/mineral/gold = 45, /turf/closed/mineral/titanium = 45,
/turf/closed/mineral/silver = 50, /turf/closed/mineral/plasma = 50, /turf/closed/mineral/bscrystal = 20)
/obj/item/stack/ore/uranium = 35, /obj/item/stack/ore/diamond = 30, /obj/item/stack/ore/gold = 45, /obj/item/stack/ore/titanium = 45,
/obj/item/stack/ore/silver = 50, /obj/item/stack/ore/plasma = 50, /obj/item/stack/ore/bluespace_crystal = 20)
/turf/closed/mineral/random/high_chance/volcanic
environment_type = "basalt"
@@ -202,55 +235,16 @@
initial_gas_mix = LAVALAND_DEFAULT_ATMOS
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
baseturfs = /turf/open/floor/plating/asteroid
mineralSpawnChanceList = list(
/turf/closed/mineral/uranium/earth_like = 35, /turf/closed/mineral/diamond/earth_like = 30, /turf/closed/mineral/gold/earth_like = 45,
/turf/closed/mineral/titanium/earth_like = 45, /turf/closed/mineral/silver/earth_like = 50, /turf/closed/mineral/plasma/earth_like = 50,
/turf/closed/mineral/bscrystal/earth_like = 20)
initial_gas_mix = OPENTURF_DEFAULT_ATMOS
defer_change = TRUE
/obj/item/stack/ore/uranium = 35, /obj/item/stack/ore/diamond = 30, /obj/item/stack/ore/gold = 45, /obj/item/stack/ore/titanium = 45,
/obj/item/stack/ore/silver = 50, /obj/item/stack/ore/plasma = 50, /obj/item/stack/ore/bluespace_crystal)
/turf/closed/mineral/random/low_chance
icon_state = "rock_lowchance"
mineralChance = 6
mineralSpawnChanceList = list(
/turf/closed/mineral/uranium = 2, /turf/closed/mineral/diamond = 1, /turf/closed/mineral/gold = 4, /turf/closed/mineral/titanium = 4,
/turf/closed/mineral/silver = 6, /turf/closed/mineral/plasma = 15, /turf/closed/mineral/iron = 40,
/turf/closed/mineral/gibtonite = 2, /turf/closed/mineral/bscrystal = 1)
/turf/closed/mineral/random/low_chance/earth_like
icon_state = "rock_lowchance_oxy"
turf_type = /turf/open/floor/plating/asteroid
baseturfs = /turf/open/floor/plating/asteroid
initial_gas_mix = OPENTURF_DEFAULT_ATMOS
mineralSpawnChanceList = list(
/turf/closed/mineral/uranium/earth_like = 2, /turf/closed/mineral/diamond/earth_like = 1, /turf/closed/mineral/gold/earth_like = 4,
/turf/closed/mineral/titanium/earth_like = 4, /turf/closed/mineral/silver/earth_like = 6, /turf/closed/mineral/plasma/earth_like = 15,
/turf/closed/mineral/iron/earth_like = 40, /turf/closed/mineral/gibtonite/earth_like = 2, /turf/closed/mineral/bscrystal/earth_like = 1)
defer_change = TRUE
/obj/item/stack/ore/uranium = 2, /obj/item/stack/ore/diamond = 1, /obj/item/stack/ore/gold = 4, /obj/item/stack/ore/titanium = 4,
/obj/item/stack/ore/silver = 6, /obj/item/stack/ore/plasma = 15, /obj/item/stack/ore/iron = 40,
/turf/closed/mineral/gibtonite = 2, /obj/item/stack/ore/bluespace_crystal = 1)
/turf/closed/mineral/random/volcanic
environment_type = "basalt"
@@ -261,15 +255,9 @@
mineralChance = 10
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 = 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)
/obj/item/stack/ore/uranium = 5, /obj/item/stack/ore/diamond = 1, /obj/item/stack/ore/gold = 10, /obj/item/stack/ore/titanium = 11,
/obj/item/stack/ore/silver = 12, /obj/item/stack/ore/plasma = 20, /obj/item/stack/ore/iron = 40,
/turf/closed/mineral/gibtonite/volcanic = 4, /obj/item/stack/ore/bluespace_crystal = 1)
/turf/closed/mineral/random/snow
name = "snowy mountainside"
@@ -283,38 +271,43 @@
turf_type = /turf/open/floor/plating/asteroid/snow/icemoon
baseturfs = /turf/open/floor/plating/asteroid/snow/icemoon
initial_gas_mix = ICEMOON_DEFAULT_ATMOS
weak_turf = TRUE
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/Change_Ore(ore_type, random = 0)
. = ..()
if(mineralType)
smooth_icon = 'icons/turf/walls/icerock_wall.dmi'
icon = 'icons/turf/walls/icerock_wall.dmi'
icon_state = "icerock_wall-0"
// base_icon_state = "icerock_wall"
smooth = SMOOTH_MORE|SMOOTH_BORDER
/turf/closed/mineral/random/snow/no_caves
/turf/closed/mineral/random/snow
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(
/turf/closed/mineral/uranium = 3, /turf/closed/mineral/diamond = 1, /turf/closed/mineral/gold = 8, /turf/closed/mineral/titanium = 8,
/turf/closed/mineral/silver = 20, /turf/closed/mineral/plasma = 30, /turf/closed/mineral/iron = 95,
/turf/closed/mineral/gibtonite = 2)
icon_state = "rock_labor"
/obj/item/stack/ore/uranium = 5, /obj/item/stack/ore/diamond = 1, /obj/item/stack/ore/gold = 10, /obj/item/stack/ore/titanium = 11,
/obj/item/stack/ore/silver = 12, /obj/item/stack/ore/plasma = 20, /obj/item/stack/ore/iron = 40,
/turf/closed/mineral/gibtonite/ice/icemoon = 4, /obj/item/stack/ore/bluespace_crystal = 1)
/turf/closed/mineral/random/snow/underground
baseturfs = /turf/open/floor/plating/asteroid/snow/icemoon
// abundant ore
mineralChance = 20
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)
/obj/item/stack/ore/uranium = 10, /obj/item/stack/ore/diamond = 4, /obj/item/stack/ore/gold = 20, /obj/item/stack/ore/titanium = 22,
/obj/item/stack/ore/silver = 24, /obj/item/stack/ore/plasma = 20, /obj/item/stack/ore/iron = 20, /obj/item/stack/ore/bananium = 1,
/turf/closed/mineral/gibtonite/ice/icemoon = 8, /obj/item/stack/ore/bluespace_crystal = 2)
/turf/closed/mineral/random/snow/more_caves
/turf/closed/mineral/random/snow/high_chance
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)
/obj/item/stack/ore/uranium = 35, /obj/item/stack/ore/diamond = 30, /obj/item/stack/ore/gold = 45, /obj/item/stack/ore/titanium = 45,
/obj/item/stack/ore/silver = 50, /obj/item/stack/ore/plasma = 50, /obj/item/stack/ore/bluespace_crystal = 20)
/turf/closed/mineral/random/labormineral
icon_state = "rock_labor"
mineralSpawnChanceList = list(
/obj/item/stack/ore/uranium = 3, /obj/item/stack/ore/diamond = 1, /obj/item/stack/ore/gold = 8, /obj/item/stack/ore/titanium = 8,
/obj/item/stack/ore/silver = 20, /obj/item/stack/ore/plasma = 30, /obj/item/stack/ore/iron = 95,
/turf/closed/mineral/gibtonite = 2)
/turf/closed/mineral/random/labormineral/volcanic
environment_type = "basalt"
@@ -323,16 +316,17 @@
initial_gas_mix = LAVALAND_DEFAULT_ATMOS
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)
/obj/item/stack/ore/uranium = 3, /obj/item/stack/ore/diamond = 1, /obj/item/stack/ore/gold = 8, /obj/item/stack/ore/titanium = 8,
/obj/item/stack/ore/silver = 20, /obj/item/stack/ore/plasma = 30, /obj/item/stack/ore/bluespace_crystal = 1, /turf/closed/mineral/gibtonite/volcanic = 2,
/obj/item/stack/ore/iron = 95)
//Subtypes for placing ores manually.
// Subtypes for mappers 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"
// base_icon_state = "mountain_wall"
smooth = SMOOTH_MORE|SMOOTH_BORDER
canSmoothWith = list (/turf/closed)
defer_change = TRUE
@@ -340,124 +334,57 @@
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)
/obj/item/stack/ore/uranium = 3, /obj/item/stack/ore/diamond = 1, /obj/item/stack/ore/gold = 8, /obj/item/stack/ore/titanium = 8,
/obj/item/stack/ore/silver = 20, /obj/item/stack/ore/plasma = 30, /obj/item/stack/ore/bluespace_crystal = 1, /turf/closed/mineral/gibtonite/volcanic = 2,
/obj/item/stack/ore/iron = 95)
/turf/closed/mineral/random/labormineral/ice/Change_Ore(ore_type, random = 0)
. = ..()
if(mineralType)
smooth_icon = 'icons/turf/walls/icerock_wall.dmi'
icon = 'icons/turf/walls/icerock_wall.dmi'
icon_state = "icerock_wall-0"
// base_icon_state = "icerock_wall"
smooth = SMOOTH_MORE|SMOOTH_BORDER
/turf/closed/mineral/iron
mineralType = /obj/item/stack/ore/iron
spreadChance = 20
spread = 1
scan_state = "rock_Iron"
/turf/closed/mineral/iron/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
/turf/closed/mineral/iron/earth_like
icon_state = "rock_oxy"
turf_type = /turf/open/floor/plating/asteroid
baseturfs = /turf/open/floor/plating/asteroid
initial_gas_mix = OPENTURF_DEFAULT_ATMOS
defer_change = TRUE
/turf/closed/mineral/iron/ice
environment_type = "snow_cavern"
icon_state = "icerock_iron"
smooth_icon = 'icons/turf/walls/icerock_wall.dmi'
// base_icon_state = "icerock_wall"
// smoothing_flags = SMOOTH_BITMASK | SMOOTH_BORDER
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/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
spreadChance = 5
spread = 1
scan_state = "rock_Uranium"
/turf/closed/mineral/uranium/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 = 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"
turf_type = /turf/open/floor/plating/asteroid
baseturfs = /turf/open/floor/plating/asteroid
initial_gas_mix = OPENTURF_DEFAULT_ATMOS
defer_change = TRUE
/turf/closed/mineral/diamond
mineralType = /obj/item/stack/ore/diamond
spreadChance = 0
spread = 1
scan_state = "rock_Diamond"
/turf/closed/mineral/diamond/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 = TRUE
/turf/closed/mineral/diamond/earth_like
icon_state = "rock_oxy"
turf_type = /turf/open/floor/plating/asteroid
baseturfs = /turf/open/floor/plating/asteroid
initial_gas_mix = OPENTURF_DEFAULT_ATMOS
defer_change = TRUE
/turf/closed/mineral/diamond/ice
environment_type = "snow_cavern"
icon_state = "icerock_diamond"
smooth_icon = 'icons/turf/walls/icerock_wall.dmi'
// base_icon_state = "icerock_wall"
// smoothing_flags = SMOOTH_BITMASK | SMOOTH_BORDER
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/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
spreadChance = 5
spread = 1
scan_state = "rock_Gold"
/turf/closed/mineral/gold/volcanic
@@ -467,56 +394,10 @@
initial_gas_mix = LAVALAND_DEFAULT_ATMOS
defer_change = TRUE
/turf/closed/mineral/gold/earth_like
icon_state = "rock_oxy"
turf_type = /turf/open/floor/plating/asteroid
baseturfs = /turf/open/floor/plating/asteroid
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
spreadChance = 5
spread = 1
scan_state = "rock_Silver"
/turf/closed/mineral/silver/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 = TRUE
/turf/closed/mineral/silver/earth_like
icon_state = "rock_oxy"
turf_type = /turf/open/floor/plating/asteroid
baseturfs = /turf/open/floor/plating/asteroid
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
@@ -524,107 +405,31 @@
/turf/closed/mineral/titanium
mineralType = /obj/item/stack/ore/titanium
spreadChance = 5
spread = 1
scan_state = "rock_Titanium"
/turf/closed/mineral/titanium/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 = TRUE
/turf/closed/mineral/titanium/earth_like
icon_state = "rock_oxy"
turf_type = /turf/open/floor/plating/asteroid
baseturfs = /turf/open/floor/plating/asteroid
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
spreadChance = 8
spread = 1
scan_state = "rock_Plasma"
/turf/closed/mineral/plasma/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 = TRUE
/turf/closed/mineral/plasma/earth_like
icon_state = "rock_oxy"
turf_type = /turf/open/floor/plating/asteroid
baseturfs = /turf/open/floor/plating/asteroid
initial_gas_mix = OPENTURF_DEFAULT_ATMOS
defer_change = TRUE
/turf/closed/mineral/plasma/ice
environment_type = "snow_cavern"
icon_state = "icerock_plasma"
smooth_icon = 'icons/turf/walls/icerock_wall.dmi'
// base_icon_state = "icerock_wall"
// smoothing_flags = SMOOTH_BITMASK | SMOOTH_BORDER
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/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
mineralType = /obj/item/stack/ore/bananium
mineralAmt = 3
spreadChance = 0
spread = 0
scan_state = "rock_Bananium"
/turf/closed/mineral/bananium/earth_like
icon_state = "rock_oxy"
turf_type = /turf/open/floor/plating/asteroid
baseturfs = /turf/open/floor/plating/asteroid
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
spreadChance = 0
spread = 0
scan_state = "rock_BScrystal"
/turf/closed/mineral/bscrystal/volcanic
@@ -634,27 +439,6 @@
initial_gas_mix = LAVALAND_DEFAULT_ATMOS
defer_change = TRUE
/turf/closed/mineral/bscrystal/earth_like
icon_state = "rock_oxy"
turf_type = /turf/open/floor/plating/asteroid
baseturfs = /turf/open/floor/plating/asteroid
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"
turf_type = /turf/open/floor/plating/asteroid/basalt
@@ -667,18 +451,12 @@
baseturfs = /turf/open/floor/plating/asteroid/basalt/lava_land_surface
defer_change = TRUE
/turf/closed/mineral/earth_like
icon_state = "rock_oxy"
turf_type = /turf/open/floor/plating/asteroid
baseturfs = /turf/open/floor/plating/asteroid
initial_gas_mix = OPENTURF_DEFAULT_ATMOS
defer_change = TRUE
/turf/closed/mineral/ash_rock //wall piece
name = "rock"
icon = 'icons/turf/mining.dmi'
smooth_icon = 'icons/turf/walls/rock_wall.dmi'
icon_state = "rock2"
// base_icon_state = "rock_wall"
smooth = SMOOTH_MORE|SMOOTH_BORDER
canSmoothWith = list (/turf/closed)
baseturfs = /turf/open/floor/plating/ashplanet/wateryrock
@@ -692,6 +470,7 @@
icon = 'icons/turf/mining.dmi'
smooth_icon = 'icons/turf/walls/mountain_wall.dmi'
icon_state = "mountainrock"
// base_icon_state = "mountain_wall"
smooth = SMOOTH_MORE|SMOOTH_BORDER
canSmoothWith = list (/turf/closed)
baseturfs = /turf/open/floor/plating/asteroid/snow
@@ -710,6 +489,7 @@
icon = 'icons/turf/mining.dmi'
smooth_icon = 'icons/turf/walls/icerock_wall.dmi'
icon_state = "icerock"
// base_icon_state = "icerock_wall"
smooth = SMOOTH_MORE|SMOOTH_BORDER
canSmoothWith = list (/turf/closed)
baseturfs = /turf/open/floor/plating/asteroid/snow/ice
@@ -725,8 +505,6 @@
/turf/closed/mineral/gibtonite
mineralAmt = 1
spreadChance = 0
spread = 0
scan_state = "rock_Gibtonite"
var/det_time = 8 //Countdown till explosion, but also rewards the player for how close you were to detonation when you defuse it
var/stage = GIBTONITE_UNSTRUCK //How far into the lifecycle of gibtonite we are
@@ -746,21 +524,15 @@
/turf/closed/mineral/gibtonite/proc/explosive_reaction(mob/user = null, triggered_by_explosion = 0)
if(stage == GIBTONITE_UNSTRUCK)
activated_overlay = mutable_appearance('icons/turf/smoothrocks.dmi', "rock_Gibtonite_active", ON_EDGED_TURF_LAYER)
activated_overlay = mutable_appearance('icons/turf/smoothrocks.dmi', "rock_Gibtonite_inactive", ON_EDGED_TURF_LAYER) //shows in gaps between pulses if there are any
add_overlay(activated_overlay)
name = "gibtonite deposit"
desc = "An active gibtonite reserve. Run!"
stage = GIBTONITE_ACTIVE
visible_message("<span class='danger'>There was gibtonite inside! It's going to explode!</span>")
var/turf/bombturf = get_turf(src)
visible_message("<span class='danger'>There's gibtonite inside! It's going to explode!</span>")
var/notify_admins = 0
if(z != 5)
notify_admins = 1
if(!triggered_by_explosion)
message_admins("[ADMIN_LOOKUPFLW(user)] has triggered a gibtonite deposit reaction at [ADMIN_VERBOSEJMP(bombturf)].")
else
message_admins("An explosion has triggered a gibtonite deposit reaction at [ADMIN_VERBOSEJMP(bombturf)].")
var/turf/bombturf = get_turf(src)
var/notify_admins = !is_mining_level(z)
if(!triggered_by_explosion)
log_game("[key_name(user)] has triggered a gibtonite deposit reaction at [AREACOORD(bombturf)].")
@@ -769,9 +541,10 @@
countdown(notify_admins)
/turf/closed/mineral/gibtonite/proc/countdown(notify_admins = 0)
set waitfor = 0
/turf/closed/mineral/gibtonite/proc/countdown(notify_admins = FALSE)
set waitfor = FALSE
while(istype(src, /turf/closed/mineral/gibtonite) && stage == GIBTONITE_ACTIVE && det_time > 0 && mineralAmt >= 1)
flick_overlay_view(image('icons/turf/smoothrocks.dmi', src, "rock_Gibtonite_active"), src, 5) //makes the animation pulse one time per tick
det_time--
sleep(5)
if(istype(src, /turf/closed/mineral/gibtonite))
@@ -790,18 +563,18 @@
stage = GIBTONITE_STABLE
if(det_time < 0)
det_time = 0
visible_message("<span class='notice'>The chain reaction was stopped! The gibtonite had [det_time] reactions left till the explosion!</span>")
visible_message("<span class='notice'>The chain reaction stopped! The gibtonite had [det_time] reactions left till the explosion!</span>")
/turf/closed/mineral/gibtonite/gets_drilled(mob/user, triggered_by_explosion = 0)
/turf/closed/mineral/gibtonite/gets_drilled(mob/user, triggered_by_explosion = FALSE)
if(stage == GIBTONITE_UNSTRUCK && mineralAmt >= 1) //Gibtonite deposit is activated
playsound(src,'sound/effects/hit_on_shattered_glass.ogg',50,1)
playsound(src,'sound/effects/hit_on_shattered_glass.ogg',50,TRUE)
explosive_reaction(user, triggered_by_explosion)
return
if(stage == GIBTONITE_ACTIVE && mineralAmt >= 1) //Gibtonite deposit goes kaboom
var/turf/bombturf = get_turf(src)
mineralAmt = 0
stage = GIBTONITE_DETONATE
explosion(bombturf,1,2,5, adminlog = 0)
explosion(bombturf,1,2,5, adminlog = FALSE)
if(stage == GIBTONITE_STABLE) //Gibtonite deposit is now benign and extractable. Depending on how close you were to it blowing up before defusing, you get better quality ore.
var/obj/item/gibtonite/G = new (src)
if(det_time <= 0)
@@ -825,18 +598,12 @@
initial_gas_mix = LAVALAND_DEFAULT_ATMOS
defer_change = TRUE
/turf/closed/mineral/gibtonite/earth_like
icon_state = "rock_oxy"
turf_type = /turf/open/floor/plating/asteroid
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'
// base_icon_state = "icerock_wall"
// smoothing_flags = SMOOTH_BITMASK | SMOOTH_BORDER
turf_type = /turf/open/floor/plating/asteroid/snow/ice
baseturfs = /turf/open/floor/plating/asteroid/snow/ice
initial_gas_mix = FROZEN_ATMOS
@@ -856,18 +623,18 @@
initial_gas_mix = LAVALAND_DEFAULT_ATMOS
defer_change = 1
smooth_icon = 'icons/turf/walls/rock_wall.dmi'
// base_icon_state = "rock_wall"
// smoothing_flags = SMOOTH_BITMASK | SMOOTH_BORDER
// /turf/closed/mineral/strong/attackby(obj/item/I, mob/user, params)
// if(!ishuman(user))
// to_chat(usr, "<span class='warning'>Only a more advanced species could break a rock such as this one!</span>")
// return FALSE
// if(user.mind?.get_skill_level(/datum/skill/mining) >= SKILL_LEVEL_MASTER)
// . = ..()
// else
// to_chat(usr, "<span class='warning'>The rock seems to be too strong to destroy. Maybe I can break it once I become a master miner.</span>")
/*
/turf/closed/mineral/strong/attackby(obj/item/I, mob/user, params)
if(!ishuman(user))
to_chat(usr, "<span class='warning'>Only a more advanced species could break a rock such as this one!</span>")
return FALSE
var/mob/living/carbon/human/H = user
if(H.mind.get_skill_level(/datum/skill/mining) >= SKILL_LEVEL_MASTER)
. = ..()
else
to_chat(usr, "<span class='warning'>The rock seems to be too strong to destroy. Maybe I can break it once I become a master miner.</span>")
*/
/turf/closed/mineral/strong/gets_drilled(mob/user)
if(!ishuman(user))
@@ -896,3 +663,5 @@
/turf/closed/mineral/strong/ex_act(severity, target)
return
#undef MINING_MESSAGE_COOLDOWN
@@ -1,39 +1,40 @@
GLOBAL_DATUM_INIT(openspace_backdrop_one_for_all, /atom/movable/openspace_backdrop, new)
/atom/movable/openspace_backdrop
name = "openspace_backdrop"
name = "openspace_backdrop"
anchored = TRUE
anchored = TRUE
icon = 'icons/turf/floors.dmi'
icon_state = "grey"
plane = OPENSPACE_BACKDROP_PLANE
mouse_opacity = MOUSE_OPACITY_TRANSPARENT
mouse_opacity = MOUSE_OPACITY_TRANSPARENT
layer = SPLASHSCREEN_LAYER
//I don't know why the others are aligned but I shall do the same.
vis_flags = VIS_INHERIT_ID
vis_flags = VIS_INHERIT_ID
/turf/open/transparent/openspace
/turf/open/openspace
name = "open space"
desc = "Watch your step!"
icon_state = "transparent"
baseturfs = /turf/open/transparent/openspace
baseturfs = /turf/open/openspace
CanAtmosPassVertical = ATMOS_PASS_YES
baseturfs = /turf/open/openspace
intact = FALSE //this means wires go on top
//mouse_opacity = MOUSE_OPACITY_TRANSPARENT
mouse_opacity = MOUSE_OPACITY_TRANSPARENT
var/can_cover_up = TRUE
var/can_build_on = TRUE
/turf/open/transparent/openspace/airless
/turf/open/openspace/airless
initial_gas_mix = AIRLESS_ATMOS
/turf/open/transparent/openspace/debug/update_multiz()
..()
return TRUE
// /turf/open/transparent/openspace/debug/update_multiz()
// ..()
// return TRUE
///No bottom level for openspace.
/turf/open/transparent/openspace/show_bottom_level()
return FALSE
// ///No bottom level for openspace.
// /turf/open/transparent/openspace/show_bottom_level()
// return FALSE
/turf/open/openspace/Initialize() // handle plane and layer here so that they don't cover other obs/turfs in Dream Maker
. = ..()
@@ -42,20 +43,20 @@ GLOBAL_DATUM_INIT(openspace_backdrop_one_for_all, /atom/movable/openspace_backdr
/turf/open/openspace/LateInitialize()
. = ..()
// AddElement(/datum/element/turf_z_transparency, FALSE)
AddElement(/datum/element/turf_z_transparency, FALSE)
/turf/open/transparent/openspace/can_have_cabling()
/turf/open/openspace/can_have_cabling()
if(locate(/obj/structure/lattice/catwalk, src))
return TRUE
return FALSE
/turf/open/transparent/openspace/zAirIn()
/turf/open/openspace/zAirIn()
return TRUE
/turf/open/transparent/openspace/zAirOut()
/turf/open/openspace/zAirOut()
return TRUE
/turf/open/transparent/openspace/zPassIn(atom/movable/A, direction, turf/source)
/turf/open/openspace/zPassIn(atom/movable/A, direction, turf/source)
if(direction == DOWN)
for(var/obj/O in contents)
if(O.obj_flags & BLOCK_Z_IN_DOWN)
@@ -68,7 +69,7 @@ GLOBAL_DATUM_INIT(openspace_backdrop_one_for_all, /atom/movable/openspace_backdr
return TRUE
return FALSE
/turf/open/transparent/openspace/zPassOut(atom/movable/A, direction, turf/destination)
/turf/open/openspace/zPassOut(atom/movable/A, direction, turf/destination)
if(A.anchored)
return FALSE
if(direction == DOWN)
@@ -83,13 +84,13 @@ GLOBAL_DATUM_INIT(openspace_backdrop_one_for_all, /atom/movable/openspace_backdr
return TRUE
return FALSE
/turf/open/transparent/openspace/proc/CanCoverUp()
/turf/open/openspace/proc/CanCoverUp()
return can_cover_up
/turf/open/transparent/openspace/proc/CanBuildHere()
/turf/open/openspace/proc/CanBuildHere()
return can_build_on
/turf/open/transparent/openspace/attackby(obj/item/C, mob/user, params)
/turf/open/openspace/attackby(obj/item/C, mob/user, params)
..()
if(!CanBuildHere())
return
@@ -130,9 +131,9 @@ GLOBAL_DATUM_INIT(openspace_backdrop_one_for_all, /atom/movable/openspace_backdr
else
to_chat(user, "<span class='warning'>You need one floor tile to build a floor!</span>")
else
to_chat(user, "<span class='warning'>The plating is going to need some support! Place metal rods first.</span>")
to_chat(user, "<span class='warning'>The plating is going to need some support! Place iron rods first.</span>")
/turf/open/transparent/openspace/rcd_vals(mob/user, obj/item/construction/rcd/the_rcd)
/turf/open/openspace/rcd_vals(mob/user, obj/item/construction/rcd/the_rcd)
if(!CanBuildHere())
return FALSE
@@ -145,7 +146,7 @@ GLOBAL_DATUM_INIT(openspace_backdrop_one_for_all, /atom/movable/openspace_backdr
return list("mode" = RCD_FLOORWALL, "delay" = 0, "cost" = 3)
return FALSE
/turf/open/transparent/openspace/rcd_act(mob/user, obj/item/construction/rcd/the_rcd, passed_mode)
/turf/open/openspace/rcd_act(mob/user, obj/item/construction/rcd/the_rcd, passed_mode)
switch(passed_mode)
if(RCD_FLOORWALL)
to_chat(user, "<span class='notice'>You build a floor.</span>")
@@ -153,25 +154,33 @@ GLOBAL_DATUM_INIT(openspace_backdrop_one_for_all, /atom/movable/openspace_backdr
return TRUE
return FALSE
/turf/open/transparent/openspace/icemoon
/turf/open/openspace/icemoon
name = "ice chasm"
baseturfs = /turf/open/transparent/openspace/icemoon
baseturfs = /turf/open/openspace/icemoon
initial_gas_mix = ICEMOON_DEFAULT_ATMOS
planetary_atmos = TRUE
var/replacement_turf = /turf/open/floor/plating/asteroid/snow/icemoon
/// Replaces itself with replacement_turf if the turf below this one is in a no ruins allowed area (usually ruins themselves)
var/protect_ruin = TRUE
/// If true mineral turfs below this openspace turf will be mined automatically
var/drill_below = TRUE
/turf/open/transparent/openspace/icemoon/Initialize()
/turf/open/openspace/icemoon/Initialize()
. = ..()
var/turf/T = below()
// if(T.flags_1 & NO_RUINS_1)
// ChangeTurf(replacement_turf, null, CHANGETURF_IGNORE_AIR)
// return
// if(!ismineralturf(T))
// return
if(T.flags_1 & NO_RUINS_1 && protect_ruin)
ChangeTurf(replacement_turf, null, CHANGETURF_IGNORE_AIR)
return
if(!ismineralturf(T) || !drill_below)
return
var/turf/closed/mineral/M = T
M.mineralAmt = 0
M.gets_drilled()
baseturfs = /turf/open/transparent/openspace/icemoon //This is to ensure that IF random turf generation produces a openturf, there won't be other turfs assigned other than openspace.
baseturfs = /turf/open/openspace/icemoon //This is to ensure that IF random turf generation produces a openturf, there won't be other turfs assigned other than openspace.
/turf/open/transparent/openspace/icemoon/can_zFall(atom/movable/A, levels = 1, turf/target)
return TRUE
/turf/open/openspace/icemoon/keep_below
drill_below = FALSE
/turf/open/openspace/icemoon/ruins
protect_ruin = FALSE
drill_below = FALSE
+6 -2
View File
@@ -58,8 +58,8 @@
set waitfor = FALSE
if(!AM || istype(AM, /obj/docking_port))
return
if(AM.loc != src) // Multi-tile objects are "in" multiple locs but its loc is it's true placement.
return // Don't move multi tile objects if their origin isnt in transit
if(AM.loc != src) // Multi-tile objects are "in" multiple locs but its loc is it's true placement.
return // Don't move multi tile objects if their origin isn't in transit
var/max = world.maxx-TRANSITIONEDGE
var/min = 1+TRANSITIONEDGE
@@ -68,6 +68,10 @@
var/datum/space_level/D = A
if (D.linkage == CROSSLINKED)
possible_transtitons += D.z_value
if(!length(possible_transtitons)) //No space to throw them to - try throwing them onto mining
possible_transtitons = SSmapping.levels_by_trait(ZTRAIT_MINING)
if(!length(possible_transtitons)) //Just throw them back on station, if not just runtime.
possible_transtitons = SSmapping.levels_by_trait(ZTRAIT_STATION)
var/_z = pick(possible_transtitons)
//now select coordinates for a border turf
+1 -1
View File
@@ -131,7 +131,7 @@ GLOBAL_LIST_EMPTY(station_turfs)
user.Move_Pulled(src)
/turf/proc/multiz_turf_del(turf/T, dir)
// SEND_SIGNAL(src, COMSIG_TURF_MULTIZ_DEL, T, dir)
SEND_SIGNAL(src, COMSIG_TURF_MULTIZ_DEL, T, dir)
/turf/proc/multiz_turf_new(turf/T, dir)
SEND_SIGNAL(src, COMSIG_TURF_MULTIZ_NEW, T, dir)