Merge remote-tracking branch 'upstream/master' into motivation

This commit is contained in:
keronshb
2021-04-14 17:55:24 -04:00
1616 changed files with 351906 additions and 333939 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
+55 -9
View File
@@ -99,6 +99,9 @@
///Mobs that are currently do_after'ing this atom, to be cleared from on Destroy()
var/list/targeted_by
///Reference to atom being orbited
var/atom/orbit_target
/**
* Called when an atom is created in byond (built in engine proc)
*
@@ -882,6 +885,9 @@
VV_DROPDOWN_OPTION(VV_HK_ADD_REAGENT, "Add Reagent")
VV_DROPDOWN_OPTION(VV_HK_TRIGGER_EMP, "EMP Pulse")
VV_DROPDOWN_OPTION(VV_HK_TRIGGER_EXPLOSION, "Explosion")
// VV_DROPDOWN_OPTION(VV_HK_RADIATE, "Radiate")
VV_DROPDOWN_OPTION(VV_HK_EDIT_FILTERS, "Edit Filters")
// VV_DROPDOWN_OPTION(VV_HK_ADD_AI, "Add AI controller")
/atom/vv_do_topic(list/href_list)
. = ..()
@@ -925,6 +931,9 @@
var/newname = input(usr, "What do you want to rename this to?", "Automatic Rename") as null|text
if(newname)
vv_auto_rename(newname)
if(href_list[VV_HK_EDIT_FILTERS] && check_rights(R_VAREDIT))
var/client/C = usr.client
C?.open_filter_editor(src)
/atom/vv_get_header()
. = ..()
@@ -983,7 +992,7 @@
return
/atom/proc/multitool_check_buffer(user, obj/item/I, silent = FALSE)
if(!istype(I, /obj/item/multitool))
if(!I.tool_behaviour == TOOL_MULTITOOL)
if(user && !silent)
to_chat(user, "<span class='warning'>[I] has no data buffer!</span>")
return FALSE
@@ -1145,7 +1154,6 @@
victim.log_message(message, LOG_ATTACK, color="blue")
// Filter stuff
/atom/proc/add_filter(name,priority,list/params)
LAZYINITLIST(filter_data)
var/list/p = params.Copy()
@@ -1161,26 +1169,64 @@
var/list/arguments = data.Copy()
arguments -= "priority"
filters += filter(arglist(arguments))
UNSETEMPTY(filter_data)
/atom/proc/transition_filter(name, time, list/new_params, easing, loop)
var/filter = get_filter(name)
if(!filter)
return
var/list/old_filter_data = filter_data[name]
var/list/params = old_filter_data.Copy()
for(var/thing in new_params)
params[thing] = new_params[thing]
animate(filter, new_params, time = time, easing = easing, loop = loop)
for(var/param in params)
filter_data[name][param] = params[param]
/atom/proc/change_filter_priority(name, new_priority)
if(!filter_data || !filter_data[name])
return
filter_data[name]["priority"] = new_priority
update_filters()
/obj/item/update_filters()
. = ..()
for(var/X in actions)
var/datum/action/A = X
A.UpdateButtonIcon()
/atom/proc/get_filter(name)
if(filter_data && filter_data[name])
return filters[filter_data.Find(name)]
/atom/proc/remove_filter(name)
if(filter_data && filter_data[name])
filter_data -= name
update_filters()
return TRUE
/atom/proc/remove_filter(name_or_names)
if(!filter_data)
return
var/list/names = islist(name_or_names) ? name_or_names : list(name_or_names)
for(var/name in names)
if(filter_data[name])
filter_data -= name
update_filters()
/atom/proc/clear_filters()
filter_data = null
filters = null
/atom/proc/intercept_zImpact(atom/movable/AM, levels = 1)
. |= SEND_SIGNAL(src, COMSIG_ATOM_INTERCEPT_Z_FALL, AM, levels)
///Sets the custom materials for an item.
/atom/proc/set_custom_materials(var/list/materials, multiplier = 1)
/atom/proc/set_custom_materials(list/materials, multiplier = 1)
if(custom_materials) //Only runs if custom materials existed at first. Should usually be the case but check anyways
for(var/i in custom_materials)
var/datum/material/custom_material = SSmaterials.GetMaterialRef(i)
custom_material.on_removed(src, material_flags) //Remove the current materials
custom_material.on_removed(src, custom_materials[i], material_flags) //Remove the current materials
if(!length(materials))
custom_materials = null
+1
View File
@@ -331,6 +331,7 @@
return
. = anchored
anchored = anchorvalue
SEND_SIGNAL(src, COMSIG_OBJ_SETANCHORED, anchorvalue)
// SEND_SIGNAL(src, COMSIG_MOVABLE_SET_ANCHORED, anchorvalue)
/atom/movable/proc/throw_impact(atom/hit_atom, datum/thrownthing/throwingdatum)
@@ -24,6 +24,7 @@
traitor_name = "Bloodsucker"
antag_flag = ROLE_BLOODSUCKER
false_report_weight = 1
chaos = 4
restricted_jobs = list("AI","Cyborg")
protected_jobs = list("Chaplain", "Security Officer", "Warden", "Detective", "Head of Security", "Captain", "Head of Personnel", "Chief Engineer", "Chief Medical Officer", "Research Director", "Quartermaster")
required_players = 20
@@ -87,7 +88,7 @@
// Init Sunlight (called from datum_bloodsucker.on_gain(), in case game mode isn't even Bloodsucker
/datum/game_mode/proc/check_start_sunlight()
// Already Sunlight (and not about to cancel)
if(istype(bloodsucker_sunlight) && !bloodsucker_sunlight.cancel_me)
if(istype(bloodsucker_sunlight))
return
bloodsucker_sunlight = new ()
@@ -97,7 +98,6 @@
if(!istype(bloodsucker_sunlight))
return
if(bloodsuckers.len <= 0)
bloodsucker_sunlight.cancel_me = TRUE
qdel(bloodsucker_sunlight)
bloodsucker_sunlight = null
@@ -6,6 +6,7 @@
name = "traitor+brothers"
config_tag = "traitorbro"
required_players = 25
chaos = 5
restricted_jobs = list("AI", "Cyborg")
protected_jobs = list("Security Officer", "Warden", "Detective", "Head of Security", "Captain", "Head of Personnel", "Chief Engineer", "Chief Medical Officer", "Research Director", "Quartermaster")
@@ -10,6 +10,7 @@ GLOBAL_VAR(changeling_team_objective_type) //If this is not null, we hand our th
config_tag = "changeling"
antag_flag = ROLE_CHANGELING
false_report_weight = 10
chaos = 5
restricted_jobs = list("AI", "Cyborg")
protected_jobs = list("Security Officer", "Warden", "Detective", "Head of Security", "Captain", "Head of Personnel", "Chief Engineer", "Chief Medical Officer", "Research Director", "Quartermaster") //citadel change - adds HoP, CE, CMO, and RD to ling role blacklist
required_players = 15
@@ -2,6 +2,7 @@
name = "traitor+changeling"
config_tag = "traitorchan"
false_report_weight = 10
chaos = 6
traitors_possible = 3 //hard limit on traitors if scaling is turned off
restricted_jobs = list("AI", "Cyborg")
required_players = 25
@@ -134,6 +134,7 @@ Credit where due:
config_tag = "clockwork_cult"
antag_flag = ROLE_SERVANT_OF_RATVAR
false_report_weight = 10
chaos = 8
required_players = 24 //Fixing this directly for now since apparently config machine for forcing modes broke.
required_enemies = 3
recommended_enemies = 5
+1 -1
View File
@@ -1,7 +1,7 @@
/datum/game_mode/nuclear/clown_ops
name = "clown ops"
config_tag = "clownops"
chaos = 8
announce_span = "danger"
announce_text = "Clown empire forces are approaching the station in an attempt to HONK it!\n\
<span class='danger'>Operatives</span>: Secure the nuclear authentication disk and use your bananium fission explosive to HONK the station.\n\
+1
View File
@@ -38,6 +38,7 @@
config_tag = "cult"
antag_flag = ROLE_CULTIST
false_report_weight = 10
chaos = 8
restricted_jobs = list("AI", "Cyborg")
protected_jobs = list("Security Officer", "Warden", "Detective", "Head of Security", "Captain", "Head of Personnel", "Chief Engineer", "Chief Medical Officer", "Research Director", "Quartermaster")
required_players = 30
@@ -1,6 +1,7 @@
/datum/game_mode/devil/devil_agents
name = "Devil Agents"
config_tag = "devil_agents"
chaos = 5
required_players = 25
required_enemies = 3
recommended_enemies = 8
@@ -3,6 +3,7 @@
config_tag = "devil"
antag_flag = ROLE_DEVIL
false_report_weight = 1
chaos = 3
protected_jobs = list("Lawyer", "Curator", "Chaplain", "Head of Security", "Captain", "AI")
required_players = 0
required_enemies = 1
+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)
@@ -106,6 +106,7 @@
for(var/i in 1 to 3)
if(config_tag in saved_dynamic_rules[i])
weight_mult -= (repeated_mode_adjust[i]/100)
weight_mult = max(0,weight_mult)
if(config_tag in costs)
cost = costs[config_tag]
if(config_tag in requirementses)
@@ -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()
@@ -3,6 +3,7 @@
config_tag = "heresy"
antag_flag = ROLE_HERETIC
false_report_weight = 5
chaos = 5
restricted_jobs = list("AI", "Cyborg")
protected_jobs = list("Security Officer", "Warden", "Detective", "Head of Security", "Captain", "Head of Personnel", "Chief Engineer", "Chief Medical Officer", "Research Director", "Quartermaster") //citadel change - adds HoP, CE, CMO, and RD to heretic role blacklist
required_players = 15
+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
View File
@@ -3,6 +3,7 @@
config_tag = "secret_extended"
false_report_weight = 5
required_players = 0
chaos = 0
announce_span = "notice"
announce_text = "Just have fun and enjoy the game!"
+32 -11
View File
@@ -17,6 +17,7 @@
var/config_tag = null
var/votable = 1
var/probability = 0
var/chaos = 5 // 0-9, used for weighting round-to-round
var/false_report_weight = 0 //How often will this show up incorrectly in a centcom report?
var/station_was_nuked = 0 //see nuclearbomb.dm and malfunction.dm
var/nuke_off_station = 0 //Used for tracking where the nuke hit
@@ -81,30 +82,43 @@
///Everyone should now be on the station and have their normal gear. This is the place to give the special roles extra things
/datum/game_mode/proc/post_setup(report) //Gamemodes can override the intercept report. Passing TRUE as the argument will force a report.
//finalize_monster_hunters() Disabled for now
if(!report)
report = !CONFIG_GET(flag/no_intercept_report)
addtimer(CALLBACK(GLOBAL_PROC, .proc/display_roundstart_logout_report), ROUNDSTART_LOGOUT_REPORT_TIME)
if(prob(20)) //CIT CHANGE - adds a 20% chance for the security level to be the opposite of what it normally is
if(prob(20)) //cit-change
flipseclevel = TRUE
// if(CONFIG_GET(flag/reopen_roundstart_suicide_roles))
// var/delay = CONFIG_GET(number/reopen_roundstart_suicide_roles_delay)
// if(delay)
// delay = (delay SECONDS)
// else
// delay = (4 MINUTES) //default to 4 minutes if the delay isn't defined.
// addtimer(CALLBACK(GLOBAL_PROC, .proc/reopen_roundstart_suicide_roles), delay)
if(SSdbcore.Connect())
var/sql
var/list/to_set = list()
var/arguments = list()
if(SSticker.mode)
sql += "game_mode = '[SSticker.mode]'"
to_set += "game_mode = :game_mode"
arguments["game_mode"] = SSticker.mode
if(GLOB.revdata.originmastercommit)
if(sql)
sql += ", "
sql += "commit_hash = '[GLOB.revdata.originmastercommit]'"
if(sql)
var/datum/DBQuery/query_round_game_mode = SSdbcore.NewQuery("UPDATE [format_table_name("round")] SET [sql] WHERE id = [GLOB.round_id]")
to_set += "commit_hash = :commit_hash"
arguments["commit_hash"] = GLOB.revdata.originmastercommit
if(to_set.len)
arguments["round_id"] = GLOB.round_id
var/datum/db_query/query_round_game_mode = SSdbcore.NewQuery(
"UPDATE [format_table_name("round")] SET [to_set.Join(", ")] WHERE id = :round_id",
arguments
)
query_round_game_mode.Execute()
qdel(query_round_game_mode)
if(report)
addtimer(CALLBACK(src, .proc/send_intercept, 0), rand(waittime_l, waittime_h))
generate_station_goals()
gamemode_ready = TRUE
return 1
return TRUE
///Handles late-join antag assignments
@@ -406,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)
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
@@ -610,3 +624,10 @@
/// Mode specific info for ghost game_info
/datum/game_mode/proc/ghost_info()
return
/datum/game_mode/proc/get_chaos()
var/chaos_levels = CONFIG_GET(keyed_list/chaos_level)
if(config_tag in chaos_levels)
return chaos_levels[config_tag]
else
return chaos
+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
+1
View File
@@ -6,6 +6,7 @@ GLOBAL_LIST_EMPTY(gangs)
name = "gang war"
config_tag = "gang"
antag_flag = ROLE_GANG
chaos = 9
restricted_jobs = list("AI", "Cyborg")
protected_jobs = list("Security Officer", "Warden", "Detective", "Head of Security", "Captain", "Head of Personnel", "Chief Engineer", "Chief Medical Officer", "Research Director", "Quartermaster")
required_players = 15
+1
View File
@@ -2,6 +2,7 @@
name = "meteor"
config_tag = "meteor"
false_report_weight = 1
chaos = 9
var/meteordelay = 2000
var/nometeors = 0
var/rampupdelta = 5
+42 -41
View File
@@ -1,4 +1,6 @@
#define DEFAULT_METEOR_LIFETIME 1800
#define MAP_EDGE_PAD 5
GLOBAL_VAR_INIT(meteor_wave_delay, 625) //minimum wait between waves in tenths of seconds
//set to at least 100 unless you want evarr ruining every round
@@ -30,7 +32,7 @@ GLOBAL_LIST_INIT(meteorsC, list(/obj/effect/meteor/dust)) //for space dust event
var/turf/pickedgoal
var/max_i = 10//number of tries to spawn meteor.
while(!isspaceturf(pickedstart))
var/startSide = dir || pick(GLOB.cardinals)
var/startSide = (dir ? dir : pick(GLOB.cardinals))
var/startZ = pick(SSmapping.levels_by_trait(ZTRAIT_STATION))
pickedstart = spaceDebrisStartLoc(startSide, startZ)
pickedgoal = spaceDebrisFinishLoc(startSide, startZ)
@@ -46,17 +48,17 @@ GLOBAL_LIST_INIT(meteorsC, list(/obj/effect/meteor/dust)) //for space dust event
var/startx
switch(startSide)
if(NORTH)
starty = world.maxy-(TRANSITIONEDGE+2)
startx = rand((TRANSITIONEDGE+2), world.maxx-(TRANSITIONEDGE+2))
starty = world.maxy-(TRANSITIONEDGE + MAP_EDGE_PAD)
startx = rand((TRANSITIONEDGE + MAP_EDGE_PAD), world.maxx-(TRANSITIONEDGE + MAP_EDGE_PAD))
if(EAST)
starty = rand((TRANSITIONEDGE+2),world.maxy-(TRANSITIONEDGE+2))
startx = world.maxx-(TRANSITIONEDGE+2)
starty = rand((TRANSITIONEDGE + MAP_EDGE_PAD),world.maxy-(TRANSITIONEDGE + MAP_EDGE_PAD))
startx = world.maxx-(TRANSITIONEDGE + MAP_EDGE_PAD)
if(SOUTH)
starty = (TRANSITIONEDGE+2)
startx = rand((TRANSITIONEDGE+2), world.maxx-(TRANSITIONEDGE+2))
starty = (TRANSITIONEDGE + MAP_EDGE_PAD)
startx = rand((TRANSITIONEDGE + MAP_EDGE_PAD), world.maxx-(TRANSITIONEDGE + MAP_EDGE_PAD))
if(WEST)
starty = rand((TRANSITIONEDGE+2), world.maxy-(TRANSITIONEDGE+2))
startx = (TRANSITIONEDGE+2)
starty = rand((TRANSITIONEDGE + MAP_EDGE_PAD), world.maxy-(TRANSITIONEDGE + MAP_EDGE_PAD))
startx = (TRANSITIONEDGE + MAP_EDGE_PAD)
. = locate(startx, starty, Z)
/proc/spaceDebrisFinishLoc(startSide, Z)
@@ -64,17 +66,17 @@ GLOBAL_LIST_INIT(meteorsC, list(/obj/effect/meteor/dust)) //for space dust event
var/endx
switch(startSide)
if(NORTH)
endy = (TRANSITIONEDGE+1)
endx = rand((TRANSITIONEDGE+1), world.maxx-(TRANSITIONEDGE+1))
endy = (TRANSITIONEDGE + MAP_EDGE_PAD)
endx = rand((TRANSITIONEDGE + MAP_EDGE_PAD), world.maxx-(TRANSITIONEDGE + MAP_EDGE_PAD))
if(EAST)
endy = rand((TRANSITIONEDGE+1), world.maxy-(TRANSITIONEDGE+1))
endx = (TRANSITIONEDGE+1)
endy = rand((TRANSITIONEDGE + MAP_EDGE_PAD), world.maxy-(TRANSITIONEDGE + MAP_EDGE_PAD))
endx = (TRANSITIONEDGE + MAP_EDGE_PAD)
if(SOUTH)
endy = world.maxy-(TRANSITIONEDGE+1)
endx = rand((TRANSITIONEDGE+1), world.maxx-(TRANSITIONEDGE+1))
endy = world.maxy-(TRANSITIONEDGE + MAP_EDGE_PAD)
endx = rand((TRANSITIONEDGE + MAP_EDGE_PAD), world.maxx-(TRANSITIONEDGE + MAP_EDGE_PAD))
if(WEST)
endy = rand((TRANSITIONEDGE+1),world.maxy-(TRANSITIONEDGE+1))
endx = world.maxx-(TRANSITIONEDGE+1)
endy = rand((TRANSITIONEDGE + MAP_EDGE_PAD),world.maxy-(TRANSITIONEDGE + MAP_EDGE_PAD))
endx = world.maxx-(TRANSITIONEDGE + MAP_EDGE_PAD)
. = locate(endx, endy, Z)
///////////////////////
@@ -82,7 +84,7 @@ GLOBAL_LIST_INIT(meteorsC, list(/obj/effect/meteor/dust)) //for space dust event
//////////////////////
/obj/effect/meteor
name = "the concept of meteor"
name = "\proper the concept of meteor"
desc = "You should probably run instead of gawking at this."
icon = 'icons/obj/meteor.dmi'
icon_state = "small"
@@ -92,7 +94,7 @@ GLOBAL_LIST_INIT(meteorsC, list(/obj/effect/meteor/dust)) //for space dust event
var/hitpwr = 2 //Level of ex_act to be called on hit.
var/dest
pass_flags = PASSTABLE
var/heavy = 0
var/heavy = FALSE
var/meteorsound = 'sound/effects/meteorimpact.ogg'
var/z_original
var/threat = 0 // used for determining which meteors are most interesting
@@ -108,12 +110,12 @@ GLOBAL_LIST_INIT(meteorsC, list(/obj/effect/meteor/dust)) //for space dust event
. = ..() //process movement...
var/turf/T = get_turf(loc)
if(.)//.. if did move, ram the turf we get in
var/turf/T = get_turf(loc)
ram_turf(T)
if(prob(10) && !isspaceturf(T) && !istype(T, /turf/closed/mineral) && !istype(T, /turf/open/floor/plating/asteroid))//randomly takes a 'hit' from ramming
get_hit()
if(prob(10) && !isspaceturf(T) && !istype(T, /turf/closed/mineral) && !istype(T, /turf/open/floor/plating/asteroid))//randomly takes a 'hit' from ramming, and ignore spare ruin aseroids
get_hit()
/obj/effect/meteor/Destroy()
if (timerid)
@@ -135,24 +137,25 @@ GLOBAL_LIST_INIT(meteorsC, list(/obj/effect/meteor/dust)) //for space dust event
/obj/effect/meteor/Bump(atom/A)
if(A)
ram_turf(get_turf(A))
playsound(src.loc, meteorsound, 40, 1)
if(!istype(A, /turf/closed/mineral) && !istype(A, /turf/open/floor/plating/asteroid))
playsound(src.loc, meteorsound, 40, TRUE)
if(!istype(A, /turf/closed/mineral) && !istype(A, /turf/open/floor/plating/asteroid)) // ignore localstation ruins
get_hit()
/obj/effect/meteor/proc/ram_turf(turf/T)
//first bust whatever is in the turf
for(var/atom/A in T)
if(A != src)
if(isliving(A))
A.visible_message("<span class='warning'>[src] slams into [A].</span>", "<span class='userdanger'>[src] slams into you!.</span>")
A.ex_act(hitpwr)
for(var/thing in T)
if(thing == src)
continue
if(isliving(thing))
var/mob/living/living_thing = thing
living_thing.visible_message("<span class='warning'>[src] slams into [living_thing].</span>", "<span class='userdanger'>[src] slams into you!.</span>")
living_thing.ex_act(hitpwr)
//then, ram the turf if it still exists
if(T)
T.ex_act(hitpwr)
//process getting 'hit' by colliding with a dense object
//or randomly when ramming turfs
/obj/effect/meteor/proc/get_hit()
@@ -162,13 +165,10 @@ GLOBAL_LIST_INIT(meteorsC, list(/obj/effect/meteor/dust)) //for space dust event
meteor_effect()
qdel(src)
/obj/effect/meteor/ex_act()
return
/obj/effect/meteor/examine(mob/user)
. = ..()
if(!(flags_1 & ADMIN_SPAWNED_1) && isliving(user))
SSmedals.UnlockMedal(MEDAL_METEOR, user.client)
return ..()
user.client.give_award(/datum/award/achievement/misc/meteor_examine, user)
/obj/effect/meteor/attackby(obj/item/I, mob/user, params)
if(I.tool_behaviour == TOOL_MINING)
@@ -232,7 +232,7 @@ GLOBAL_LIST_INIT(meteorsC, list(/obj/effect/meteor/dust)) //for space dust event
name = "big meteor"
icon_state = "large"
hits = 6
heavy = 1
heavy = TRUE
dropamt = 4
threat = 10
@@ -245,7 +245,7 @@ GLOBAL_LIST_INIT(meteorsC, list(/obj/effect/meteor/dust)) //for space dust event
name = "flaming meteor"
icon_state = "flaming"
hits = 5
heavy = 1
heavy = TRUE
meteorsound = 'sound/effects/bamf.ogg'
meteordrop = list(/obj/item/stack/ore/plasma)
threat = 20
@@ -258,7 +258,7 @@ GLOBAL_LIST_INIT(meteorsC, list(/obj/effect/meteor/dust)) //for space dust event
/obj/effect/meteor/irradiated
name = "glowing meteor"
icon_state = "glowing"
heavy = 1
heavy = TRUE
meteordrop = list(/obj/item/stack/ore/uranium)
threat = 15
@@ -275,7 +275,7 @@ GLOBAL_LIST_INIT(meteorsC, list(/obj/effect/meteor/dust)) //for space dust event
icon_state = "meateor"
desc = "Just... don't think too hard about where this thing came from."
hits = 2
heavy = 1
heavy = TRUE
meteorsound = 'sound/effects/blobattack.ogg'
meteordrop = list(/obj/item/reagent_containers/food/snacks/meat/slab/human, /obj/item/reagent_containers/food/snacks/meat/slab/human/mutant, /obj/item/organ/heart, /obj/item/organ/lungs, /obj/item/organ/tongue, /obj/item/organ/appendix/)
var/meteorgibs = /obj/effect/gibspawner/generic
@@ -327,7 +327,7 @@ GLOBAL_LIST_INIT(meteorsC, list(/obj/effect/meteor/dust)) //for space dust event
desc = "Your life briefly passes before your eyes the moment you lay them on this monstrosity."
hits = 30
hitpwr = 1
heavy = 1
heavy = TRUE
meteorsound = 'sound/effects/bamf.ogg'
meteordrop = list(/obj/item/stack/ore/plasma)
threat = 50
@@ -358,7 +358,7 @@ GLOBAL_LIST_INIT(meteorsSPOOKY, list(/obj/effect/meteor/pumpkin))
icon = 'icons/obj/meteor_spooky.dmi'
icon_state = "pumpkin"
hits = 10
heavy = 1
heavy = TRUE
dropamt = 1
meteordrop = list(/obj/item/clothing/head/hardhat/pumpkinhead, /obj/item/reagent_containers/food/snacks/grown/pumpkin)
threat = 100
@@ -368,3 +368,4 @@ GLOBAL_LIST_INIT(meteorsSPOOKY, list(/obj/effect/meteor/pumpkin))
meteorsound = pick('sound/hallucinations/im_here1.ogg','sound/hallucinations/im_here2.ogg')
//////////////////////////
#undef DEFAULT_METEOR_LIFETIME
#undef MAP_EDGE_PAD
+1
View File
@@ -11,6 +11,7 @@
required_players = 20
required_enemies = 1
recommended_enemies = 1
chaos = 9
restricted_jobs = list("Cyborg", "AI")
+1
View File
@@ -2,6 +2,7 @@
name = "nuclear emergency"
config_tag = "nuclear"
false_report_weight = 10
chaos = 9
required_players = 28 // 30 players - 3 players to be the nuke ops = 25 players remaining
required_enemies = 2
recommended_enemies = 5
+1 -1
View File
@@ -1240,7 +1240,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/))
-62
View File
@@ -33,68 +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"
@@ -3,6 +3,7 @@
name = "overthrow"
config_tag = "overthrow"
antag_flag = ROLE_OVERTHROW
chaos = 5
restricted_jobs = list("AI", "Cyborg")
protected_jobs = list("Security Officer", "Warden", "Detective", "Head of Security", "Captain", "Head of Personnel", "Chief Engineer", "Chief Medical Officer", "Research Director", "Quartermaster")
required_players = 20 // the core idea is of a swift, bloodless coup, so it shouldn't be as chaotic as revs.
@@ -12,6 +12,7 @@
config_tag = "revolution"
antag_flag = ROLE_REV
false_report_weight = 10
chaos = 8
restricted_jobs = list("AI", "Cyborg")
protected_jobs = list("Security Officer", "Warden", "Detective", "Head of Security", "Captain", "Head of Personnel", "Chief Engineer", "Chief Medical Officer", "Research Director", "Quartermaster")
required_players = 20
@@ -10,6 +10,7 @@
required_enemies = 5
recommended_enemies = 8
reroll_friendly = 0
chaos = 7
traitor_name = "Nanotrasen Internal Affairs Agent"
antag_flag = ROLE_INTERNAL_AFFAIRS
+1
View File
@@ -17,6 +17,7 @@
recommended_enemies = 4
reroll_friendly = 1
enemy_minimum_age = 0
chaos = 2
announce_span = "danger"
announce_text = "There are Syndicate agents on the station!\n\
+1
View File
@@ -12,6 +12,7 @@
recommended_enemies = 1
enemy_minimum_age = 7
round_ends_with_antag_death = 1
chaos = 9
announce_span = "danger"
announce_text = "There is a space wizard attacking the station!\n\
<span class='danger'>Wizard</span>: Accomplish your objectives and cause mayhem on the station.\n\
+1 -1
View File
@@ -82,7 +82,7 @@
O.add_fingerprint(user)
update_icon()
else if(istype(O, /obj/item/weldingtool) && user.a_intent != INTENT_HARM)
else if(O.tool_behaviour == TOOL_WELDER && user.a_intent != INTENT_HARM)
if(stat & BROKEN)
if(!O.tool_start_check(user, amount=0))
return
+12 -5
View File
@@ -137,7 +137,7 @@ Class Procs:
GLOB.machines += src
if(ispath(circuit, /obj/item/circuitboard))
circuit = new circuit
circuit = new circuit(src)
circuit.apply_default_parts(src)
if(!speed_process && init_process)
@@ -361,11 +361,11 @@ Class Procs:
/obj/machinery/deconstruct(disassembled = TRUE)
if(!(flags_1 & NODECONSTRUCT_1))
on_deconstruction()
if(component_parts && component_parts.len)
if(LAZYLEN(component_parts))
spawn_frame(disassembled)
for(var/obj/item/I in component_parts)
I.forceMove(loc)
component_parts.Cut()
LAZYCLEARLIST(component_parts)
qdel(src)
/obj/machinery/proc/spawn_frame(disassembled)
@@ -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
@@ -539,12 +541,17 @@ Class Procs:
/obj/machinery/Exited(atom/movable/AM, atom/newloc)
. = ..()
// if(AM == occupant)
// set_occupant(null)
if (AM == occupant)
SEND_SIGNAL(src, COMSIG_MACHINE_EJECT_OCCUPANT, occupant)
occupant = null
if(AM == circuit && circuit.loc != src)
component_parts -= AM //TODO: make the cmp part functions use lazyX
circuit = null
/obj/machinery/proc/adjust_item_drop_location(atom/movable/AM) // Adjust item drop location to a 3x3 grid inside the tile, returns slot id from 0 to 8
var/md5 = md5(AM.name) // Oh, and it's deterministic too. A specific item will always drop from the same slot.
/obj/machinery/proc/adjust_item_drop_location(atom/movable/AM) // Adjust item drop location to a 3x3 grid inside the tile, returns slot id from 0 to 8
var/md5 = md5(AM.name) // Oh, and it's deterministic too. A specific item will always drop from the same slot.
for (var/i in 1 to 32)
. += hex2num(md5[i])
. = . % 9
+14 -2
View File
@@ -8,7 +8,19 @@
max_integrity = 200
var/obj/item/bodypart/storedpart
var/initial_icon_state
var/static/list/style_list_icons = list("standard" = 'icons/mob/augmentation/augments.dmi', "engineer" = 'icons/mob/augmentation/augments_engineer.dmi', "security" = 'icons/mob/augmentation/augments_security.dmi', "mining" = 'icons/mob/augmentation/augments_mining.dmi')
var/static/list/style_list_icons = list("standard" = 'icons/mob/augmentation/augments.dmi',
"engineer" = 'icons/mob/augmentation/augments_engineer.dmi',
"security" = 'icons/mob/augmentation/augments_security.dmi',
"mining" = 'icons/mob/augmentation/augments_mining.dmi',
"Talon" = 'icons/mob/augmentation/cosmetic_prosthetic/talon.dmi',
"Nanotrasen" = 'icons/mob/augmentation/cosmetic_prosthetic/nanotrasen.dmi',
"Hephaesthus" = 'icons/mob/augmentation/cosmetic_prosthetic/hephaestus.dmi',
"Bishop" = 'icons/mob/augmentation/cosmetic_prosthetic/bishop.dmi',
"Xion" = 'icons/mob/augmentation/cosmetic_prosthetic/xion.dmi',
"Grayson" = 'icons/mob/augmentation/cosmetic_prosthetic/grayson.dmi',
"Cybersolutions" = 'icons/mob/augmentation/cosmetic_prosthetic/cybersolutions.dmi',
"Ward" = 'icons/mob/augmentation/cosmetic_prosthetic/ward.dmi'
)
/obj/machinery/aug_manipulator/examine(mob/user)
. = ..()
@@ -73,7 +85,7 @@
O.add_fingerprint(user)
update_icon()
else if(istype(O, /obj/item/weldingtool) && user.a_intent != INTENT_HARM)
else if(O.tool_behaviour == TOOL_WELDER && user.a_intent != INTENT_HARM)
if(obj_integrity < max_integrity)
if(!O.tool_start_check(user, amount=0))
return
+55 -41
View File
@@ -1,6 +1,6 @@
#define AUTOLATHE_MAIN_MENU 1
#define AUTOLATHE_CATEGORY_MENU 2
#define AUTOLATHE_SEARCH_MENU 3
#define AUTOLATHE_MAIN_MENU 1
#define AUTOLATHE_CATEGORY_MENU 2
#define AUTOLATHE_SEARCH_MENU 3
/obj/machinery/autolathe
name = "autolathe"
@@ -17,7 +17,7 @@
var/list/L = list()
var/list/LL = list()
var/hacked = FALSE
var/disabled = 0
var/disabled = FALSE
var/shocked = FALSE
var/hack_wire
var/disable_wire
@@ -27,13 +27,13 @@
var/prod_coeff = 1
var/datum/design/being_built
var/datum/techweb/stored_research
var/list/datum/design/matching_designs
var/selected_category
var/screen = 1
var/base_price = 25
var/hacked_price = 50
var/datum/techweb/specialized/autounlocking/stored_research = /datum/techweb/specialized/autounlocking/autolathe
var/list/categories = list(
"Tools",
"Electronics",
@@ -46,21 +46,16 @@
"Dinnerware",
"Imported"
)
var/list/allowed_materials
/// Base print speed
var/base_print_speed = 10
/obj/machinery/autolathe/Initialize()
var/list/mats = allowed_materials
if(!mats)
mats = SSmaterials.materialtypes_by_category[MAT_CATEGORY_RIGID]
AddComponent(/datum/component/material_container, mats, _show_on_examine=TRUE, _after_insert=CALLBACK(src, .proc/AfterMaterialInsert))
. = ..()
wires = new /datum/wires/autolathe(src)
stored_research = new stored_research
stored_research = new /datum/techweb/specialized/autounlocking/autolathe
matching_designs = list()
/obj/machinery/autolathe/ComponentInitialize()
AddComponent(/datum/component/material_container, SSmaterials.materialtypes_by_category[MAT_CATEGORY_RIGID], 0, TRUE, null, null, CALLBACK(src, .proc/AfterMaterialInsert))
/obj/machinery/autolathe/Destroy()
QDEL_NULL(wires)
return ..()
@@ -83,7 +78,7 @@
if(AUTOLATHE_SEARCH_MENU)
dat = search_win(user)
var/datum/browser/popup = new(user, name, name, 400, 500)
var/datum/browser/popup = new(user, "autolathe", name, 400, 500)
popup.set_content(dat)
popup.open()
@@ -114,9 +109,9 @@
return TRUE
if(istype(O, /obj/item/disk/design_disk))
user.visible_message("[user] begins to load \the [O] in \the [src]...",
"You begin to load a design from \the [O]...",
"You hear the chatter of a floppy drive.")
user.visible_message("<span class='notice'>[user] begins to load \the [O] in \the [src]...</span>",
"<span class='notice'>You begin to load a design from \the [O]...</span>",
"<span class='hear'>You hear the chatter of a floppy drive.</span>")
busy = TRUE
var/obj/item/disk/design_disk/D = O
if(do_after(user, 14.4, target = src))
@@ -128,14 +123,16 @@
return ..()
/obj/machinery/autolathe/proc/AfterMaterialInsert(obj/item/item_inserted, id_inserted, amount_inserted)
/obj/machinery/autolathe/proc/AfterMaterialInsert(item_inserted, id_inserted, amount_inserted)
if(istype(item_inserted, /obj/item/stack/ore/bluespace_crystal))
use_power(MINERAL_MATERIAL_AMOUNT / 10)
else if(item_inserted.custom_materials?.len && item_inserted.custom_materials[SSmaterials.GetMaterialRef(/datum/material/glass)])
else if(custom_materials && custom_materials.len && custom_materials[SSmaterials.GetMaterialRef(/datum/material/glass)])
flick("autolathe_r",src)//plays glass insertion animation by default otherwise
else
flick("autolathe_o",src)//plays metal insertion animation
use_power(min(1000, amount_inserted / 100))
updateUsrDialog()
@@ -187,7 +184,7 @@
if(materials.materials[i] > 0)
list_to_show += i
used_material = input("Choose [used_material]", "Custom Material") as null|anything in list_to_show
used_material = input("Choose [used_material]", "Custom Material") as null|anything in sortList(list_to_show, /proc/cmp_typepaths_asc)
if(!used_material)
return //Didn't pick any material, so you can't build shit either.
custom_materials[used_material] += amount_needed
@@ -198,8 +195,8 @@
busy = TRUE
use_power(power)
icon_state = "autolathe_n"
var/time = is_stack ? 10 : base_print_speed * coeff * multiplier
addtimer(CALLBACK(src, .proc/make_item, power, materials_used, custom_materials, multiplier, coeff, is_stack), time)
var/time = is_stack ? 32 : (32 * coeff * multiplier) ** 0.8
addtimer(CALLBACK(src, .proc/make_item, power, materials_used, custom_materials, multiplier, coeff, is_stack, usr), time)
else
to_chat(usr, "<span class=\"alert\">Not enough materials for this operation.</span>")
@@ -218,10 +215,11 @@
return
/obj/machinery/autolathe/proc/make_item(power, var/list/materials_used, var/list/picked_materials, multiplier, coeff, is_stack)
/obj/machinery/autolathe/proc/make_item(power, list/materials_used, list/picked_materials, multiplier, coeff, is_stack, mob/user)
var/datum/component/material_container/materials = GetComponent(/datum/component/material_container)
var/atom/A = drop_location()
use_power(power)
materials.use_materials(materials_used)
if(is_stack)
@@ -235,6 +233,11 @@
if(length(picked_materials))
new_item.set_custom_materials(picked_materials, 1 / multiplier) //Ensure we get the non multiplied amount
for(var/x in picked_materials)
var/datum/material/M = x
if(!istype(M, /datum/material/glass) && !istype(M, /datum/material/iron))
user.client.give_award(/datum/award/achievement/misc/getting_an_upgrade, user)
icon_state = "autolathe"
busy = FALSE
@@ -246,12 +249,10 @@
T += MB.rating*75000
var/datum/component/material_container/materials = GetComponent(/datum/component/material_container)
materials.max_amount = T
var/manips = 0
var/total_manip_rating = 0
T=1.2
for(var/obj/item/stock_parts/manipulator/M in component_parts)
total_manip_rating += M.rating
manips++
prod_coeff = STANDARD_PART_LEVEL_LATHE_COEFFICIENT(total_manip_rating / (manips? manips : 1))
T -= M.rating*0.2
prod_coeff = min(1,max(0,T)) // Coeff going 1 -> 0,8 -> 0,6 -> 0,4
/obj/machinery/autolathe/examine(mob/user)
. += ..()
@@ -376,6 +377,7 @@
return materials.has_materials(required_materials)
/obj/machinery/autolathe/proc/get_design_cost(datum/design/D)
var/coeff = (ispath(D.build_path, /obj/item/stack) ? 1 : prod_coeff)
var/dat
@@ -416,9 +418,7 @@
hacked = state
for(var/id in SSresearch.techweb_designs)
var/datum/design/D = SSresearch.techweb_design_by_id(id)
if(D.build_type & stored_research.design_autounlock_skip_types)
continue
if((D.build_type & stored_research.design_autounlock_buildtypes) && ("hacked" in D.category))
if((D.build_type & AUTOLATHE) && ("hacked" in D.category))
if(hacked)
stored_research.add_design(D)
else
@@ -428,19 +428,27 @@
. = ..()
adjust_hacked(TRUE)
//Called when the object is constructed by an autolathe
//Has a reference to the autolathe so you can do !!FUN!! things with hacked lathes
/obj/item/proc/autolathe_crafted(obj/machinery/autolathe/A)
return
/obj/machinery/autolathe/secure
name = "secured autolathe"
desc = "It produces items using metal and glass. This model was reprogrammed without some of the more hazardous designs."
circuit = /obj/item/circuitboard/machine/autolathe/secure
stored_research = /datum/techweb/specialized/autounlocking/autolathe/public
base_print_speed = 20
/obj/machinery/autolathe/secure/Initialize()
. = ..()
// let's not leave the parent datum floating, right?
if(stored_research)
QDEL_NULL(stored_research)
stored_research = new /datum/techweb/specialized/autounlocking/autolathe/public
/obj/machinery/autolathe/toy
name = "autoylathe"
desc = "It produces toys using plastic, metal and glass."
circuit = /obj/item/circuitboard/machine/autolathe/toy
stored_research = /datum/techweb/specialized/autounlocking/autolathe/toy
categories = list(
"Toys",
"Figurines",
@@ -453,12 +461,18 @@
"Misc",
"Imported"
)
allowed_materials = list(
/datum/material/iron,
/datum/material/glass,
/datum/material/plastic
)
/obj/machinery/autolathe/toy/Initialize()
. = ..()
// let's not leave the parent datum floating, right?
if(stored_research)
QDEL_NULL(stored_research)
stored_research = new /datum/techweb/specialized/autounlocking/autolathe/toy
/obj/machinery/autolathe/toy/hacked/Initialize()
. = ..()
adjust_hacked(TRUE)
// override the base to allow plastics
/obj/machinery/autolathe/ComponentInitialize()
var/list/extra_mats = list(/datum/material/plastic)
AddComponent(/datum/component/material_container, SSmaterials.materialtypes_by_category[MAT_CATEGORY_RIGID] + extra_mats, 0, TRUE, null, null, CALLBACK(src, .proc/AfterMaterialInsert))
+2 -2
View File
@@ -65,7 +65,7 @@
. += "button-board"
/obj/machinery/button/attackby(obj/item/W, mob/user, params)
if(istype(W, /obj/item/screwdriver))
if(W.tool_behaviour == TOOL_SCREWDRIVER)
if(panel_open || allowed(user))
default_deconstruction_screwdriver(user, "button-open", "[skin]",W)
update_icon()
@@ -93,7 +93,7 @@
req_access = board.accesses
to_chat(user, "<span class='notice'>You add [W] to the button.</span>")
if(!device && !board && istype(W, /obj/item/wrench))
if(!device && !board && W.tool_behaviour == TOOL_WRENCH)
to_chat(user, "<span class='notice'>You start unsecuring the button frame...</span>")
W.play_tool_sound(src)
if(W.use_tool(src, user, 40))
@@ -39,7 +39,7 @@
switch(state)
if(1)
// State 1
if(istype(W, /obj/item/weldingtool))
if(W.tool_behaviour == TOOL_WELDER)
if(weld(W, user))
to_chat(user, "<span class='notice'>You weld the assembly securely into place.</span>")
setAnchored(TRUE)
@@ -56,7 +56,7 @@
return
return
else if(istype(W, /obj/item/weldingtool))
else if(W.tool_behaviour == TOOL_WELDER)
if(weld(W, user))
to_chat(user, "<span class='notice'>You unweld the assembly from its place.</span>")
@@ -133,7 +133,9 @@
qdel(src)
return TRUE
/obj/structure/camera_assembly/proc/weld(obj/item/weldingtool/W, mob/living/user)
/obj/structure/camera_assembly/proc/weld(obj/item/W, mob/living/user)
if(!W.tool_behaviour == TOOL_WELDER)
return
if(!W.tool_start_check(user, amount=0))
return FALSE
to_chat(user, "<span class='notice'>You start to weld \the [src]...</span>")
+11 -9
View File
@@ -10,7 +10,7 @@
circuit = /obj/item/circuitboard/machine/cell_charger
pass_flags = PASSTABLE
var/obj/item/stock_parts/cell/charging = null
var/charge_rate = 500
var/recharge_coeff = 1
/obj/machinery/cell_charger/update_overlays()
. += ..()
@@ -28,9 +28,10 @@
. = ..()
. += "There's [charging ? "a" : "no"] cell in the charger."
if(charging)
. += "Current charge: [round(charging.percent(), 1)]%."
var/obj/item/stock_parts/cell/C = charging.get_cell()
. += "Current charge: [C.percent()]%."
if(in_range(user, src) || isobserver(user))
. += "<span class='notice'>The status display reads: Charge rate at <b>[charge_rate]J</b> per cycle.</span>"
. += "<span class='notice'>The status display reads: Charge rate at <b>[recharge_coeff*10]J</b> per cycle.</span>"
/obj/machinery/cell_charger/attackby(obj/item/W, mob/user, params)
if(istype(W, /obj/item/stock_parts/cell) && !panel_open)
@@ -122,17 +123,18 @@
charging.emp_act(severity)
/obj/machinery/cell_charger/RefreshParts()
charge_rate = 500
for(var/obj/item/stock_parts/capacitor/C in component_parts)
charge_rate *= C.rating
recharge_coeff = C.rating
/obj/machinery/cell_charger/process()
if(!charging || !anchored || (stat & (BROKEN|NOPOWER)))
return
if(charging.percent() >= 100)
return
use_power(charge_rate)
charging.give(charge_rate) //this is 2558, efficient batteries exist
if(charging)
var/obj/item/stock_parts/cell/C = charging.get_cell()
if(C)
if(C.charge < C.maxcharge)
C.give(C.chargerate * recharge_coeff)
use_power(250 * recharge_coeff)
update_icon()
+8 -10
View File
@@ -297,22 +297,20 @@
if(default_deconstruction_crowbar(W))
return
if(istype(W, /obj/item/multitool))
var/obj/item/multitool/P = W
if(istype(P.buffer, /obj/machinery/computer/cloning))
if(get_area(P.buffer) != get_area(src))
if(W.tool_behaviour == TOOL_MULTITOOL)
if(istype(W.buffer, /obj/machinery/computer/cloning))
if(get_area(W.buffer) != get_area(src))
to_chat(user, "<font color = #666633>-% Cannot link machines across power zones. Buffer cleared %-</font color>")
P.buffer = null
W.buffer = null
return
to_chat(user, "<font color = #666633>-% Successfully linked [P.buffer] with [src] %-</font color>")
var/obj/machinery/computer/cloning/comp = P.buffer
to_chat(user, "<font color = #666633>-% Successfully linked [W.buffer] with [src] %-</font color>")
var/obj/machinery/computer/cloning/comp = W.buffer
if(connected)
connected.DetachCloner(src)
comp.AttachCloner(src)
else
P.buffer = src
to_chat(user, "<font color = #666633>-% Successfully stored [REF(P.buffer)] [P.buffer.name] in buffer %-</font color>")
W.buffer = src
to_chat(user, "<font color = #666633>-% Successfully stored [REF(W.buffer)] [W.buffer] in buffer %-</font color>")
return
var/mob/living/mob_occupant = occupant
+2 -1
View File
@@ -44,7 +44,8 @@
icon_state = "colormate"
/obj/machinery/gear_painter/Destroy()
inserted.forceMove(drop_location())
if(inserted) //please i beg you do not drop nulls
inserted.forceMove(drop_location())
return ..()
/obj/machinery/gear_painter/attackby(obj/item/I, mob/living/user)
+31 -23
View File
@@ -17,20 +17,16 @@
/obj/machinery/computer/Initialize(mapload, obj/item/circuitboard/C)
. = ..()
power_change()
if(!QDELETED(C))
qdel(circuit)
circuit = C
C.moveToNullspace()
/obj/machinery/computer/Destroy()
QDEL_NULL(circuit)
return ..()
. = ..()
/obj/machinery/computer/process()
if(stat & (NOPOWER|BROKEN))
return 0
return 1
return FALSE
return TRUE
/obj/machinery/computer/ratvar_act()
if(!clockwork)
@@ -87,25 +83,32 @@
switch(damage_type)
if(BRUTE)
if(stat & BROKEN)
playsound(src.loc, 'sound/effects/hit_on_shattered_glass.ogg', 70, 1)
playsound(src.loc, 'sound/effects/hit_on_shattered_glass.ogg', 70, TRUE)
else
playsound(src.loc, 'sound/effects/glasshit.ogg', 75, 1)
playsound(src.loc, 'sound/effects/glasshit.ogg', 75, TRUE)
if(BURN)
playsound(src.loc, 'sound/items/welder.ogg', 100, 1)
playsound(src.loc, 'sound/items/welder.ogg', 100, TRUE)
/obj/machinery/computer/obj_break(damage_flag)
if(circuit && !(flags_1 & NODECONSTRUCT_1)) //no circuit, no breaking
if(!(stat & BROKEN))
playsound(loc, 'sound/effects/glassbr3.ogg', 100, 1)
stat |= BROKEN
update_icon()
set_light(0)
if(!circuit) //no circuit, no breaking
return
. = ..()
if(. && !(stat & BROKEN))
stat |= BROKEN
playsound(loc, 'sound/effects/glassbr3.ogg', 100, TRUE)
set_light(0)
update_icon()
/obj/machinery/computer/emp_act(severity)
. = ..()
if (!(. & EMP_PROTECT_SELF))
if(prob(severity/1.8))
obj_break("energy")
switch(severity)
if(1)
if(prob(50))
obj_break("energy")
if(2)
if(prob(10))
obj_break("energy")
/obj/machinery/computer/deconstruct(disassembled = TRUE, mob/user)
on_deconstruction()
@@ -114,12 +117,14 @@
var/obj/structure/frame/computer/A = new /obj/structure/frame/computer(src.loc)
A.setDir(dir)
A.circuit = circuit
A.setAnchored(TRUE)
// Circuit removal code is handled in /obj/machinery/Exited()
circuit.forceMove(A)
A.set_anchored(TRUE)
if(stat & BROKEN)
if(user)
to_chat(user, "<span class='notice'>The broken glass falls out.</span>")
else
playsound(src, 'sound/effects/hit_on_shattered_glass.ogg', 70, 1)
playsound(src, 'sound/effects/hit_on_shattered_glass.ogg', 70, TRUE)
new /obj/item/shard(drop_location())
new /obj/item/shard(drop_location())
A.state = 3
@@ -129,8 +134,11 @@
to_chat(user, "<span class='notice'>You disconnect the monitor.</span>")
A.state = 4
A.icon_state = "4"
circuit = null
for(var/obj/C in src)
C.forceMove(loc)
qdel(src)
/obj/machinery/computer/AltClick(mob/user)
. = ..()
if(!user.canUseTopic(src, !issilicon(user)) || !(stat & (NOPOWER|BROKEN)))
return
+2 -2
View File
@@ -10,8 +10,8 @@
var/mob/living/silicon/ai/occupier = null
var/active = FALSE
/obj/machinery/computer/aifixer/attackby(obj/I, mob/user, params)
if(occupier && istype(I, /obj/item/screwdriver))
/obj/machinery/computer/aifixer/attackby(obj/item/I, mob/user, params)
if(occupier && I.tool_behaviour == TOOL_SCREWDRIVER)
if(stat & (NOPOWER|BROKEN))
to_chat(user, "<span class='warning'>The screws on [name]'s screen won't budge.</span>")
else
+8 -1
View File
@@ -151,7 +151,14 @@
var/obj/machinery/power/apc/target = locate(ref) in GLOB.apcs_list
if(!target)
return
target.vars[type] = target.setsubsystem(text2num(value))
value = target.setsubsystem(text2num(value))
switch(type) // Sanity check
if("equipment", "lighting", "environ")
target.vars[type] = value
else
message_admins("Warning: possible href exploit by [key_name(usr)] - attempted to set [type] on [target] to [value]")
log_game("Warning: possible href exploit by [key_name(usr)] - attempted to set [type] on [target] to [value]")
return
target.update_icon()
target.update()
var/setTo = ""
+44 -34
View File
@@ -3,14 +3,7 @@
#define ARCADE_WEIGHT_RARE 1
#define ARCADE_RATIO_PLUSH 0.20 // average 1 out of 6 wins is a plush.
/obj/machinery/computer/arcade
name = "random arcade"
desc = "random arcade machine"
icon_state = "arcade"
icon_keyboard = null
icon_screen = "invaders"
clockwork = TRUE //it'd look weird
var/list/prizes = list(
GLOBAL_LIST_INIT(arcade_prize_pool, list(
/obj/item/toy/balloon = ARCADE_WEIGHT_USELESS,
/obj/item/toy/beach_ball = ARCADE_WEIGHT_USELESS,
/obj/item/toy/cattoy = ARCADE_WEIGHT_USELESS,
@@ -70,9 +63,16 @@
/obj/item/clothing/mask/fakemoustache/italian = ARCADE_WEIGHT_RARE,
/obj/item/clothing/suit/hooded/wintercoat/ratvar/fake = ARCADE_WEIGHT_TRICK,
/obj/item/clothing/suit/hooded/wintercoat/narsie/fake = ARCADE_WEIGHT_TRICK
)
))
/obj/machinery/computer/arcade
name = "random arcade"
desc = "random arcade machine"
icon_state = "arcade"
icon_keyboard = "no_keyboard"
icon_screen = "invaders"
light_color = LIGHT_COLOR_GREEN
var/list/prize_override
/obj/machinery/computer/arcade/proc/Reset()
return
@@ -91,44 +91,54 @@
var/obj/machinery/computer/arcade/A = new CB.build_path(loc, CB)
A.setDir(dir)
return INITIALIZE_HINT_QDEL
//The below object acts as a spawner with a wide array of possible picks, most being uninspired references to past/current player characters.
//Nevertheless, this keeps its ratio constant with the sum of all the others prizes.
prizes[/obj/item/toy/plush/random] = counterlist_sum(prizes) * ARCADE_RATIO_PLUSH
Reset()
/obj/machinery/computer/arcade/proc/prizevend(mob/user, list/rarity_classes)
SEND_SIGNAL(user, COMSIG_ADD_MOOD_EVENT, "arcade", /datum/mood_event/arcade)
/obj/machinery/computer/arcade/proc/prizevend(mob/user, prizes = 1)
// if(user.mind?.get_skill_level(/datum/skill/gaming) >= SKILL_LEVEL_LEGENDARY && HAS_TRAIT(user, TRAIT_GAMERGOD))
// visible_message("<span class='notice'>[user] inputs an intense cheat code!</span>",
// "<span class='notice'>You hear a flurry of buttons being pressed.</span>")
// say("CODE ACTIVATED: EXTRA PRIZES.")
// prizes *= 2
for(var/i = 0, i < prizes, i++)
SEND_SIGNAL(user, COMSIG_ADD_MOOD_EVENT, "arcade", /datum/mood_event/arcade)
if(prob(0.0001)) //1 in a million
new /obj/item/gun/energy/pulse/prize(src)
visible_message("<span class='notice'>[src] dispenses.. woah, a gun! Way past cool.</span>", "<span class='notice'>You hear a chime and a shot.</span>")
user.client.give_award(/datum/award/achievement/misc/pulse, user)
return
if(prob(1) && prob(1) && prob(1)) //Proper 1 in a million
new /obj/item/gun/energy/pulse/prize(src)
SSmedals.UnlockMedal(MEDAL_PULSE, usr.client)
var/prizeselect
if(prize_override)
prizeselect = pickweight(prize_override)
else
prizeselect = pickweight(GLOB.arcade_prize_pool)
var/atom/movable/the_prize = new prizeselect(get_turf(src))
playsound(src, 'sound/machines/machine_vend.ogg', 50, TRUE, extrarange = -3)
visible_message("<span class='notice'>[src] dispenses [the_prize]!</span>", "<span class='notice'>You hear a chime and a clunk.</span>")
if(!contents.len)
var/list/toy_raffle
if(rarity_classes)
for(var/A in prizes)
if(prizes[A] in rarity_classes)
LAZYSET(toy_raffle, A, prizes[A])
if(!toy_raffle)
toy_raffle = prizes
var/prizeselect = pickweight(toy_raffle)
new prizeselect(src)
var/atom/movable/prize = pick(contents)
visible_message("<span class='notice'>[src] dispenses [prize]!</span>", "<span class='notice'>You hear a chime and a clunk.</span>")
prize.forceMove(get_turf(src))
/obj/machinery/computer/arcade/emp_act(severity)
. = ..()
var/override = FALSE
if(prize_override)
override = TRUE
if(stat & (NOPOWER|BROKEN) || . & EMP_PROTECT_SELF)
return
var/empprize = null
var/num_of_prizes = rand(round(severity/50),round(severity/100))
var/num_of_prizes = 0
switch(severity)
if(1)
num_of_prizes = rand(1,4)
if(2)
num_of_prizes = rand(0,2)
for(var/i = num_of_prizes; i > 0; i--)
empprize = pickweight(prizes)
if(override)
empprize = pickweight(prize_override)
else
empprize = pickweight(GLOB.arcade_prize_pool)
new empprize(loc)
explosion(loc, -1, 0, 1+num_of_prizes, flame_range = 1+num_of_prizes)
+392 -125
View File
@@ -1,130 +1,399 @@
// ** BATTLE ** //
/obj/machinery/computer/arcade/battle
name = "arcade machine"
desc = "Does not support Pinball."
icon_state = "arcade"
circuit = /obj/item/circuitboard/computer/arcade/battle
var/enemy_name = "Space Villain"
var/temp = "Winners don't use space drugs" //Temporary message, for attack messages, etc
var/player_hp = 30 //Player health/attack points
var/player_mp = 10
var/enemy_hp = 45 //Enemy health/attack points
var/enemy_mp = 20
var/gameover = FALSE
var/blocked = FALSE //Player cannot attack/heal while set
var/turtle = 0
var/turn_speed = 5 //Measured in deciseconds.
var/enemy_name = "Space Villain"
///Enemy health/attack points
var/enemy_hp = 100
var/enemy_mp = 40
///Temporary message, for attack messages, etc
var/temp = "<br><center><h3>Winners don't use space drugs<center><h3>"
///the list of passive skill the enemy currently has. the actual passives are added in the enemy_setup() proc
var/list/enemy_passive
///if all the enemy's weakpoints have been triggered becomes TRUE
var/finishing_move = FALSE
///linked to passives, when it's equal or above the max_passive finishing move will become TRUE
var/pissed_off = 0
///the number of passives the enemy will start with
var/max_passive = 3
///weapon wielded by the enemy, the shotgun doesn't count.
var/chosen_weapon
///Player health
var/player_hp = 85
///player magic points
var/player_mp = 20
///used to remember the last three move of the player before this turn.
var/list/last_three_move
///if the enemy or player died. restart the game when TRUE
var/gameover = FALSE
///the player cannot make any move while this is set to TRUE. should only TRUE during enemy turns.
var/blocked = FALSE
///used to clear the enemy_action proc timer when the game is restarted
var/timer_id
///weapon used by the enemy, pure fluff.for certain actions
var/list/weapons
///unique to the emag mode, acts as a time limit where the player dies when it reaches 0.
var/bomb_cooldown = 19
///creates the enemy base stats for a new round along with the enemy passives
/obj/machinery/computer/arcade/battle/proc/enemy_setup(player_skill)
player_hp = 85
player_mp = 20
enemy_hp = 100
enemy_mp = 40
gameover = FALSE
blocked = FALSE
finishing_move = FALSE
pissed_off = 0
last_three_move = null
enemy_passive = list("short_temper" = TRUE, "poisonous" = TRUE, "smart" = TRUE, "shotgun" = TRUE, "magical" = TRUE, "chonker" = TRUE)
for(var/i = LAZYLEN(enemy_passive); i > max_passive; i--) //we'll remove passives from the list until we have the number of passive we want
var/picked_passive = pick(enemy_passive)
LAZYREMOVE(enemy_passive, picked_passive)
if(LAZYACCESS(enemy_passive, "chonker"))
enemy_hp += 20
if(LAZYACCESS(enemy_passive, "shotgun"))
chosen_weapon = "shotgun"
else if(weapons)
chosen_weapon = pick(weapons)
else
chosen_weapon = "null gun" //if the weapons list is somehow empty, shouldn't happen but runtimes are sneaky bastards.
if(player_skill)
player_hp += player_skill * 2
/obj/machinery/computer/arcade/battle/Reset()
max_passive = 3
var/name_action
var/name_part1
var/name_part2
name_action = pick("Defeat ", "Annihilate ", "Save ", "Strike ", "Stop ", "Destroy ", "Robust ", "Romance ", "Pwn ", "Own ", "Ban ")
if(SSevents.holidays && SSevents.holidays[HALLOWEEN])
name_action = pick_list(ARCADE_FILE, "rpg_action_halloween")
name_part1 = pick_list(ARCADE_FILE, "rpg_adjective_halloween")
name_part2 = pick_list(ARCADE_FILE, "rpg_enemy_halloween")
weapons = strings(ARCADE_FILE, "rpg_weapon_halloween")
else if(SSevents.holidays && SSevents.holidays[CHRISTMAS])
name_action = pick_list(ARCADE_FILE, "rpg_action_xmas")
name_part1 = pick_list(ARCADE_FILE, "rpg_adjective_xmas")
name_part2 = pick_list(ARCADE_FILE, "rpg_enemy_xmas")
weapons = strings(ARCADE_FILE, "rpg_weapon_xmas")
else if(SSevents.holidays && SSevents.holidays[VALENTINES])
name_action = pick_list(ARCADE_FILE, "rpg_action_valentines")
name_part1 = pick_list(ARCADE_FILE, "rpg_adjective_valentines")
name_part2 = pick_list(ARCADE_FILE, "rpg_enemy_valentines")
weapons = strings(ARCADE_FILE, "rpg_weapon_valentines")
else
name_action = pick_list(ARCADE_FILE, "rpg_action")
name_part1 = pick_list(ARCADE_FILE, "rpg_adjective")
name_part2 = pick_list(ARCADE_FILE, "rpg_enemy")
weapons = strings(ARCADE_FILE, "rpg_weapon")
name_part1 = pick("the Automatic ", "Farmer ", "Lord ", "Professor ", "the Cuban ", "the Evil ", "the Dread King ", "the Space ", "Lord ", "the Great ", "Duke ", "General ")
name_part2 = pick("Melonoid", "Murdertron", "Sorcerer", "Ruin", "Jeff", "Ectoplasm", "Crushulon", "Uhangoid", "Vhakoid", "Peteoid", "slime", "Griefer", "ERPer", "Lizard Man", "Unicorn", "Bloopers")
enemy_name = ("The " + name_part1 + " " + name_part2)
name = (name_action + " " + enemy_name)
enemy_name = replacetext((name_part1 + name_part2), "the ", "")
name = (name_action + name_part1 + name_part2)
enemy_setup(0) //in the case it's reset we assume the player skill is 0 because the VOID isn't a gamer
/obj/machinery/computer/arcade/battle/ui_interact(mob/user)
. = ..()
screen_setup(user)
///sets up the main screen for the user
/obj/machinery/computer/arcade/battle/proc/screen_setup(mob/user)
var/dat = "<a href='byond://?src=[REF(src)];close=1'>Close</a>"
dat += "<center><h4>[enemy_name]</h4></center>"
dat += "<br><center><h3>[temp]</h3></center>"
dat += "[temp]"
dat += "<br><center>Health: [player_hp] | Magic: [player_mp] | Enemy Health: [enemy_hp]</center>"
if (gameover)
dat += "<center><b><a href='byond://?src=[REF(src)];newgame=1'>New Game</a>"
else
dat += "<center><b><a href='byond://?src=[REF(src)];attack=1'>Attack</a> | "
dat += "<a href='byond://?src=[REF(src)];heal=1'>Heal</a> | "
dat += "<a href='byond://?src=[REF(src)];charge=1'>Recharge Power</a>"
dat += "<center><b><a href='byond://?src=[REF(src)];attack=1'>Light attack</a>"
dat += "<center><b><a href='byond://?src=[REF(src)];defend=1'>Defend</a>"
dat += "<center><b><a href='byond://?src=[REF(src)];counter_attack=1'>Counter attack</a>"
dat += "<center><b><a href='byond://?src=[REF(src)];power_attack=1'>Power attack</a>"
dat += "</b></center>"
var/datum/browser/popup = new(user, "arcade", "Space Villain 2000")
popup.set_content(dat)
popup.open()
if(user.client) //mainly here to avoid a runtime when the player gets gibbed when losing the emag mode.
var/datum/browser/popup = new(user, "arcade", "Space Villain 2000")
popup.set_content(dat)
popup.open()
/obj/machinery/computer/arcade/battle/Topic(href, href_list)
if(..())
return
var/gamerSkill = 0
// if(usr?.mind)
// gamerSkill = usr.mind.get_skill_level(/datum/skill/gaming)
if (!blocked && !gameover)
var/attackamt = rand(5,7) + rand(0, gamerSkill)
if(finishing_move) //time to bonk that fucker,cuban pete will sometime survive a finishing move.
attackamt *= 100
//light attack suck absolute ass but it doesn't cost any MP so it's pretty good to finish an enemy off
if (href_list["attack"])
blocked = TRUE
var/attackamt = rand(2,6)
temp = "You attack for [attackamt] damage!"
playsound(loc, 'sound/arcade/hit.ogg', 50, TRUE, extrarange = -3)
updateUsrDialog()
if(turtle > 0)
turtle--
sleep(turn_speed)
temp = "<br><center><h3>you do quick jab for [attackamt] of damage!</h3></center>"
enemy_hp -= attackamt
arcade_action(usr)
arcade_action(usr,"attack",attackamt)
else if (href_list["heal"])
blocked = TRUE
var/pointamt = rand(1,3)
var/healamt = rand(6,8)
temp = "You use [pointamt] magic to heal for [healamt] damage!"
playsound(loc, 'sound/arcade/heal.ogg', 50, TRUE, extrarange = -3)
updateUsrDialog()
turtle++
//defend lets you gain back MP and take less damage from non magical attack.
else if(href_list["defend"])
temp = "<br><center><h3>you take a defensive stance and gain back 10 mp!</h3></center>"
player_mp += 10
arcade_action(usr,"defend",attackamt)
playsound(src, 'sound/arcade/mana.ogg', 50, TRUE, extrarange = -3)
sleep(turn_speed)
player_mp -= pointamt
player_hp += healamt
blocked = TRUE
updateUsrDialog()
arcade_action(usr)
//mainly used to counter short temper and their absurd damage, will deal twice the damage the player took of a non magical attack.
else if(href_list["counter_attack"] && player_mp >= 10)
temp = "<br><center><h3>you prepare yourself to counter the next attack!</h3></center>"
player_mp -= 10
arcade_action(usr,"counter_attack",attackamt)
playsound(src, 'sound/arcade/mana.ogg', 50, TRUE, extrarange = -3)
else if (href_list["charge"])
blocked = TRUE
var/chargeamt = rand(4,7)
temp = "You regain [chargeamt] points"
playsound(loc, 'sound/arcade/mana.ogg', 50, TRUE, extrarange = -3)
player_mp += chargeamt
if(turtle > 0)
turtle--
else if(href_list["counter_attack"] && player_mp < 10)
temp = "<br><center><h3>you don't have the mp necessary to counter attack and defend yourself instead</h3></center>"
player_mp += 10
arcade_action(usr,"defend",attackamt)
playsound(src, 'sound/arcade/mana.ogg', 50, TRUE, extrarange = -3)
updateUsrDialog()
sleep(turn_speed)
arcade_action(usr)
//power attack deals twice the amount of damage but is really expensive MP wise, mainly used with combos to get weakpoints.
else if (href_list["power_attack"] && player_mp >= 20)
temp = "<br><center><h3>You attack [enemy_name] with all your might for [attackamt * 2] damage!</h3></center>"
enemy_hp -= attackamt * 2
player_mp -= 20
arcade_action(usr,"power_attack",attackamt)
else if(href_list["power_attack"] && player_mp < 20)
temp = "<br><center><h3>You don't have the mp necessary for a power attack and settle for a light attack!</h3></center>"
enemy_hp -= attackamt
arcade_action(usr,"attack",attackamt)
if (href_list["close"])
usr.unset_machine()
usr << browse(null, "window=arcade")
else if (href_list["newgame"]) //Reset everything
temp = "New Round"
player_hp = initial(player_hp)
player_mp = initial(player_mp)
enemy_hp = initial(enemy_hp)
enemy_mp = initial(enemy_mp)
gameover = FALSE
turtle = 0
temp = "<br><center><h3>New Round<center><h3>"
if(obj_flags & EMAGGED)
Reset()
obj_flags &= ~EMAGGED
enemy_setup(gamerSkill)
screen_setup(usr)
add_fingerprint(usr)
updateUsrDialog()
return
/obj/machinery/computer/arcade/battle/proc/arcade_action(mob/user)
if ((enemy_mp <= 0) || (enemy_hp <= 0))
///happens after a player action and before the enemy turn. the enemy turn will be cancelled if there's a gameover.
/obj/machinery/computer/arcade/battle/proc/arcade_action(mob/user,player_stance,attackamt)
screen_setup(user)
blocked = TRUE
if(player_stance == "attack" || player_stance == "power_attack")
if(attackamt > 40)
playsound(src, 'sound/arcade/boom.ogg', 50, TRUE, extrarange = -3)
else
playsound(src, 'sound/arcade/hit.ogg', 50, TRUE, extrarange = -3)
timer_id = addtimer(CALLBACK(src, .proc/enemy_action,player_stance,user),1 SECONDS,TIMER_STOPPABLE)
gameover_check(user)
///the enemy turn, the enemy's action entirely depend on their current passive and a teensy tiny bit of randomness
/obj/machinery/computer/arcade/battle/proc/enemy_action(player_stance,mob/user)
var/list/list_temp = list()
switch(LAZYLEN(last_three_move)) //we keep the last three action of the player in a list here
if(0 to 2)
LAZYADD(last_three_move, player_stance)
if(3)
for(var/i in 1 to 2)
last_three_move[i] = last_three_move[i + 1]
last_three_move[3] = player_stance
if(4 to INFINITY)
last_three_move = null //this shouldn't even happen but we empty the list if it somehow goes above 3
var/enemy_stance
var/attack_amount = rand(8,10) //making the attack amount not vary too much so that it's easier to see if the enemy has a shotgun
if(player_stance == "defend")
attack_amount -= 5
//if emagged, cuban pete will set up a bomb acting up as a timer. when it reaches 0 the player fucking dies
if(obj_flags & EMAGGED)
switch(bomb_cooldown--)
if(18)
list_temp += "<br><center><h3>[enemy_name] takes two valve tank and links them together, what's he planning?<center><h3>"
if(15)
list_temp += "<br><center><h3>[enemy_name] adds a remote control to the tan- ho god is that a bomb?<center><h3>"
if(12)
list_temp += "<br><center><h3>[enemy_name] throws the bomb next to you, you'r too scared to pick it up. <center><h3>"
if(6)
list_temp += "<br><center><h3>[enemy_name]'s hand brushes the remote linked to the bomb, your heart skipped a beat. <center><h3>"
if(2)
list_temp += "<br><center><h3>[enemy_name] is going to press the button! It's now or never! <center><h3>"
if(0)
player_hp -= attack_amount * 1000 //hey it's a maxcap we might as well go all in
//yeah I used the shotgun as a passive, you know why? because the shotgun gives +5 attack which is pretty good
if(LAZYACCESS(enemy_passive, "shotgun"))
if(weakpoint_check("shotgun","defend","defend","power_attack"))
list_temp += "<br><center><h3>You manage to disarm [enemy_name] with a surprise power attack and shoot him with his shotgun until it runs out of ammo! <center><h3> "
enemy_hp -= 10
chosen_weapon = "empty shotgun"
else
attack_amount += 5
//heccing chonker passive, only gives more HP at the start of a new game but has one of the hardest weakpoint to trigger.
if(LAZYACCESS(enemy_passive, "chonker"))
if(weakpoint_check("chonker","power_attack","power_attack","power_attack"))
list_temp += "<br><center><h3>After a lot of power attacks you manage to tip over [enemy_name] as they fall over their enormous weight<center><h3> "
enemy_hp -= 30
//smart passive trait, mainly works in tandem with other traits, makes the enemy unable to be counter_attacked
if(LAZYACCESS(enemy_passive, "smart"))
if(weakpoint_check("smart","defend","defend","attack"))
list_temp += "<br><center><h3>[enemy_name] is confused by your illogical strategy!<center><h3> "
attack_amount -= 5
else if(attack_amount >= player_hp)
player_hp -= attack_amount
list_temp += "<br><center><h3>[enemy_name] figures out you are really close to death and finishes you off with their [chosen_weapon]!<center><h3>"
enemy_stance = "attack"
else if(player_stance == "counter_attack")
list_temp += "<br><center><h3>[enemy_name] is not taking your bait. <center><h3> "
if(LAZYACCESS(enemy_passive, "short_temper"))
list_temp += "However controlling their hatred of you still takes a toll on their mental and physical health!"
enemy_hp -= 5
enemy_mp -= 5
enemy_stance = "defensive"
//short temper passive trait, gets easily baited into being counter attacked but will bypass your counter when low on HP
if(LAZYACCESS(enemy_passive, "short_temper"))
if(weakpoint_check("short_temper","counter_attack","counter_attack","counter_attack"))
list_temp += "<br><center><h3>[enemy_name] is getting frustrated at all your counter attacks and throws a tantrum!<center><h3>"
enemy_hp -= attack_amount
else if(player_stance == "counter_attack")
if(!(LAZYACCESS(enemy_passive, "smart")) && enemy_hp > 30)
list_temp += "<br><center><h3>[enemy_name] took the bait and allowed you to counter attack for [attack_amount * 2] damage!<center><h3>"
player_hp -= attack_amount
enemy_hp -= attack_amount * 2
enemy_stance = "attack"
else if(enemy_hp <= 30) //will break through the counter when low enough on HP even when smart.
list_temp += "<br><center><h3>[enemy_name] is getting tired of your tricks and breaks through your counter with their [chosen_weapon]!<center><h3>"
player_hp -= attack_amount
enemy_stance = "attack"
else if(!enemy_stance)
var/added_temp
if(rand())
added_temp = "you for [attack_amount + 5] damage!"
player_hp -= attack_amount + 5
enemy_stance = "attack"
else
added_temp = "the wall, breaking their skull in the process and losing [attack_amount] hp!" //[enemy_name] you have a literal dent in your skull
enemy_hp -= attack_amount
enemy_stance = "attack"
list_temp += "<br><center><h3>[enemy_name] grits their teeth and charge right into [added_temp]<center><h3>"
//in the case none of the previous passive triggered, Mainly here to set an enemy stance for passives that needs it like the magical passive.
if(!enemy_stance)
enemy_stance = pick("attack","defensive")
if(enemy_stance == "attack")
player_hp -= attack_amount
list_temp += "<br><center><h3>[enemy_name] attacks you for [attack_amount] points of damage with their [chosen_weapon]<center><h3>"
if(player_stance == "counter_attack")
enemy_hp -= attack_amount * 2
list_temp += "<br><center><h3>You counter [enemy_name]'s attack and deal [attack_amount * 2] points of damage!<center><h3>"
if(enemy_stance == "defensive" && enemy_mp < 15)
list_temp += "<br><center><h3>[enemy_name] take some time to get some mp back!<center><h3> "
enemy_mp += attack_amount
else if (enemy_stance == "defensive" && enemy_mp >= 15 && !(LAZYACCESS(enemy_passive, "magical")))
list_temp += "<br><center><h3>[enemy_name] quickly heal themselves for 5 hp!<center><h3> "
enemy_mp -= 15
enemy_hp += 5
//magical passive trait, recharges MP nearly every turn it's not blasting you with magic.
if(LAZYACCESS(enemy_passive, "magical"))
if(player_mp >= 50)
list_temp += "<br><center><h3>the huge amount of magical energy you have acumulated throws [enemy_name] off balance!<center><h3>"
enemy_mp = 0
LAZYREMOVE(enemy_passive, "magical")
pissed_off++
else if(LAZYACCESS(enemy_passive, "smart") && player_stance == "counter_attack" && enemy_mp >= 20)
list_temp += "<br><center><h3>[enemy_name] blasts you with magic from afar for 10 points of damage before you can counter!<center><h3>"
player_hp -= 10
enemy_mp -= 20
else if(enemy_hp >= 20 && enemy_mp >= 40 && enemy_stance == "defensive")
list_temp += "<br><center><h3>[enemy_name] Blasts you with magic from afar!<center><h3>"
enemy_mp -= 40
player_hp -= 30
enemy_stance = "attack"
else if(enemy_hp < 20 && enemy_mp >= 20 && enemy_stance == "defensive") //it's a pretty expensive spell so they can't spam it that much
list_temp += "<br><center><h3>[enemy_name] heal themselves with magic and gain back 20 hp!<center><h3>"
enemy_hp += 20
enemy_mp -= 30
else
list_temp += "<br><center><h3>[enemy_name]'s magical nature lets them get some mp back!<center><h3>"
enemy_mp += attack_amount
//poisonous passive trait, while it's less damage added than the shotgun it acts up even when the enemy doesn't attack at all.
if(LAZYACCESS(enemy_passive, "poisonous"))
if(weakpoint_check("poisonous","attack","attack","attack"))
list_temp += "<br><center><h3>your flurry of attack throws back the poisonnous gas at [enemy_name] and makes them choke on it!<center><h3> "
enemy_hp -= 5
else
list_temp += "<br><center><h3>the stinky breath of [enemy_name] hurts you for 3 hp!<center><h3> "
player_hp -= 3
//if all passive's weakpoint have been triggered, set finishing_move to TRUE
if(pissed_off >= max_passive && !finishing_move)
list_temp += "<br><center><h3>You have weakened [enemy_name] enough for them to show their weak point, you will do 10 times as much damage with your next attack!<center><h3> "
finishing_move = TRUE
playsound(src, 'sound/arcade/heal.ogg', 50, TRUE, extrarange = -3)
temp = list_temp.Join()
gameover_check(user)
screen_setup(user)
blocked = FALSE
/obj/machinery/computer/arcade/battle/proc/gameover_check(mob/user)
var/xp_gained = 0
if(enemy_hp <= 0)
if(!gameover)
if(timer_id)
deltimer(timer_id)
timer_id = null
if(player_hp <= 0)
player_hp = 1 //let's just pretend the enemy didn't kill you so not both the player and enemy look dead.
gameover = TRUE
temp = "[enemy_name] has fallen! Rejoice!"
playsound(loc, 'sound/arcade/win.ogg', 50, TRUE, extrarange = -3)
blocked = FALSE
temp = "<br><center><h3>[enemy_name] has fallen! Rejoice!<center><h3>"
playsound(loc, 'sound/arcade/win.ogg', 50, TRUE)
if(obj_flags & EMAGGED)
new /obj/effect/spawner/newbomb/timer/syndicate(loc)
@@ -133,78 +402,76 @@
log_game("[key_name(usr)] has outbombed Cuban Pete and been awarded a bomb.")
Reset()
obj_flags &= ~EMAGGED
xp_gained += 100
else
prizevend(user)
xp_gained += 50
SSblackbox.record_feedback("nested tally", "arcade_results", 1, list("win", (obj_flags & EMAGGED ? "emagged":"normal")))
else if ((obj_flags & EMAGGED) && (turtle >= 4))
var/boomamt = rand(5,10)
temp = "[enemy_name] throws a bomb, exploding you for [boomamt] damage!"
playsound(loc, 'sound/arcade/boom.ogg', 50, TRUE, extrarange = -3)
player_hp -= boomamt
else if ((enemy_mp <= 5) && (prob(70)))
var/stealamt = rand(2,3)
temp = "[enemy_name] steals [stealamt] of your power!"
playsound(loc, 'sound/arcade/steal.ogg', 50, TRUE, extrarange = -3)
player_mp -= stealamt
updateUsrDialog()
if (player_mp <= 0)
gameover = TRUE
sleep(turn_speed)
temp = "You have been drained! GAME OVER"
playsound(loc, 'sound/arcade/lose.ogg', 50, TRUE, extrarange = -3)
if(obj_flags & EMAGGED)
usr.gib()
SSblackbox.record_feedback("nested tally", "arcade_results", 1, list("loss", "mana", (obj_flags & EMAGGED ? "emagged":"normal")))
else if ((enemy_hp <= 10) && (enemy_mp > 4))
temp = "[enemy_name] heals for 4 health!"
playsound(loc, 'sound/arcade/heal.ogg', 50, TRUE, extrarange = -3)
enemy_hp += 4
enemy_mp -= 4
else
var/attackamt = rand(3,6)
temp = "[enemy_name] attacks for [attackamt] damage!"
playsound(loc, 'sound/arcade/hit.ogg', 50, TRUE, extrarange = -3)
player_hp -= attackamt
if ((player_mp <= 0) || (player_hp <= 0))
else if(player_hp <= 0)
if(timer_id)
deltimer(timer_id)
timer_id = null
gameover = TRUE
temp = "You have been crushed! GAME OVER"
playsound(loc, 'sound/arcade/lose.ogg', 50, TRUE, extrarange = -3)
temp = "<br><center><h3>You have been crushed! GAME OVER<center><h3>"
playsound(loc, 'sound/arcade/lose.ogg', 50, TRUE)
xp_gained += 10//pity points
if(obj_flags & EMAGGED)
usr.gib()
var/mob/living/living_user = user
if (istype(living_user))
living_user.gib()
SSblackbox.record_feedback("nested tally", "arcade_results", 1, list("loss", "hp", (obj_flags & EMAGGED ? "emagged":"normal")))
blocked = FALSE
return
// if(gameover)
// user?.mind?.adjust_experience(/datum/skill/gaming, xp_gained+1)//always gain at least 1 point of XP
///used to check if the last three move of the player are the one we want in the right order and if the passive's weakpoint has been triggered yet
/obj/machinery/computer/arcade/battle/proc/weakpoint_check(passive,first_move,second_move,third_move)
if(LAZYLEN(last_three_move) < 3)
return FALSE
if(last_three_move[1] == first_move && last_three_move[2] == second_move && last_three_move[3] == third_move && LAZYACCESS(enemy_passive, passive))
LAZYREMOVE(enemy_passive, passive)
pissed_off++
return TRUE
else
return FALSE
/obj/machinery/computer/arcade/battle/Destroy()
enemy_passive = null
weapons = null
last_three_move = null
return ..() //well boys we did it, lists are no more
/obj/machinery/computer/arcade/battle/examine_more(mob/user)
to_chat(user, "<span class='notice'>Scribbled on the side of the Arcade Machine you notice some writing...\
\nmagical -> >=50 power\
\nsmart -> defend, defend, light attack\
\nshotgun -> defend, defend, power attack\
\nshort temper -> counter, counter, counter\
\npoisonous -> light attack, light attack, light attack\
\nchonker -> power attack, power attack, power attack</span>")
return ..()
var/list/msg = list("<span class='notice'><i>You notice some writing scribbled on the side of [src]...</i></span>")
msg += "\t<span class='info'>smart -> defend, defend, light attack</span>"
msg += "\t<span class='info'>shotgun -> defend, defend, power attack</span>"
msg += "\t<span class='info'>short temper -> counter, counter, counter</span>"
msg += "\t<span class='info'>poisonous -> light attack, light attack, light attack</span>"
msg += "\t<span class='info'>chonker -> power attack, power attack, power attack</span>"
return msg
/obj/machinery/computer/arcade/battle/emag_act(mob/user)
. = ..()
if(obj_flags & EMAGGED)
return
to_chat(user, "<span class='warning'>A mesmerizing Rhumba beat starts playing from the arcade machine's speakers!</span>")
temp = "If you die in the game, you die for real!"
player_hp = 30
player_mp = 10
enemy_hp = 45
enemy_mp = 20
temp = "<br><center><h2>If you die in the game, you die for real!<center><h2>"
max_passive = 6
bomb_cooldown = 18
var/gamerSkill = 0
// if(usr?.mind)
// gamerSkill = usr.mind.get_skill_level(/datum/skill/gaming)
enemy_setup(gamerSkill)
enemy_hp += 100 //extra HP just to make cuban pete even more bullshit
player_hp += 30 //the player will also get a few extra HP in order to have a fucking chance
screen_setup(user)
gameover = FALSE
blocked = FALSE
obj_flags |= EMAGGED
@@ -268,7 +268,7 @@
visible_message("<span class='notice'>[src] dispenses [itemname]!</span>", "<span class='notice'>You hear a chime and a clunk.</span>")
DISABLE_BITFIELD(obj_flags, EMAGGED)
else
var/dope_prizes = (area >= 480) ? list(ARCADE_WEIGHT_RARE) : (area >= 256) ? list(ARCADE_WEIGHT_RARE, ARCADE_WEIGHT_TRICK) : null
var/dope_prizes = (area >= 480) ? 6 : (area >= 256) ? 4 : 2
prizevend(user, dope_prizes)
if(game_status == MINESWEEPER_GAME_WON)
@@ -311,12 +311,12 @@
var/new_rows = input(user, "How many rows do you want? (Minimum: 4, Maximum: 30)", "Minesweeper Rows") as null|num
if(!new_rows || !user.canUseTopic(src, !hasSiliconAccessInArea(user)))
return FALSE
new_rows = clamp(new_rows + 1, 4, 30)
new_rows = clamp(new_rows + 1, 4, 20)
playsound(loc, 'sound/arcade/minesweeper_menuselect.ogg', 50, FALSE, extrarange = -3)
var/new_columns = input(user, "How many columns do you want? (Minimum: 4, Maximum: 50)", "Minesweeper Squares") as null|num
if(!new_columns || !user.canUseTopic(src, !hasSiliconAccessInArea(user)))
return FALSE
new_columns = clamp(new_columns + 1, 4, 50)
new_columns = clamp(new_columns + 1, 4, 30)
playsound(loc, 'sound/arcade/minesweeper_menuselect.ogg', 50, FALSE, extrarange = -3)
var/grid_area = (new_rows - 1) * (new_columns - 1)
var/lower_limit = round(grid_area*0.156)
@@ -8,7 +8,7 @@
icon_state = "arcade"
circuit = /obj/item/circuitboard/computer/arcade/amputation
/obj/machinery/computer/arcade/amputation/on_attack_hand(mob/user, act_intent = user.a_intent, unarmed_attack_flags)
/obj/machinery/computer/arcade/amputation/on_attack_hand(mob/user)
if(!iscarbon(user))
return
var/mob/living/carbon/c_user = user
@@ -24,8 +24,13 @@
var/obj/item/bodypart/chopchop = c_user.get_bodypart(which_hand)
chopchop.dismember()
qdel(chopchop)
playsound(loc, 'sound/arcade/win.ogg', 50, TRUE, extrarange = -3)
for(var/i=1; i<=rand(3,5); i++)
prizevend(user)
// user.mind?.adjust_experience(/datum/skill/gaming, 100)
playsound(loc, 'sound/arcade/win.ogg', 50, TRUE)
prizevend(user, rand(3,5))
else
to_chat(c_user, "<span class='notice'>You (wisely) decide against putting your hand in the machine.</span>")
/obj/machinery/computer/arcade/amputation/festive //dispenses wrapped gifts instead of arcade prizes, also known as the ancap christmas tree
name = "Mediborg's Festive Amputation Adventure"
desc = "A picture of a blood-soaked medical cyborg wearing a Santa hat flashes on the screen. The mediborg has a speech bubble that says, \"Put your hand in the machine if you aren't a <b>coward!</b>\""
prize_override = list(/obj/item/a_gift/anything = 1)
@@ -1,5 +1,3 @@
// *** THE ORION TRAIL ** //
#define ORION_TRAIL_WINTURN 9
@@ -15,6 +13,8 @@
#define ORION_TRAIL_COLLISION "Collision"
#define ORION_TRAIL_SPACEPORT "Spaceport"
#define ORION_TRAIL_BLACKHOLE "BlackHole"
#define ORION_TRAIL_OLDSHIP "Old Ship"
#define ORION_TRAIL_SEARCH "Old Ship Search"
#define ORION_STATUS_START 1
#define ORION_STATUS_NORMAL 2
@@ -44,7 +44,8 @@
ORION_TRAIL_LING = 3,
ORION_TRAIL_MALFUNCTION = 2,
ORION_TRAIL_COLLISION = 1,
ORION_TRAIL_SPACEPORT = 2
ORION_TRAIL_SPACEPORT = 2,
ORION_TRAIL_OLDSHIP = 2
)
var/list/stops = list()
var/list/stopblurbs = list()
@@ -55,13 +56,27 @@
var/gameStatus = ORION_STATUS_START
var/canContinueEvent = 0
var/obj/item/radio/Radio
var/list/gamers = list()
var/killed_crew = 0
/obj/machinery/computer/arcade/orion_trail/Initialize()
. = ..()
Radio = new /obj/item/radio(src)
Radio.listening = 0
/obj/machinery/computer/arcade/orion_trail/Destroy()
QDEL_NULL(Radio)
return ..()
/obj/machinery/computer/arcade/orion_trail/kobayashi
name = "Kobayashi Maru control computer"
desc = "A test for cadets"
icon = 'icons/obj/machines/particle_accelerator.dmi'
icon_state = "control_boxp"
events = list("Raiders" = 3, "Interstellar Flux" = 1, "Illness" = 3, "Breakdown" = 2, "Malfunction" = 2, "Collision" = 1, "Spaceport" = 2)
prizes = list(/obj/item/paper/fluff/holodeck/trek_diploma = 1)
prize_override = list(/obj/item/paper/fluff/holodeck/trek_diploma = 1)
settlers = list("Kirk","Worf","Gene")
/obj/machinery/computer/arcade/orion_trail/Reset()
@@ -96,14 +111,52 @@
event = null
gameStatus = ORION_STATUS_NORMAL
lings_aboard = 0
killed_crew = 0
//spaceport junk
spaceport_raided = 0
spaceport_freebie = 0
last_spaceport_action = ""
/obj/machinery/computer/arcade/orion_trail/ui_interact(mob/user)
/obj/machinery/computer/arcade/orion_trail/proc/report_player(mob/gamer)
if(gamers[gamer] == -2)
return // enough harassing them
if(gamers[gamer] == -1)
say("WARNING: Continued antisocial behavior detected: Dispensing self-help literature.")
new /obj/item/paper/pamphlet/violent_video_games(drop_location())
gamers[gamer]--
return
if(!(gamer in gamers))
gamers[gamer] = 0
gamers[gamer]++ // How many times the player has 'prestiged' (massacred their crew)
if(gamers[gamer] > 2 && prob(20 * gamers[gamer]))
Radio.set_frequency(FREQ_SECURITY)
Radio.talk_into(src, "SECURITY ALERT: Crewmember [gamer] recorded displaying antisocial tendencies in [get_area(src)]. Please watch for violent behavior.", FREQ_SECURITY)
Radio.set_frequency(FREQ_MEDICAL)
Radio.talk_into(src, "PSYCH ALERT: Crewmember [gamer] recorded displaying antisocial tendencies in [get_area(src)]. Please schedule psych evaluation.", FREQ_MEDICAL)
gamers[gamer] = -1
gamer.client.give_award(/datum/award/achievement/misc/gamer, gamer) // PSYCH REPORT NOTE: patient kept rambling about how they did it for an "achievement", recommend continued holding for observation
// gamer.mind?.adjust_experience(/datum/skill/gaming, 50) // cheevos make u better
if(!isnull(GLOB.data_core.general))
for(var/datum/data/record/R in GLOB.data_core.general)
if(R.fields["name"] == gamer.name)
R.fields["m_stat"] = "*Unstable*"
return
/obj/machinery/computer/arcade/orion_trail/ui_interact(mob/_user)
. = ..()
if (!isliving(_user))
return
var/mob/living/user = _user
if(fuel <= 0 || food <=0 || settlers.len == 0)
gameStatus = ORION_STATUS_GAMEOVER
event = null
@@ -136,6 +189,8 @@
desc = "Learn how our ancestors got to Orion, and have fun in the process!"
dat += "<P ALIGN=Right><a href='byond://?src=[REF(src)];menu=1'>May They Rest In Peace</a></P>"
// user?.mind?.adjust_experience(/datum/skill/gaming, 10)//learning from your mistakes is the first rule of roguelikes
else if(event)
dat = eventdat
else if(gameStatus == ORION_STATUS_NORMAL)
@@ -174,20 +229,32 @@
return
busy = TRUE
// var/gamerSkillLevel = 0
var/gamerSkill = 0
var/gamerSkillRands = 0
// if(usr?.mind)
// gamerSkillLevel = usr.mind.get_skill_level(/datum/skill/gaming)
// gamerSkill = usr.mind.get_skill_modifier(/datum/skill/gaming, SKILL_PROBS_MODIFIER)
// gamerSkillRands = usr.mind.get_skill_modifier(/datum/skill/gaming, SKILL_RANDS_MODIFIER)
var/xp_gained = 0
if (href_list["continue"]) //Continue your travels
if(gameStatus == ORION_STATUS_NORMAL && !event && turns != 7)
if(turns >= ORION_TRAIL_WINTURN)
win(usr)
xp_gained += 34
else
food -= (alive+lings_aboard)*2
fuel -= 5
if(turns == 2 && prob(30))
if(turns == 2 && prob(30-gamerSkill))
event = ORION_TRAIL_COLLISION
event()
else if(prob(75))
else if(prob(75-gamerSkill))
event = pickweight(events)
if(lings_aboard)
if(event == ORION_TRAIL_LING || prob(55))
if(event == ORION_TRAIL_LING || prob(55-gamerSkill))
event = ORION_TRAIL_LING_ATTACK
event()
turns += 1
@@ -195,15 +262,18 @@
var/mob/living/carbon/M = usr //for some vars
switch(event)
if(ORION_TRAIL_RAIDERS)
if(prob(50))
if(prob(50-gamerSkill))
to_chat(usr, "<span class='userdanger'>You hear battle shouts. The tramping of boots on cold metal. Screams of agony. The rush of venting air. Are you going insane?</span>")
M.hallucination += 30
else
to_chat(usr, "<span class='userdanger'>Something strikes you from behind! It hurts like hell and feel like a blunt weapon, but nothing is there...</span>")
M.take_bodypart_damage(30)
playsound(loc, 'sound/weapons/genhit2.ogg', 100, 1)
playsound(loc, 'sound/weapons/genhit2.ogg', 100, TRUE)
if(ORION_TRAIL_ILLNESS)
var/severity = rand(1,3) //pray to RNGesus. PRAY, PIGS
var/maxSeverity = 3
// if(gamerSkillLevel >= SKILL_LEVEL_EXPERT)
// maxSeverity = 2 //part of gitting gud is rng mitigation
var/severity = rand(1,maxSeverity) //pray to RNGesus. PRAY, PIGS
if(severity == 1)
to_chat(M, "<span class='userdanger'>You suddenly feel slightly nauseated.</span>" )
if(severity == 2)
@@ -215,16 +285,16 @@
sleep(30)
M.vomit(10, distance = 5)
if(ORION_TRAIL_FLUX)
if(prob(75))
if(prob(75-gamerSkill))
M.DefaultCombatKnockdown(60)
say("A sudden gust of powerful wind slams [M] into the floor!")
M.take_bodypart_damage(25)
playsound(loc, 'sound/weapons/genhit.ogg', 100, 1)
playsound(loc, 'sound/weapons/genhit.ogg', 100, TRUE)
else
to_chat(M, "<span class='userdanger'>A violent gale blows past you, and you barely manage to stay standing!</span>")
if(ORION_TRAIL_COLLISION) //by far the most damaging event
if(prob(90))
playsound(loc, 'sound/effects/bang.ogg', 100, 1)
if(prob(90-gamerSkill))
playsound(loc, 'sound/effects/bang.ogg', 100, TRUE)
var/turf/open/floor/F
for(F in orange(1, src))
F.ScrapeAway()
@@ -232,15 +302,15 @@
if(hull)
sleep(10)
say("A new floor suddenly appears around [src]. What the hell?")
playsound(loc, 'sound/weapons/genhit.ogg', 100, 1)
playsound(loc, 'sound/weapons/genhit.ogg', 100, TRUE)
var/turf/open/space/T
for(T in orange(1, src))
T.PlaceOnTop(/turf/open/floor/plating)
else
say("Something slams into the floor around [src] - luckily, it didn't get through!")
playsound(loc, 'sound/effects/bang.ogg', 50, 1)
playsound(loc, 'sound/effects/bang.ogg', 50, TRUE)
if(ORION_TRAIL_MALFUNCTION)
playsound(loc, 'sound/effects/empulse.ogg', 50, 1)
playsound(loc, 'sound/effects/empulse.ogg', 50, TRUE)
visible_message("<span class='danger'>[src] malfunctions, randomizing in-game stats!</span>")
var/oldfood = food
var/oldfuel = fuel
@@ -254,7 +324,7 @@
audible_message("<span class='danger'>[src] lets out a somehow ominous chime.</span>")
food = oldfood
fuel = oldfuel
playsound(loc, 'sound/machines/chime.ogg', 50, 1)
playsound(loc, 'sound/machines/chime.ogg', 50, TRUE)
else if(href_list["newgame"]) //Reset everything
if(gameStatus == ORION_STATUS_START)
@@ -266,6 +336,10 @@
food = 80
fuel = 60
settlers = list("Harry","Larry","Bob")
else if(href_list["search"]) //search old ship
if(event == ORION_TRAIL_OLDSHIP)
event = ORION_TRAIL_SEARCH
event()
else if(href_list["slow"]) //slow down
if(event == ORION_TRAIL_FLUX)
food -= (alive+lings_aboard)*2
@@ -302,11 +376,11 @@
event = null
else if(href_list["blackhole"]) //keep speed past a black hole
if(turns == 7)
if(prob(75))
if(prob(75-gamerSkill))
event = ORION_TRAIL_BLACKHOLE
event()
if(obj_flags & EMAGGED)
playsound(loc, 'sound/effects/supermatter.ogg', 100, 1)
playsound(loc, 'sound/effects/supermatter.ogg', 100, TRUE)
say("A miniature black hole suddenly appears in front of [src], devouring [usr] alive!")
if(isliving(usr))
var/mob/living/L = usr
@@ -328,22 +402,29 @@
else if(href_list["killcrew"]) //shoot a crewmember
if(gameStatus == ORION_STATUS_NORMAL || event == ORION_TRAIL_LING)
var/sheriff = remove_crewmember() //I shot the sheriff
playsound(loc,'sound/weapons/gunshot.ogg', 100, 1)
playsound(loc,'sound/weapons/gunshot.ogg', 100, TRUE)
killed_crew++
var/mob/living/user = usr
if(settlers.len == 0 || alive == 0)
say("The last crewmember [sheriff], shot themselves, GAME OVER!")
if(obj_flags & EMAGGED)
usr.death(0)
obj_flags &= EMAGGED
user.death(FALSE)
gameStatus = ORION_STATUS_GAMEOVER
event = null
if(killed_crew >= 4)
xp_gained -= 15//no cheating by spamming game overs
report_player(usr)
else if(obj_flags & EMAGGED)
if(usr.name == sheriff)
say("The crew of the ship chose to kill [usr.name]!")
usr.death(0)
user.death(FALSE)
if(event == ORION_TRAIL_LING) //only ends the ORION_TRAIL_LING event, since you can do this action in multiple places
event = null
killed_crew-- // the kill was valid
//Spaceport specific interactions
//they get a header because most of them don't reset event (because it's a shop, you leave when you want to)
@@ -356,6 +437,7 @@
fuel -= 10
food -= 10
event()
killed_crew-- // I mean not really but you know
else if(href_list["sellcrew"]) //sell a crewmember
if(gameStatus == ORION_STATUS_MARKET)
@@ -377,15 +459,16 @@
else if(href_list["raid_spaceport"])
if(gameStatus == ORION_STATUS_MARKET)
if(!spaceport_raided)
var/success = min(15 * alive,100) //default crew (4) have a 60% chance
var/success = min(15 * alive + gamerSkill,100) //default crew (4) have a 60% chance
spaceport_raided = 1
var/FU = 0
var/FO = 0
if(prob(success))
FU = rand(5,15)
FO = rand(5,15)
FU = rand(5 + gamerSkillRands,15 + gamerSkillRands)
FO = rand(5 + gamerSkillRands,15 + gamerSkillRands)
last_spaceport_action = "You successfully raided the spaceport! You gained [FU] Fuel and [FO] Food! (+[FU]FU,+[FO]FO)"
xp_gained += 10
else
FU = rand(-5,-15)
FO = rand(-5,-15)
@@ -444,8 +527,7 @@
add_fingerprint(usr)
updateUsrDialog()
busy = FALSE
return
// usr?.mind?.adjust_experience(/datum/skill/gaming, xp_gained+1)
/obj/machinery/computer/arcade/orion_trail/proc/event()
eventdat = "<center><h1>[event]</h1></center>"
@@ -474,6 +556,38 @@
eventdat += "<P ALIGN=Right><a href='byond://?src=[REF(src)];slow=1'>Slow Down</a> <a href='byond://?src=[REF(src)];keepspeed=1'>Continue</a></P>"
eventdat += "<P ALIGN=Right><a href='byond://?src=[REF(src)];close=1'>Close</a></P>"
if(ORION_TRAIL_OLDSHIP)
eventdat += "<br>Your crew spots an old ship floating through space. It might have some supplies, but then again it looks rather unsafe."
eventdat += "<P ALIGN=Right><a href='byond://?src=[REF(src)];search=1'>Search it</a><a href='byond://?src=[REF(src)];eventclose=1'>Leave it</a></P><P ALIGN=Right><a href='byond://?src=[REF(src)];close=1'>Close</a></P>"
canContinueEvent = 1
if(ORION_TRAIL_SEARCH)
switch(rand(100))
if(0 to 15)
var/rescued = add_crewmember()
var/oldfood = rand(1,7)
var/oldfuel = rand(4,10)
food += oldfood
fuel += oldfuel
eventdat += "<br>As you look through it you find some supplies and a living person!"
eventdat += "<br>[rescued] was rescued from the abandoned ship!"
eventdat += "<br>You found [oldfood] <b>Food</b> and [oldfuel] <b>Fuel</b>."
if(15 to 35)
var/lfuel = rand(4,7)
var/deadname = remove_crewmember()
fuel -= lfuel
eventdat += "<br>[deadname] was lost deep in the wreckage, and your own vessel lost [lfuel] <b>Fuel</b> maneuvering to the the abandoned ship."
if(35 to 65)
var/oldfood = rand(5,11)
food += oldfood
engine++
eventdat += "<br>You found [oldfood] <b>Food</b> and some parts amongst the wreck."
else
eventdat += "<br>As you look through the wreck you cannot find much of use."
eventdat += "<P ALIGN=Right><a href='byond://?src=[REF(src)];eventclose=1'>Continue</a></P>"
eventdat += "<P ALIGN=Right><a href='byond://?src=[REF(src)];close=1'>Close</a></P>"
canContinueEvent = 1
if(ORION_TRAIL_ILLNESS)
eventdat += "A deadly illness has been contracted!"
var/deadname = remove_crewmember()
@@ -687,7 +801,7 @@
//Add Random/Specific crewmember
/obj/machinery/computer/arcade/orion_trail/proc/add_crewmember(var/specific = "")
/obj/machinery/computer/arcade/orion_trail/proc/add_crewmember(specific = "")
var/newcrew = ""
if(specific)
newcrew = specific
@@ -703,7 +817,7 @@
//Remove Random/Specific crewmember
/obj/machinery/computer/arcade/orion_trail/proc/remove_crewmember(var/specific = "", var/dont_remove = "")
/obj/machinery/computer/arcade/orion_trail/proc/remove_crewmember(specific = "", dont_remove = "")
var/list/safe2remove = settlers
var/removed = ""
if(dont_remove)
@@ -779,14 +893,14 @@
to_chat(user, "<span class='warning'>You flip the switch on the underside of [src].</span>")
active = 1
visible_message("<span class='notice'>[src] softly beeps and whirs to life!</span>")
playsound(loc, 'sound/machines/defib_SaftyOn.ogg', 25, 1)
playsound(loc, 'sound/machines/defib_SaftyOn.ogg', 25, TRUE)
say("This is ship ID #[rand(1,1000)] to Orion Port Authority. We're coming in for landing, over.")
sleep(20)
visible_message("<span class='warning'>[src] begins to vibrate...</span>")
say("Uh, Port? Having some issues with our reactor, could you check it out? Over.")
sleep(30)
say("Oh, God! Code Eight! CODE EIGHT! IT'S GONNA BL-")
playsound(loc, 'sound/machines/buzz-sigh.ogg', 25, 1)
playsound(loc, 'sound/machines/buzz-sigh.ogg', 25, TRUE)
sleep(3.6)
visible_message("<span class='userdanger'>[src] explodes!</span>")
explosion(loc, 2,4,8, flame_range = 16)
+23 -14
View File
@@ -92,6 +92,7 @@ GLOBAL_LIST_EMPTY(atmos_air_controllers)
icon_screen = "tank"
icon_keyboard = "atmos_key"
circuit = /obj/item/circuitboard/computer/atmos_control
light_color = LIGHT_COLOR_CYAN
var/frequency = FREQ_ATMOS_STORAGE
var/list/sensors = list(
@@ -102,6 +103,20 @@ GLOBAL_LIST_EMPTY(atmos_air_controllers)
ATMOS_GAS_MONITOR_SENSOR_N2O = "Nitrous Oxide Tank",
ATMOS_GAS_MONITOR_SENSOR_AIR = "Mixed Air Tank",
ATMOS_GAS_MONITOR_SENSOR_MIX = "Mix Tank",
// ATMOS_GAS_MONITOR_SENSOR_BZ = "BZ Tank",
// ATMOS_GAS_MONITOR_SENSOR_FREON = "Freon Tank",
// ATMOS_GAS_MONITOR_SENSOR_HALON = "Halon Tank",
// ATMOS_GAS_MONITOR_SENSOR_HEALIUM = "Healium Tank",
// ATMOS_GAS_MONITOR_SENSOR_H2 = "Hydrogen Tank",
// ATMOS_GAS_MONITOR_SENSOR_HYPERNOBLIUM = "Hypernoblium Tank",
// ATMOS_GAS_MONITOR_SENSOR_MIASMA = "Miasma Tank",
// ATMOS_GAS_MONITOR_SENSOR_NO2 = "Nitryl Tank",
// ATMOS_GAS_MONITOR_SENSOR_PLUOXIUM = "Pluoxium Tank",
// ATMOS_GAS_MONITOR_SENSOR_PROTO_NITRATE = "Proto-Nitrate Tank",
// ATMOS_GAS_MONITOR_SENSOR_STIMULUM = "Stimulum Tank",
// ATMOS_GAS_MONITOR_SENSOR_TRITIUM = "Tritium Tank",
// ATMOS_GAS_MONITOR_SENSOR_H2O = "Water Vapor Tank",
// ATMOS_GAS_MONITOR_SENSOR_ZAUKER = "Zauker Tank",
ATMOS_GAS_MONITOR_LOOP_DISTRIBUTION = "Distribution Loop",
ATMOS_GAS_MONITOR_LOOP_ATMOS_WASTE = "Atmos Waste Loop",
ATMOS_GAS_MONITOR_SENSOR_INCINERATOR = "Incinerator Chamber",
@@ -110,7 +125,6 @@ GLOBAL_LIST_EMPTY(atmos_air_controllers)
var/list/sensor_information = list()
var/datum/radio_frequency/radio_connection
light_color = LIGHT_COLOR_CYAN
/obj/machinery/computer/atmos_control/Initialize()
. = ..()
@@ -165,15 +179,10 @@ GLOBAL_LIST_EMPTY(atmos_air_controllers)
/obj/machinery/computer/atmos_control/incinerator
name = "Incinerator Air Control"
sensors = list(ATMOS_GAS_MONITOR_SENSOR_INCINERATOR = "Incinerator Chamber")
ui_x = 400
ui_y = 300
//Toxins mix sensor only
/obj/machinery/computer/atmos_control/toxinsmix
name = "Toxins Mixing Air Control"
sensors = list(ATMOS_GAS_MONITOR_SENSOR_TOXINS_LAB = "Toxins Mixing Chamber")
ui_x = 400
ui_y = 300
/////////////////////////////////////////////////////////////
// LARGE TANK CONTROL
@@ -184,13 +193,9 @@ GLOBAL_LIST_EMPTY(atmos_air_controllers)
var/output_tag
frequency = FREQ_ATMOS_STORAGE
circuit = /obj/item/circuitboard/computer/atmos_control/tank
var/list/input_info
var/list/output_info
ui_x = 500
ui_y = 315
/obj/machinery/computer/atmos_control/tank/oxygen_tank
name = "Oxygen Supply Control"
input_tag = ATMOS_GAS_MONITOR_INPUT_O2
@@ -236,7 +241,7 @@ GLOBAL_LIST_EMPTY(atmos_air_controllers)
// This hacky madness is the evidence of the fact that a lot of machines were never meant to be constructable, im so sorry you had to see this
/obj/machinery/computer/atmos_control/tank/proc/reconnect(mob/user)
var/list/IO = list()
var/datum/radio_frequency/freq = SSradio.return_frequency(FREQ_ATMOS_STORAGE)
var/datum/radio_frequency/freq = SSradio.return_frequency(frequency)
var/list/devices = freq.devices["_default"]
for(var/obj/machinery/atmospherics/components/unary/vent_pump/U in devices)
var/list/text = splittext(U.id_tag, "_")
@@ -252,10 +257,11 @@ GLOBAL_LIST_EMPTY(atmos_air_controllers)
src.output_tag = "[S]_out"
name = "[uppertext(S)] Supply Control"
var/list/new_devices = freq.devices["4"]
sensors.Cut()
for(var/obj/machinery/air_sensor/U in new_devices)
var/list/text = splittext(U.id_tag, "_")
if(text[1] == S)
sensors = list("[S]_sensor" = "Tank")
sensors = list("[S]_sensor" = "[S] Tank")
break
for(var/obj/machinery/atmospherics/components/unary/outlet_injector/U in devices)
@@ -268,13 +274,16 @@ GLOBAL_LIST_EMPTY(atmos_air_controllers)
data["tank"] = TRUE
data["inputting"] = input_info ? input_info["power"] : FALSE
data["inputRate"] = input_info ? input_info["volume_rate"] : 0
data["maxInputRate"] = input_info ? MAX_TRANSFER_RATE : 0
data["outputting"] = output_info ? output_info["power"] : FALSE
data["outputPressure"] = output_info ? output_info["internal"] : 0
data["maxOutputPressure"] = output_info ? MAX_OUTPUT_PRESSURE : 0
return data
/obj/machinery/computer/atmos_control/tank/ui_act(action, params)
if(..() || !radio_connection)
. = ..()
if(. || !radio_connection)
return
var/datum/signal/signal = new(list("sigtype" = "command", "user" = usr))
switch(action)
+64 -30
View File
@@ -3,40 +3,40 @@
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)
if(istype(P, /obj/item/wrench))
if(P.tool_behaviour == TOOL_WRENCH)
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(istype(P, /obj/item/weldingtool))
if(P.tool_behaviour == TOOL_WELDER)
if(!P.tool_start_check(user, amount=0))
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)
qdel(src)
return
if(1)
if(istype(P, /obj/item/wrench))
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
@@ -46,13 +46,13 @@
else if(istype(P, /obj/item/circuitboard) && !circuit)
to_chat(user, "<span class='warning'>This frame does not accept circuit boards of this type!</span>")
return
if(istype(P, /obj/item/screwdriver) && circuit)
if(P.tool_behaviour == TOOL_SCREWDRIVER && circuit)
P.play_tool_sound(src)
to_chat(user, "<span class='notice'>You screw [circuit] into place.</span>")
state = 2
icon_state = "2"
return
if(istype(P, /obj/item/crowbar) && circuit)
if(P.tool_behaviour == TOOL_CROWBAR && circuit)
P.play_tool_sound(src)
to_chat(user, "<span class='notice'>You remove [circuit].</span>")
state = 1
@@ -62,7 +62,7 @@
circuit = null
return
if(2)
if(istype(P, /obj/item/screwdriver) && circuit)
if(P.tool_behaviour == TOOL_SCREWDRIVER && circuit)
P.play_tool_sound(src)
to_chat(user, "<span class='notice'>You unfasten the circuit board.</span>")
state = 1
@@ -71,14 +71,16 @@
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"
return
if(3)
if(istype(P, /obj/item/wirecutters))
if(P.tool_behaviour == TOOL_WIRECUTTER)
P.play_tool_sound(src)
to_chat(user, "<span class='notice'>You remove the cables.</span>")
state = 2
@@ -90,15 +92,17 @@
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"
return
if(4)
if(istype(P, /obj/item/crowbar))
if(P.tool_behaviour == TOOL_CROWBAR)
P.play_tool_sound(src)
to_chat(user, "<span class='notice'>You remove the glass panel.</span>")
state = 3
@@ -106,22 +110,53 @@
var/obj/item/stack/sheet/glass/G = new(drop_location(), 2)
G.add_fingerprint(user)
return
if(istype(P, /obj/item/screwdriver))
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 ..()
//callback proc used on stacks use_tool to stop unnecessary amounts being wasted from spam clicking.
/obj/structure/frame/computer/proc/check_state(target_state)
if(state == target_state)
return TRUE
return FALSE
/obj/structure/frame/computer/deconstruct(disassembled = TRUE)
if(!(flags_1 & NODECONSTRUCT_1))
@@ -133,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
+74 -49
View File
@@ -1,3 +1,5 @@
#define DEFAULT_MAP_SIZE 15
/obj/machinery/computer/security
name = "security camera console"
desc = "Used to access the various cameras on the station."
@@ -8,15 +10,19 @@
var/list/network = list("ss13")
var/obj/machinery/camera/active_camera
/// The turf where the camera was last updated.
var/turf/last_camera_turf
var/list/concurrent_users = list()
// Stuff needed to render the map
var/map_name
var/const/default_map_size = 15
var/obj/screen/cam_screen
var/obj/screen/plane_master/lighting/cam_plane_master
var/obj/screen/map_view/cam_screen
/// All the plane masters that need to be applied.
var/list/cam_plane_masters
var/obj/screen/background/cam_background
interaction_flags_machine = INTERACT_MACHINE_ALLOW_SILICON | INTERACT_MACHINE_SET_MACHINE //| INTERACT_MACHINE_REQUIRES_SIGHT
/obj/machinery/computer/security/Initialize()
. = ..()
// Map name has to start and end with an A-Z character,
@@ -33,18 +39,20 @@
cam_screen.assigned_map = map_name
cam_screen.del_on_map_removal = FALSE
cam_screen.screen_loc = "[map_name]:1,1"
cam_plane_master = new
cam_plane_master.name = "plane_master"
cam_plane_master.assigned_map = map_name
cam_plane_master.del_on_map_removal = FALSE
cam_plane_master.screen_loc = "[map_name]:CENTER"
cam_plane_masters = list()
for(var/plane in subtypesof(/obj/screen/plane_master))
var/obj/screen/instance = new plane()
instance.assigned_map = map_name
instance.del_on_map_removal = FALSE
instance.screen_loc = "[map_name]:CENTER"
cam_plane_masters += instance
cam_background = new
cam_background.assigned_map = map_name
cam_background.del_on_map_removal = FALSE
/obj/machinery/computer/security/Destroy()
qdel(cam_screen)
qdel(cam_plane_master)
QDEL_LIST(cam_plane_masters)
qdel(cam_background)
return ..()
@@ -56,9 +64,10 @@
/obj/machinery/computer/security/ui_interact(mob/user, datum/tgui/ui)
// Update UI
ui = SStgui.try_update_ui(user, src, ui)
// Show static if can't use the camera
if(!active_camera?.can_use())
show_camera_static()
// Update the camera, showing static if necessary and updating data if the location has moved.
update_active_camera_screen()
if(!ui)
var/user_ref = REF(user)
var/is_living = isliving(user)
@@ -72,7 +81,7 @@
use_power(active_power_usage)
// Register map objects
user.client.register_map_obj(cam_screen)
for(var/plane in cam_plane_master)
for(var/plane in cam_plane_masters)
user.client.register_map_obj(plane)
user.client.register_map_obj(cam_background)
// Open UI
@@ -100,6 +109,7 @@
data["cameras"] += list(list(
name = C.c_tag,
))
return data
/obj/machinery/computer/security/ui_act(action, params)
@@ -110,31 +120,51 @@
if(action == "switch_camera")
var/c_tag = params["name"]
var/list/cameras = get_available_cameras()
var/obj/machinery/camera/C = cameras[c_tag]
active_camera = C
var/obj/machinery/camera/selected_camera = cameras[c_tag]
active_camera = selected_camera
playsound(src, get_sfx("terminal_type"), 25, FALSE)
// Show static if can't use the camera
if(!active_camera?.can_use())
show_camera_static()
if(!selected_camera)
return TRUE
var/list/visible_turfs = list()
for(var/turf/T in (C.isXRay() \
? range(C.view_range, C) \
: view(C.view_range, C)))
visible_turfs += T
var/list/bbox = get_bbox_of_atoms(visible_turfs)
var/size_x = bbox[3] - bbox[1] + 1
var/size_y = bbox[4] - bbox[2] + 1
cam_screen.vis_contents = visible_turfs
cam_background.icon_state = "clear"
cam_background.fill_rect(1, 1, size_x, size_y)
update_active_camera_screen()
return TRUE
/obj/machinery/computer/security/proc/update_active_camera_screen()
// Show static if can't use the camera
if(!active_camera?.can_use())
show_camera_static()
return
var/list/visible_turfs = list()
// Is this camera located in or attached to a living thing? If so, assume the camera's loc is the living thing.
var/cam_location = isliving(active_camera.loc) ? active_camera.loc : active_camera
// If we're not forcing an update for some reason and the cameras are in the same location,
// we don't need to update anything.
// Most security cameras will end here as they're not moving.
var/newturf = get_turf(cam_location)
if(last_camera_turf == newturf)
return
// Cameras that get here are moving, and are likely attached to some moving atom such as cyborgs.
last_camera_turf = get_turf(cam_location)
var/list/visible_things = active_camera.isXRay() ? range(active_camera.view_range, cam_location) : view(active_camera.view_range, cam_location)
for(var/turf/visible_turf in visible_things)
visible_turfs += visible_turf
var/list/bbox = get_bbox_of_atoms(visible_turfs)
var/size_x = bbox[3] - bbox[1] + 1
var/size_y = bbox[4] - bbox[2] + 1
cam_screen.vis_contents = visible_turfs
cam_background.icon_state = "clear"
cam_background.fill_rect(1, 1, size_x, size_y)
/obj/machinery/computer/security/ui_close(mob/user)
var/user_ref = REF(user)
var/is_living = isliving(user)
@@ -151,7 +181,7 @@
/obj/machinery/computer/security/proc/show_camera_static()
cam_screen.vis_contents.Cut()
cam_background.icon_state = "scanline2"
cam_background.fill_rect(1, 1, default_map_size, default_map_size)
cam_background.fill_rect(1, 1, DEFAULT_MAP_SIZE, DEFAULT_MAP_SIZE)
// Returns the list of cameras accessible from this computer
/obj/machinery/computer/security/proc/get_available_cameras()
@@ -179,7 +209,7 @@
name = "security camera monitor"
desc = "An old TV hooked into the station's camera network."
icon_state = "television"
icon_keyboard = null
icon_keyboard = "no_keyboard"
icon_screen = "detective_tv"
pass_flags = PASSTABLE
@@ -211,7 +241,7 @@
/obj/machinery/computer/security/qm
name = "\improper Quartermaster's camera console"
desc = "A console with access to the mining, auxillary base and vault camera networks."
desc = "A console with access to the mining, auxiliary base and vault camera networks."
network = list("mine", "auxbase", "vault")
circuit = null
@@ -222,17 +252,12 @@
desc = "Used for watching an empty arena."
icon = 'icons/obj/stationobjs.dmi'
icon_state = "telescreen"
layer = SIGN_LAYER
network = list("thunder")
density = FALSE
circuit = null
light_power = 0
/obj/machinery/computer/security/telescreen/Initialize()
. = ..()
var/turf/T = get_turf_pixel(src)
if(iswallturf(T))
plane = ABOVE_WALL_PLANE
/obj/machinery/computer/security/telescreen/update_icon_state()
icon_state = initial(icon_state)
if(stat & BROKEN)
@@ -246,21 +271,19 @@
network = list("thunder")
density = FALSE
circuit = null
//interaction_flags_atom = NONE // interact() is called by BigClick()
interaction_flags_atom = NONE // interact() is called by BigClick()
var/icon_state_off = "entertainment_blank"
var/icon_state_on = "entertainment"
/* If someone would like to try to get this long-distance viewing thing working, be my guest. I tried everything I could possibly think of and it just refused to operate correctly.
/obj/machinery/computer/security/telescreen/entertainment/Initialize()
. = ..()
RegisterSignal(src, COMSIG_CLICK, .proc/BigClick)
// Bypass clickchain to allow humans to use the telescreen from a distance
/obj/machinery/computer/security/telescreen/entertainment/proc/BigClick()
interact(usr)
SIGNAL_HANDLER
*/
INVOKE_ASYNC(src, /atom.proc/interact, usr)
/obj/machinery/computer/security/telescreen/entertainment/proc/notify(on)
if(on && icon_state == icon_state_off)
@@ -279,8 +302,8 @@
network = list("rd", "aicore", "aiupload", "minisat", "xeno", "test")
/obj/machinery/computer/security/telescreen/circuitry
name = "circuitry telescreen"
desc = "Used for watching the other eggheads from the safety of the circuitry lab."
name = "research telescreen"
desc = "A telescreen with access to the research division's camera network."
network = list("rd")
/obj/machinery/computer/security/telescreen/ce
@@ -324,8 +347,8 @@
network = list("prison")
/obj/machinery/computer/security/telescreen/auxbase
name = "auxillary base monitor"
desc = "A telescreen that connects to the auxillary base's camera."
name = "auxiliary base monitor"
desc = "A telescreen that connects to the auxiliary base's camera."
network = list("auxbase")
/obj/machinery/computer/security/telescreen/minisat
@@ -346,3 +369,5 @@
for(var/i in network)
network -= i
network += "[idnum][i]"
#undef DEFAULT_MAP_SIZE
+9 -11
View File
@@ -133,22 +133,20 @@
to_chat(user, "<span class='notice'>You insert [W].</span>")
playsound(src, 'sound/machines/terminal_insert_disc.ogg', 50, 0)
src.updateUsrDialog()
else if(istype(W, /obj/item/multitool))
var/obj/item/multitool/P = W
if(istype(P.buffer, clonepod_type))
if(get_area(P.buffer) != get_area(src))
else if(W.tool_behaviour == TOOL_MULTITOOL)
if(istype(W.buffer, clonepod_type))
if(get_area(W.buffer) != get_area(src))
to_chat(user, "<font color = #666633>-% Cannot link machines across power zones. Buffer cleared %-</font color>")
P.buffer = null
W.buffer = null
return
to_chat(user, "<font color = #666633>-% Successfully linked [P.buffer] with [src] %-</font color>")
var/obj/machinery/clonepod/pod = P.buffer
to_chat(user, "<font color = #666633>-% Successfully linked [W.buffer] with [src] %-</font color>")
var/obj/machinery/clonepod/pod = W.buffer
if(pod.connected)
pod.connected.DetachCloner(pod)
AttachCloner(pod)
else
P.buffer = src
to_chat(user, "<font color = #666633>-% Successfully stored [REF(P.buffer)] [P.buffer.name] in buffer %-</font color>")
W.buffer = src
to_chat(user, "<font color = #666633>-% Successfully stored [REF(W.buffer)] [W.buffer] in buffer %-</font color>")
return
else
return ..()
@@ -473,7 +471,7 @@
scanner.locked = prev_locked
src.updateUsrDialog()
playsound(src, 'sound/machines/terminal_prompt_confirm.ogg', 50, 0)
/obj/machinery/computer/cloning/proc/scan_occupant(occupant)
var/mob/living/mob_occupant = get_mob_or_brainmob(occupant)
File diff suppressed because it is too large Load Diff
@@ -23,11 +23,10 @@
if(W.tool_behaviour == TOOL_MULTITOOL)
if(!multitool_check_buffer(user, W))
return
var/obj/item/multitool/M = W
if(M.buffer && istype(M.buffer, /obj/machinery/launchpad))
if(W.buffer && istype(W.buffer, /obj/machinery/launchpad))
if(LAZYLEN(launchpads) < maximum_pads)
launchpads |= M.buffer
M.buffer = null
launchpads |= W.buffer
W.buffer = null
to_chat(user, "<span class='notice'>You upload the data from the [W.name]'s buffer.</span>")
else
to_chat(user, "<span class='warning'>[src] cannot handle any more connections!</span>")
@@ -55,11 +55,12 @@
return connected_mechpad
/obj/machinery/computer/mechpad/multitool_act(mob/living/user, obj/item/tool)
if(!tool.tool_behaviour == TOOL_MULTITOOL)
return
if(!multitool_check_buffer(user, tool))
return
var/obj/item/multitool/multitool = tool
if(istype(multitool.buffer, /obj/machinery/mechpad))
var/obj/machinery/mechpad/buffered_console = multitool.buffer
if(istype(tool.buffer, /obj/machinery/mechpad))
var/obj/machinery/mechpad/buffered_console = tool.buffer
if(!(mechpads.len < maximum_pads))
to_chat(user, "<span class='warning'>[src] cannot handle any more connections!</span>")
return
@@ -69,13 +70,13 @@
connected_mechpad = buffered_console
connected_mechpad.connected_console = src
connected_mechpad.id = id
multitool.buffer = null
to_chat(user, "<span class='notice'>You connect the console to the pad with data from the [multitool.name]'s buffer.</span>")
tool.buffer = null
to_chat(user, "<span class='notice'>You connect the console to the pad with data from the [tool.name]'s buffer.</span>")
else
mechpads += buffered_console
LAZYADD(buffered_console.consoles, src)
multitool.buffer = null
to_chat(user, "<span class='notice'>You upload the data from the [multitool.name]'s buffer.</span>")
tool.buffer = null
to_chat(user, "<span class='notice'>You upload the data from the [tool.name]'s buffer.</span>")
/**
* Tries to call the launch proc on the connected mechpad, returns if there is no connected mechpad or there is no mecha on the pad
+104 -67
View File
@@ -1,21 +1,38 @@
/obj/machinery/computer/pod
name = "mass driver launch control"
desc = "A combined blastdoor and mass driver control unit."
// processing_flags = START_PROCESSING_MANUALLY
/// Connected mass driver
var/obj/machinery/mass_driver/connected = null
var/title = "Mass Driver Controls"
/// ID of the launch control
var/id = 1
var/timing = 0
/// If the launch timer counts down
var/timing = FALSE
/// Time before auto launch
var/time = 30
/// Range in which we search for a mass drivers and poddoors nearby
var/range = 4
/// Countdown timer for the mass driver's delayed launch functionality.
COOLDOWN_DECLARE(massdriver_countdown)
/obj/machinery/computer/pod/Initialize()
. = ..()
for(var/obj/machinery/mass_driver/M in range(range, src))
if(M.id == id)
connected = M
break
/obj/machinery/computer/pod/process(delta_time)
if(COOLDOWN_FINISHED(src, massdriver_countdown))
timing = FALSE
// alarm() sleeps, so we want to end processing first and can't rely on return PROCESS_KILL
// end_processing()
STOP_PROCESSING(SSmachines, src)
alarm()
/**
* Initiates launching sequence by checking if all components are functional, opening poddoors, firing mass drivers and then closing poddoors
*/
/obj/machinery/computer/pod/proc/alarm()
if(stat & (NOPOWER|BROKEN))
return
@@ -39,92 +56,112 @@
if(M.id == id)
M.close()
/obj/machinery/computer/pod/ui_interact(mob/user)
/obj/machinery/computer/pod/ui_interact(mob/user, datum/tgui/ui)
ui = SStgui.try_update_ui(user, src, ui)
if(!ui)
ui = new(user, src, "MassDriverControl", name)
ui.open()
/obj/machinery/computer/pod/ui_data(mob/user)
var/list/data = list()
// If the cooldown has finished, just display the time. If the cooldown hasn't finished, display the cooldown.
var/display_time = COOLDOWN_FINISHED(src, massdriver_countdown) ? time : COOLDOWN_TIMELEFT(src, massdriver_countdown) * 0.1
data["connected"] = connected ? TRUE : FALSE
data["seconds"] = round(display_time % 60)
data["minutes"] = round((display_time - data["seconds"]) / 60)
data["timing"] = timing
data["power"] = connected ? connected.power : 0.25
data["poddoor"] = FALSE
for(var/obj/machinery/door/poddoor/door in range(range, src))
if(door.id == id)
data["poddoor"] = TRUE
break
return data
/obj/machinery/computer/pod/ui_act(action, list/params)
. = ..()
if(!allowed(user))
to_chat(user, "<span class='warning'>Access denied.</span>")
if(.)
return
if(!allowed(usr))
to_chat(usr, "<span class='warning'>Access denied.</span>")
return
var/dat = ""
if(connected)
var/d2
if(timing) //door controls do not need timers.
d2 = "<A href='?src=[REF(src)];time=0'>Stop Time Launch</A>"
else
d2 = "<A href='?src=[REF(src)];time=1'>Initiate Time Launch</A>"
dat += "<HR>\nTimer System: [d2]\nTime Left: [DisplayTimeText(time)] <A href='?src=[REF(src)];tp=-30'>-</A> <A href='?src=[REF(src)];tp=-1'>-</A> <A href='?src=[REF(src)];tp=1'>+</A> <A href='?src=[REF(src)];tp=30'>+</A>"
var/temp = ""
var/list/L = list( 0.25, 0.5, 1, 2, 4, 8, 16 )
for(var/t in L)
if(t == connected.power)
temp += "[t] "
switch(action)
if("set_power")
if(!connected)
return
var/value = text2num(params["power"])
if(!value)
return
value = clamp(value, 0.25, 16)
connected.power = value
return TRUE
if("launch")
alarm()
return TRUE
if("time")
timing = !timing
if(timing)
COOLDOWN_START(src, massdriver_countdown, time SECONDS)
// begin_processing()
START_PROCESSING(SSmachines, src)
else
temp += "<A href = '?src=[REF(src)];power=[t]'>[t]</A> "
dat += "<HR>\nPower Level: [temp]<BR>\n<A href = '?src=[REF(src)];alarm=1'>Firing Sequence</A><BR>\n<A href = '?src=[REF(src)];drive=1'>Test Fire Driver</A><BR>\n<A href = '?src=[REF(src)];door=1'>Toggle Outer Door</A><BR>"
else
dat += "<BR>\n<A href = '?src=[REF(src)];door=1'>Toggle Outer Door</A><BR>"
dat += "<BR><BR><A href='?src=[REF(user)];mach_close=computer'>Close</A>"
add_fingerprint(usr)
var/datum/browser/popup = new(user, "computer", title, 400, 500)
popup.set_content(dat)
popup.open()
/obj/machinery/computer/pod/process()
if(!..())
return
if(timing)
if(time > 0)
time = round(time) - 1
else
alarm()
time = 0
timing = 0
updateDialog()
/obj/machinery/computer/pod/Topic(href, href_list)
if(..())
return
if(usr.contents.Find(src) || (in_range(src, usr) && isturf(loc)) || hasSiliconAccessInArea(usr))
usr.set_machine(src)
if(href_list["power"])
var/t = text2num(href_list["power"])
t = min(max(0.25, t), 16)
if(connected)
connected.power = t
if(href_list["alarm"])
alarm()
if(href_list["time"])
timing = text2num(href_list["time"])
if(href_list["tp"])
var/tp = text2num(href_list["tp"])
time += tp
time = min(max(round(time), 0), 120)
if(href_list["door"])
time = COOLDOWN_TIMELEFT(src, massdriver_countdown) * 0.1
COOLDOWN_RESET(src, massdriver_countdown)
// end_processing()
STOP_PROCESSING(SSmachines, src)
return TRUE
if("input")
var/value = text2num(params["adjust"])
if(!value)
return
value = round(time + value)
time = clamp(value, 0, 120)
return TRUE
if("door")
for(var/obj/machinery/door/poddoor/M in range(range, src))
if(M.id == id)
if(M.density)
M.open()
else
M.close()
if(href_list["drive"])
return TRUE
if("driver_test")
for(var/obj/machinery/mass_driver/M in range(range, src))
if(M.id == id)
M.power = connected.power
M.power = connected?.power
M.drive()
updateUsrDialog()
return TRUE
/obj/machinery/computer/pod/old
name = "\improper DoorMex control console"
title = "Door Controls"
icon_state = "oldcomp"
icon_screen = "library"
icon_keyboard = null
icon_keyboard = "no_keyboard"
// /obj/machinery/computer/pod/old/mass_driver_controller
// name = "\improper Mass Driver Controller"
// icon = 'icons/obj/airlock_machines.dmi'
// icon_state = "airlock_control_standby"
// icon_keyboard = "no_keyboard"
// density = FALSE
// /obj/machinery/computer/pod/old/mass_driver_controller/toxinsdriver
// id = MASSDRIVER_TOXINS
// //for maps where pod doors are outside of the standard 4 tile controller detection range (ie Pubbystation)
// /obj/machinery/computer/pod/old/mass_driver_controller/toxinsdriver/longrange
// range = 6
// /obj/machinery/computer/pod/old/mass_driver_controller/chapelgun
// id = MASSDRIVER_CHAPEL
// /obj/machinery/computer/pod/old/mass_driver_controller/trash
// id = MASSDRIVER_DISPOSALS
/obj/machinery/computer/pod/old/syndicate
name = "\improper ProComp Executive IIc"
desc = "The Syndicate operate on a tight budget. Operates external airlocks."
title = "External Airlock Controls"
req_access = list(ACCESS_SYNDICATE)
/obj/machinery/computer/pod/old/swf
+2
View File
@@ -264,6 +264,8 @@ What a mess.*/
active1 = null
if(!( GLOB.data_core.security.Find(active2) ))
active2 = null
if(!authenticated && href_list["choice"] != "Log In") // logging in is the only action you can do if not logged in
return
if(usr.contents.Find(src) || (in_range(src, usr) && isturf(loc)) || hasSiliconAccessInArea(usr) || IsAdminGhost(usr))
usr.set_machine(src)
switch(href_list["choice"])
+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
+75 -50
View File
@@ -21,6 +21,11 @@
circuit = null
qdel(src)
//callback proc used on stacks use_tool to stop unnecessary amounts being wasted from spam clicking.
/obj/structure/frame/proc/check_state(target_state)
if(state == target_state)
return TRUE
return FALSE
/obj/structure/frame/machine
name = "machine frame"
@@ -31,7 +36,7 @@
/obj/structure/frame/machine/examine(user)
. = ..()
if(state == 3 && req_components && req_component_names)
var/hasContent = 0
var/hasContent = FALSE
var/requires = "It requires"
for(var/i = 1 to req_components.len)
@@ -41,10 +46,10 @@
continue
var/use_and = i == req_components.len
requires += "[(hasContent ? (use_and ? ", and" : ",") : "")] [amt] [amt == 1 ? req_component_names[tname] : "[req_component_names[tname]]\s"]"
hasContent = 1
hasContent = TRUE
if(hasContent)
. += requires + "."
. += "[requires]."
else
. += "It does not require any more components."
@@ -71,7 +76,7 @@
amt += req_components[path]
return amt
/obj/structure/frame/machine/attackby(obj/item/P, mob/user, params)
/obj/structure/frame/machine/attackby(obj/item/P, mob/living/user, params)
switch(state)
if(1)
if(istype(P, /obj/item/circuitboard/machine))
@@ -83,50 +88,51 @@
if(istype(P, /obj/item/stack/cable_coil))
if(!P.tool_start_check(user, amount=5))
return
to_chat(user, "<span class='notice'>You start to add cables to the frame...</span>")
if(P.use_tool(src, user, 20, volume=50, amount=5))
if(P.use_tool(src, user, 20, volume=50, amount=5, extra_checks = CALLBACK(src, .proc/check_state, 1)))
to_chat(user, "<span class='notice'>You add cables to the frame.</span>")
state = 2
icon_state = "box_1"
return
if(istype(P, /obj/item/screwdriver) && !anchored)
if(P.tool_behaviour == TOOL_SCREWDRIVER && !anchored)
user.visible_message("<span class='warning'>[user] disassembles the frame.</span>", \
"<span class='notice'>You start to disassemble the frame...</span>", "You hear banging and clanking.")
if(P.use_tool(src, user, 40, volume=50))
"<span class='notice'>You start to disassemble the frame...</span>", "<span class='hear'>You hear banging and clanking.</span>")
if(P.use_tool(src, user, 40, volume=50, extra_checks = CALLBACK(src, .proc/check_state, 1)))
if(state == 1)
to_chat(user, "<span class='notice'>You disassemble the frame.</span>")
var/obj/item/stack/sheet/metal/M = new (loc, 5)
M.add_fingerprint(user)
qdel(src)
return
if(istype(P, /obj/item/wrench))
to_chat(user, "<span class='notice'>You start [anchored ? "un" : ""]securing [name]...</span>")
if(P.use_tool(src, user, 40, volume=75))
if(P.tool_behaviour == TOOL_WRENCH)
to_chat(user, "<span class='notice'>You start [anchored ? "un" : ""]securing [src]...</span>")
if(P.use_tool(src, user, 40, volume=75, extra_checks = CALLBACK(src, .proc/check_state, 1)))
if(state == 1)
to_chat(user, "<span class='notice'>You [anchored ? "un" : ""]secure [name].</span>")
setAnchored(!anchored)
to_chat(user, "<span class='notice'>You [anchored ? "un" : ""]secure [src].</span>")
set_anchored(!anchored)
return
if(2)
if(istype(P, /obj/item/wrench))
to_chat(user, "<span class='notice'>You start [anchored ? "un" : ""]securing [name]...</span>")
if(P.use_tool(src, user, 40, volume=75))
to_chat(user, "<span class='notice'>You [anchored ? "un" : ""]secure [name].</span>")
setAnchored(!anchored)
if(P.tool_behaviour == TOOL_WRENCH)
to_chat(user, "<span class='notice'>You start [anchored ? "un" : ""]securing [src]...</span>")
if(P.use_tool(src, user, 40, volume=75, extra_checks = CALLBACK(src, .proc/check_state, 2)))
to_chat(user, "<span class='notice'>You [anchored ? "un" : ""]secure [src].</span>")
set_anchored(!anchored)
return
if(istype(P, /obj/item/circuitboard/machine))
var/obj/item/circuitboard/machine/B = P
if(!B.build_path)
to_chat(user, "<span class'warning'>This circuitboard seems to be broken.</span>")
to_chat(user, "<span class='warning'>This circuitboard seems to be broken.</span>")
return
if(!anchored && B.needs_anchored)
to_chat(user, "<span class='warning'>The frame needs to be secured first!</span>")
return
if(!user.transferItemToLoc(B, src))
return
playsound(src.loc, 'sound/items/deconstruct.ogg', 50, 1)
playsound(src.loc, 'sound/items/deconstruct.ogg', 50, TRUE)
to_chat(user, "<span class='notice'>You add the circuit board to the frame.</span>")
circuit = B
icon_state = "box_2"
@@ -140,7 +146,7 @@
to_chat(user, "<span class='warning'>This frame does not accept circuit boards of this type!</span>")
return
if(istype(P, /obj/item/wirecutters))
if(P.tool_behaviour == TOOL_WIRECUTTER)
P.play_tool_sound(src)
to_chat(user, "<span class='notice'>You remove the cables.</span>")
state = 1
@@ -149,7 +155,7 @@
return
if(3)
if(istype(P, /obj/item/crowbar))
if(P.tool_behaviour == TOOL_CROWBAR)
P.play_tool_sound(src)
state = 2
circuit.forceMove(drop_location())
@@ -167,35 +173,52 @@
icon_state = "box_1"
return
if(istype(P, /obj/item/wrench) && !circuit.needs_anchored)
to_chat(user, "<span class='notice'>You start [anchored ? "un" : ""]securing [name]...</span>")
if(P.use_tool(src, user, 40, volume=75))
to_chat(user, "<span class='notice'>You [anchored ? "un" : ""]secure [name].</span>")
setAnchored(!anchored)
if(P.tool_behaviour == TOOL_WRENCH && !circuit.needs_anchored)
to_chat(user, "<span class='notice'>You start [anchored ? "un" : ""]securing [src]...</span>")
if(P.use_tool(src, user, 40, volume=75, extra_checks = CALLBACK(src, .proc/check_state, 3)))
to_chat(user, "<span class='notice'>You [anchored ? "un" : ""]secure [src].</span>")
set_anchored(!anchored)
return
if(istype(P, /obj/item/screwdriver))
var/component_check = 1
if(P.tool_behaviour == TOOL_SCREWDRIVER)
var/component_check = TRUE
for(var/R in req_components)
if(req_components[R] > 0)
component_check = 0
component_check = FALSE
break
if(component_check)
P.play_tool_sound(src)
var/obj/machinery/new_machine = new circuit.build_path(loc)
if(new_machine.circuit)
QDEL_NULL(new_machine.circuit)
new_machine.circuit = circuit
new_machine.setAnchored(anchored)
new_machine.on_construction()
for(var/obj/O in new_machine.component_parts)
qdel(O)
new_machine.component_parts = list()
for(var/obj/O in src)
O.moveToNullspace()
new_machine.component_parts += O
circuit.moveToNullspace()
new_machine.RefreshParts()
if(istype(new_machine))
// Machines will init with a set of default components. Move to nullspace so we don't trigger handle_atom_del, then qdel.
// Finally, replace with this frame's parts.
if(new_machine.circuit)
// Move to nullspace and delete.
new_machine.circuit.moveToNullspace()
QDEL_NULL(new_machine.circuit)
for(var/obj/old_part in new_machine.component_parts)
// Move to nullspace and delete.
old_part.moveToNullspace()
qdel(old_part)
// Set anchor state and move the frame's parts over to the new machine.
// Then refresh parts and call on_construction().
new_machine.set_anchored(anchored)
new_machine.component_parts = list()
circuit.forceMove(new_machine)
new_machine.component_parts += circuit
new_machine.circuit = circuit
for(var/obj/new_part in src)
new_part.forceMove(new_machine)
new_machine.component_parts += new_part
new_machine.RefreshParts()
new_machine.on_construction()
// TODO: make sleepers not shit out parts PROPERLY THIS TIME.
new_machine.circuit.moveToNullspace()
qdel(src)
return
@@ -229,12 +252,15 @@
for(var/obj/item/part in added_components)
if(istype(part,/obj/item/stack))
var/obj/item/stack/S = part
var/obj/item/stack/NS = locate(S.merge_type) in components //find a stack to merge with
if(NS)
S.merge(NS)
var/obj/item/stack/incoming_stack = part
for(var/obj/item/stack/merge_stack in components)
if(incoming_stack.can_merge(merge_stack))
incoming_stack.merge(merge_stack)
if(QDELETED(incoming_stack))
break
if(!QDELETED(part)) //If we're a stack and we merged we might not exist anymore
components += part
part.forceMove(src)
to_chat(user, "<span class='notice'>[part.name] applied.</span>")
if(added_components.len)
replacer.play_rped_sound()
@@ -264,9 +290,9 @@
to_chat(user, "<span class='notice'>You add [P] to [src].</span>")
components += P
req_components[I]--
return 1
return TRUE
to_chat(user, "<span class='warning'>You cannot add that to the machine!</span>")
return 0
return FALSE
if(user.a_intent == INTENT_HARM)
return ..()
@@ -277,5 +303,4 @@
for(var/X in components)
var/obj/item/I = X
I.forceMove(loc)
..()
+10 -1
View File
@@ -296,6 +296,12 @@
AM.forceMove(src)
R.module.remove_module(I, TRUE)
else
if(ishuman(mob_occupant))
var/mob/living/carbon/human/H = mob_occupant
if(H.mind && H.client && H.client.prefs && H == H.mind.original_character)
H.SaveTCGCards()
var/list/gear = list()
if(iscarbon(mob_occupant)) // sorry simp-le-mobs deserve no mercy
var/mob/living/carbon/C = mob_occupant
@@ -403,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)
+1 -1
View File
@@ -35,7 +35,7 @@
/obj/machinery/jukebox/attackby(obj/item/O, mob/user, params)
if(!active && !(flags_1 & NODECONSTRUCT_1))
if(istype(O, /obj/item/wrench))
if(O.tool_behaviour == TOOL_WRENCH)
if(!anchored && !isinspace())
to_chat(user,"<span class='notice'>You secure [src] to the floor.</span>")
setAnchored(TRUE)
+5 -3
View File
@@ -99,19 +99,21 @@
return
..()
/obj/machinery/defibrillator_mount/multitool_act(mob/living/user, obj/item/multitool)
/obj/machinery/defibrillator_mount/multitool_act(mob/living/user, obj/item/W)
if(!W.tool_behaviour == TOOL_MULTITOOL)
return
if(!defib)
to_chat(user, "<span class='warning'>There isn't any defibrillator to clamp in!</span>")
return TRUE
if(!clamps_locked)
to_chat(user, "<span class='warning'>[src]'s clamps are disengaged!</span>")
return TRUE
user.visible_message("<span class='notice'>[user] presses [multitool] into [src]'s ID slot...</span>", \
user.visible_message("<span class='notice'>[user] presses [W] into [src]'s ID slot...</span>", \
"<span class='notice'>You begin overriding the clamps on [src]...</span>")
playsound(src, 'sound/machines/click.ogg', 50, TRUE)
if(!do_after(user, 100, target = src) || !clamps_locked)
return
user.visible_message("<span class='notice'>[user] pulses [multitool], and [src]'s clamps slide up.</span>", \
user.visible_message("<span class='notice'>[user] pulses [W], and [src]'s clamps slide up.</span>", \
"<span class='notice'>You override the locking clamps on [src]!</span>")
playsound(src, 'sound/machines/locktoggle.ogg', 50, TRUE)
clamps_locked = FALSE
+1 -1
View File
@@ -26,7 +26,7 @@
return
/obj/structure/barricade/attackby(obj/item/I, mob/user, params)
if(istype(I, /obj/item/weldingtool) && user.a_intent != INTENT_HARM && bar_material == METAL)
if(I.tool_behaviour == TOOL_WELDER && user.a_intent != INTENT_HARM && bar_material == METAL)
if(obj_integrity < max_integrity)
if(!I.tool_start_check(user, amount=0))
return
+20 -15
View File
@@ -864,7 +864,7 @@
update_icon()
return
if(AIRLOCK_SECURITY_METAL)
if(istype(C, /obj/item/weldingtool))
if(C.tool_behaviour == TOOL_WELDER)
if(!C.tool_start_check(user, amount=2))
return
to_chat(user, "<span class='notice'>You begin cutting the panel's shielding...</span>")
@@ -879,10 +879,9 @@
update_icon()
return
if(AIRLOCK_SECURITY_PLASTEEL_I_S)
if(istype(C, /obj/item/crowbar))
var/obj/item/crowbar/W = C
if(C.tool_behaviour == TOOL_CROWBAR)
to_chat(user, "<span class='notice'>You start removing the inner layer of shielding...</span>")
if(W.use_tool(src, user, 40, volume=100))
if(C.use_tool(src, user, 40, volume=100))
if(!panel_open)
return
if(security_level != AIRLOCK_SECURITY_PLASTEEL_I_S)
@@ -896,7 +895,7 @@
update_icon()
return
if(AIRLOCK_SECURITY_PLASTEEL_I)
if(istype(C, /obj/item/weldingtool))
if(C.tool_behaviour == TOOL_WELDER)
if(!C.tool_start_check(user, amount=2))
return
to_chat(user, "<span class='notice'>You begin cutting the inner layer of shielding...</span>")
@@ -909,7 +908,7 @@
security_level = AIRLOCK_SECURITY_PLASTEEL_I_S
return
if(AIRLOCK_SECURITY_PLASTEEL_O_S)
if(istype(C, /obj/item/crowbar))
if(C.tool_behaviour == TOOL_CROWBAR)
to_chat(user, "<span class='notice'>You start removing outer layer of shielding...</span>")
if(C.use_tool(src, user, 40, volume=100))
if(!panel_open)
@@ -922,7 +921,7 @@
spawn_atom_to_turf(/obj/item/stack/sheet/plasteel, user.loc, 1)
return
if(AIRLOCK_SECURITY_PLASTEEL_O)
if(istype(C, /obj/item/weldingtool))
if(C.tool_behaviour == TOOL_WELDER)
if(!C.tool_start_check(user, amount=2))
return
to_chat(user, "<span class='notice'>You begin cutting the outer layer of shielding...</span>")
@@ -935,7 +934,7 @@
security_level = AIRLOCK_SECURITY_PLASTEEL_O_S
return
if(AIRLOCK_SECURITY_PLASTEEL)
if(istype(C, /obj/item/wirecutters))
if(C.tool_behaviour == TOOL_WIRECUTTER)
if(src.hasPower() && src.shock(user, 60)) // Protective grille of wiring is electrified
return
to_chat(user, "<span class='notice'>You start cutting through the outer grille.</span>")
@@ -946,7 +945,7 @@
"<span class='notice'>You cut through \the [src]'s outer grille.</span>")
security_level = AIRLOCK_SECURITY_PLASTEEL_O
return
if(istype(C, /obj/item/screwdriver))
if(C.tool_behaviour == TOOL_SCREWDRIVER)
if(panel_open && detonated)
to_chat(user, "<span class='warning'>[src] has no maintenance panel!</span>")
return
@@ -954,7 +953,7 @@
to_chat(user, "<span class='notice'>You [panel_open ? "open":"close"] the maintenance panel of the airlock.</span>")
C.play_tool_sound(src)
src.update_icon()
else if(istype(C, /obj/item/wirecutters) && note)
else if(C.tool_behaviour == TOOL_WIRECUTTER && note)
user.visible_message("<span class='notice'>[user] cuts down [note] from [src].</span>", "<span class='notice'>You remove [note] from [src].</span>")
C.play_tool_sound(src)
note.forceMove(get_turf(user))
@@ -999,7 +998,9 @@
return ..()
/obj/machinery/door/airlock/try_to_weld(obj/item/weldingtool/W, mob/user)
/obj/machinery/door/airlock/try_to_weld(obj/item/W, mob/user)
if(!W.tool_behaviour == TOOL_WELDER)
return
if(!operating && density)
if(user.a_intent != INTENT_HELP)
if(!W.tool_start_check(user, amount=0))
@@ -1028,12 +1029,14 @@
else
to_chat(user, "<span class='notice'>The airlock doesn't need repairing.</span>")
/obj/machinery/door/airlock/proc/weld_checks(obj/item/weldingtool/W, mob/user)
/obj/machinery/door/airlock/proc/weld_checks(obj/item/W, mob/user)
if(!W.tool_behaviour == TOOL_WELDER)
return
return !operating && density
/obj/machinery/door/airlock/try_to_crowbar(obj/item/I, mob/living/user)
var/beingcrowbarred = null
if(istype(I, /obj/item/crowbar) )
if(I.tool_behaviour == TOOL_CROWBAR)
beingcrowbarred = 1
else
beingcrowbarred = 0
@@ -1059,7 +1062,7 @@
to_chat(user, "<span class='warning'>The airlock's motors resist your efforts to force it!</span>")
else if(locked)
to_chat(user, "<span class='warning'>The airlock's bolts prevent it from being forced!</span>")
else if( !welded && !operating)
else if(!welded && !operating)
if(!beingcrowbarred) //being fireaxe'd
var/obj/item/fireaxe/axe = I
if(!axe.wielded)
@@ -1069,7 +1072,9 @@
else
INVOKE_ASYNC(src, (density ? .proc/open : .proc/close), 2)
if(istype(I, /obj/item/crowbar/power))
if(I.tool_behaviour == TOOL_CROWBAR)
if(!I.can_force_powered)
return
if(hasPower() && isElectrified())
shock(user,100)//it's like sticking a forck in a power socket
return
+2 -2
View File
@@ -658,7 +658,7 @@
/obj/machinery/door/airlock/clockwork/proc/attempt_construction(obj/item/I, mob/living/user)
if(!I || !user || !user.canUseTopic(src))
return 0
else if(istype(I, /obj/item/wrench))
else if(I.tool_behaviour == TOOL_WRENCH)
if(construction_state == GEAR_SECURE)
user.visible_message("<span class='notice'>[user] begins loosening [src]'s cogwheel...</span>", "<span class='notice'>You begin loosening [src]'s cogwheel...</span>")
if(!I.use_tool(src, user, 75, volume=50) || construction_state != GEAR_SECURE)
@@ -674,7 +674,7 @@
playsound(src, 'sound/items/deconstruct.ogg', 50, 1)
construction_state = GEAR_SECURE
return 1
else if(istype(I, /obj/item/crowbar))
else if(I.tool_behaviour == TOOL_CROWBAR)
if(construction_state == GEAR_SECURE)
to_chat(user, "<span class='warning'>[src]'s cogwheel is too tightly secured! Your [I.name] can't reach under it!</span>")
return 1
+3 -1
View File
@@ -173,7 +173,9 @@
/obj/machinery/door/proc/unrestricted_side(mob/M) //Allows for specific side of airlocks to be unrestrected (IE, can exit maint freely, but need access to enter)
return get_dir(src, M) & unres_sides
/obj/machinery/door/proc/try_to_weld(obj/item/weldingtool/W, mob/user)
/obj/machinery/door/proc/try_to_weld(obj/item/W, mob/user)
if(!W.tool_behaviour == TOOL_WELDER)
return
return
/obj/machinery/door/proc/try_to_crowbar(obj/item/I, mob/user)
+3 -1
View File
@@ -123,7 +123,9 @@
/obj/machinery/door/firedoor/try_to_activate_door(mob/user)
return
/obj/machinery/door/firedoor/try_to_weld(obj/item/weldingtool/W, mob/user)
/obj/machinery/door/firedoor/try_to_weld(obj/item/W, mob/user)
if(!W.tool_behaviour == TOOL_WELDER)
return
if(!W.tool_start_check(user, amount=0))
return
user.visible_message("<span class='notice'>[user] starts [welded ? "unwelding" : "welding"] [src].</span>", "<span class='notice'>You start welding [src].</span>")
+2 -2
View File
@@ -243,7 +243,7 @@
add_fingerprint(user)
if(!(flags_1&NODECONSTRUCT_1))
if(istype(I, /obj/item/screwdriver))
if(I.tool_behaviour == TOOL_SCREWDRIVER)
if(density || operating)
to_chat(user, "<span class='warning'>You need to open the door to access the maintenance panel!</span>")
return
@@ -252,7 +252,7 @@
to_chat(user, "<span class='notice'>You [panel_open ? "open":"close"] the maintenance panel of the [src.name].</span>")
return
if(istype(I, /obj/item/crowbar))
if(I.tool_behaviour == TOOL_CROWBAR)
if(panel_open && !density && !operating)
user.visible_message("[user] removes the electronics from the [src.name].", \
"<span class='notice'>You start to remove electronics from the [src.name]...</span>")
+1 -1
View File
@@ -54,7 +54,7 @@ GLOBAL_LIST_EMPTY(doppler_arrays)
return
/obj/machinery/doppler_array/attackby(obj/item/I, mob/user, params)
if(istype(I, /obj/item/wrench))
if(I.tool_behaviour == TOOL_WRENCH)
if(!anchored && !isinspace())
anchored = TRUE
power_change()
+2 -2
View File
@@ -210,13 +210,13 @@
icon_state = icon_on
/obj/machinery/droneDispenser/attackby(obj/item/I, mob/living/user)
if(istype(I, /obj/item/crowbar))
if(I.tool_behaviour == TOOL_CROWBAR)
var/datum/component/material_container/materials = GetComponent(/datum/component/material_container)
materials.retrieve_all()
I.play_tool_sound(src)
to_chat(user, "<span class='notice'>You retrieve the materials from [src].</span>")
else if(istype(I, /obj/item/weldingtool))
else if(I.tool_behaviour == TOOL_WELDER)
if(!(stat & BROKEN))
to_chat(user, "<span class='warning'>[src] doesn't need repairs.</span>")
return
+6 -6
View File
@@ -160,7 +160,7 @@
/obj/machinery/firealarm/attackby(obj/item/W, mob/user, params)
add_fingerprint(user)
if(istype(W, /obj/item/screwdriver) && buildstage == 2)
if(W.tool_behaviour == TOOL_SCREWDRIVER && buildstage == 2)
W.play_tool_sound(src)
panel_open = !panel_open
to_chat(user, "<span class='notice'>The wires have been [panel_open ? "exposed" : "unexposed"].</span>")
@@ -169,7 +169,7 @@
if(panel_open)
if(istype(W, /obj/item/weldingtool) && user.a_intent == INTENT_HELP)
if((W.tool_behaviour == TOOL_WELDER) && user.a_intent == INTENT_HELP)
if(obj_integrity < max_integrity)
if(!W.tool_start_check(user, amount=0))
return
@@ -184,7 +184,7 @@
switch(buildstage)
if(2)
if(istype(W, /obj/item/multitool))
if(W.tool_behaviour == TOOL_MULTITOOL)
detecting = !detecting
if (src.detecting)
user.visible_message("[user] has reconnected [src]'s detecting unit!", "<span class='notice'>You reconnect [src]'s detecting unit.</span>")
@@ -192,7 +192,7 @@
user.visible_message("[user] has disconnected [src]'s detecting unit!", "<span class='notice'>You disconnect [src]'s detecting unit.</span>")
return
else if (istype(W, /obj/item/wirecutters))
else if(W.tool_behaviour == TOOL_WIRECUTTER)
buildstage = 1
W.play_tool_sound(src)
new /obj/item/stack/cable_coil(user.loc, 5)
@@ -215,7 +215,7 @@
update_icon()
return
else if(istype(W, /obj/item/crowbar))
else if(W.tool_behaviour == TOOL_CROWBAR)
user.visible_message("[user.name] removes the electronics from [src.name].", \
"<span class='notice'>You start prying out the circuit...</span>")
if(W.use_tool(src, user, 20, volume=50))
@@ -247,7 +247,7 @@
update_icon()
return
else if(istype(W, /obj/item/wrench))
else if(W.tool_behaviour == TOOL_WRENCH)
user.visible_message("[user] removes the fire alarm assembly from the wall.", \
"<span class='notice'>You remove the fire alarm assembly from the wall.</span>")
var/obj/item/wallframe/firealarm/frame = new /obj/item/wallframe/firealarm()
+6 -6
View File
@@ -57,8 +57,8 @@
//Don't want to render prison breaks impossible
/obj/machinery/flasher/attackby(obj/item/W, mob/user, params)
add_fingerprint(user)
if (istype(W, /obj/item/wirecutters))
if (bulb)
if(W.tool_behaviour == TOOL_WIRECUTTER)
if(bulb)
user.visible_message("[user] begins to disconnect [src]'s flashbulb.", "<span class='notice'>You begin to disconnect [src]'s flashbulb...</span>")
if(W.use_tool(src, user, 30, volume=50) && bulb)
user.visible_message("[user] has disconnected [src]'s flashbulb!", "<span class='notice'>You disconnect [src]'s flashbulb.</span>")
@@ -66,7 +66,7 @@
bulb = null
power_change()
else if (istype(W, /obj/item/assembly/flash/handheld))
else if(istype(W, /obj/item/assembly/flash/handheld))
if (!bulb)
if(!user.transferItemToLoc(W, src))
return
@@ -76,7 +76,7 @@
else
to_chat(user, "<span class='warning'>A flashbulb is already installed in [src]!</span>")
else if (istype(W, /obj/item/wrench))
else if(W.tool_behaviour == TOOL_WRENCH)
if(!bulb)
to_chat(user, "<span class='notice'>You start unsecuring the flasher frame...</span>")
if(W.use_tool(src, user, 40, volume=50))
@@ -173,10 +173,10 @@
flash()
/obj/machinery/flasher/portable/attackby(obj/item/W, mob/user, params)
if (istype(W, /obj/item/wrench))
if(W.tool_behaviour == TOOL_WRENCH)
W.play_tool_sound(src, 100)
if (!anchored && !isinspace())
if(!anchored && !isinspace())
to_chat(user, "<span class='notice'>[src] is now secured.</span>")
add_overlay("[base_state]-s")
setAnchored(TRUE)
+3 -3
View File
@@ -79,7 +79,7 @@ GLOBAL_LIST_EMPTY(network_holopads)
var/secure = FALSE
/// If we are currently calling another holopad
var/calling = FALSE
/*
/obj/machinery/holopad/secure
name = "secure holopad"
desc = "It's a floor-mounted device for projecting holographic images. This one will refuse to auto-connect incoming calls."
@@ -90,7 +90,7 @@ GLOBAL_LIST_EMPTY(network_holopads)
var/obj/item/circuitboard/machine/holopad/board = circuit
board.secure = TRUE
board.build_path = /obj/machinery/holopad/secure
*/
/obj/machinery/holopad/tutorial
resistance_flags = INDESTRUCTIBLE | LAVA_PROOF | FIRE_PROOF | UNACIDABLE | ACID_PROOF
flags_1 = NODECONSTRUCT_1
@@ -372,7 +372,7 @@ GLOBAL_LIST_EMPTY(network_holopads)
if(force_answer_call && world.time > (HC.call_start_time + (HOLOPAD_MAX_DIAL_TIME / 2)))
HC.Answer(src)
break
if(!secure) //HC.head_call &&
if(HC.head_call && !secure)
HC.Answer(src)
break
if(outgoing_call)
+1 -1
View File
@@ -91,7 +91,7 @@
// src.sd_SetLuminosity(0)
/obj/machinery/sparker/attackby(obj/item/W, mob/user, params)
if (istype(W, /obj/item/screwdriver))
if(W.tool_behaviour == TOOL_SCREWDRIVER)
add_fingerprint(user)
src.disable = !src.disable
if (src.disable)
+1 -2
View File
@@ -38,8 +38,7 @@
if(I.tool_behaviour == TOOL_MULTITOOL)
if(!multitool_check_buffer(user, I))
return
var/obj/item/multitool/M = I
M.buffer = src
I.buffer = src
to_chat(user, "<span class='notice'>You save the data in the [I.name]'s buffer.</span>")
return TRUE
+1
View File
@@ -178,6 +178,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
+20 -3
View File
@@ -11,8 +11,24 @@
var/id = 1
var/drive_range = 50 //this is mostly irrelevant since current mass drivers throw into space, but you could make a lower-range mass driver for interstation transport or something I guess.
/obj/machinery/mass_driver/connect_to_shuttle(obj/docking_port/mobile/port, obj/docking_port/stationary/dock, idnum, override=FALSE)
id = "[idnum][id]"
// /obj/machinery/mass_driver/chapelgun
// name = "holy driver"
// id = MASSDRIVER_CHAPEL
// /obj/machinery/mass_driver/toxins
// id = MASSDRIVER_TOXINS
// /obj/machinery/mass_driver/trash
// id = MASSDRIVER_DISPOSALS
// /obj/machinery/mass_driver/Destroy()
// for(var/obj/machinery/computer/pod/control in GLOB.machines)
// if(control.id == id)
// control.connected = null
// return ..()
/obj/machinery/mass_driver/connect_to_shuttle(obj/docking_port/mobile/port, obj/docking_port/stationary/dock)
id = "[port.id]_[id]"
/obj/machinery/mass_driver/proc/drive(amount)
if(stat & (BROKEN|NOPOWER))
@@ -22,6 +38,8 @@
var/atom/target = get_edge_target_turf(src, dir)
for(var/atom/movable/O in loc)
if(!O.anchored || ismecha(O)) //Mechs need their launch platforms.
if(ismob(O) && !isliving(O))
continue
O_limit++
if(O_limit >= 20)
audible_message("<span class='notice'>[src] lets out a screech, it doesn't seem to be able to handle the load.</span>")
@@ -30,7 +48,6 @@
O.throw_at(target, drive_range * power, power)
flick("mass_driver1", src)
/obj/machinery/mass_driver/emp_act(severity)
. = ..()
if (. & EMP_PROTECT_SELF)
+4 -3
View File
@@ -37,13 +37,14 @@
return TRUE
/obj/machinery/mechpad/multitool_act(mob/living/user, obj/item/tool)
if(!tool.tool_behaviour == TOOL_MULTITOOL)
return
if(!panel_open)
return
if(!multitool_check_buffer(user, tool))
return
var/obj/item/multitool/multitool = tool
multitool.buffer = src
to_chat(user, "<span class='notice'>You save the data in the [multitool.name]'s buffer.</span>")
tool.buffer = src
to_chat(user, "<span class='notice'>You save the data in the [tool.name]'s buffer.</span>")
return TRUE
/**
+1 -1
View File
@@ -89,7 +89,7 @@
if(T.intact)
return // prevent intraction when T-scanner revealed
if(istype(I, /obj/item/screwdriver))
if(I.tool_behaviour == TOOL_SCREWDRIVER)
open = !open
user.visible_message("[user] [open ? "opens" : "closes"] the beacon's cover.", "<span class='notice'>You [open ? "open" : "close"] the beacon's cover.</span>")
+6 -3
View File
@@ -127,7 +127,9 @@ Buildable meters
/obj/item/pipe/attack_self(mob/user)
setDir(turn(dir,-90))
/obj/item/pipe/wrench_act(mob/living/user, obj/item/wrench/W)
/obj/item/pipe/wrench_act(mob/living/user, obj/item/W)
if(!W.tool_behaviour == TOOL_WRENCH)
return
if(!isturf(loc))
return TRUE
@@ -196,8 +198,9 @@ Buildable meters
w_class = WEIGHT_CLASS_BULKY
var/piping_layer = PIPING_LAYER_DEFAULT
/obj/item/pipe_meter/wrench_act(mob/living/user, obj/item/wrench/W)
/obj/item/pipe_meter/wrench_act(mob/living/user, obj/item/W)
if(!W.tool_behaviour == TOOL_WRENCH)
return
var/obj/machinery/atmospherics/pipe/pipe
for(var/obj/machinery/atmospherics/pipe/P in loc)
if(P.piping_layer == piping_layer)
@@ -283,9 +283,9 @@
/obj/machinery/porta_turret/attackby(obj/item/I, mob/user, params)
if(stat & BROKEN)
if(istype(I, /obj/item/crowbar))
//If the turret is destroyed, you can remove it with a crowbar to
//try and salvage its components
if(I.tool_behaviour == TOOL_CROWBAR)
//If the turret is destroyed, you can remove it with something
//that acts like a crowbar to try and salvage its components
to_chat(user, "<span class='notice'>You begin prying the metal coverings off...</span>")
if(I.use_tool(src, user, 20))
if(prob(70))
@@ -302,7 +302,7 @@
qdel(src)
return
else if((istype(I, /obj/item/wrench)) && (!on))
else if((I.tool_behaviour == TOOL_WRENCH) && (!on))
if(raised)
return
@@ -329,12 +329,11 @@
to_chat(user, "<span class='notice'>Controls are now [locked ? "locked" : "unlocked"].</span>")
else
to_chat(user, "<span class='alert'>Access denied.</span>")
else if(istype(I, /obj/item/multitool) && !locked)
else if(I.tool_behaviour == TOOL_MULTITOOL && !locked)
if(!multitool_check_buffer(user, I))
return
var/obj/item/multitool/M = I
M.buffer = src
to_chat(user, "<span class='notice'>You add [src] to multitool buffer.</span>")
I.buffer = src
to_chat(user, "<span class='notice'>You add [src] to [I]'s buffer.</span>")
else
return ..()
@@ -393,6 +392,27 @@
spark_system.start() //creates some sparks because they look cool
qdel(cover) //deletes the cover - no need on keeping it there!
//turret healing
/obj/machinery/porta_turret/examine(mob/user)
. = ..()
if(obj_integrity < max_integrity)
. += "<span class='notice'>[src] is damaged, use a lit welder to fix it.</span>"
/obj/machinery/porta_turret/welder_act(mob/living/user, obj/item/I)
. = TRUE
if(cover && obj_integrity < max_integrity)
if(!I.tool_start_check(user, amount=0))
return
user.visible_message("[user] is welding the turret.", \
"<span class='notice'>You begin repairing the turret...</span>", \
"<span class='italics'>You hear welding.</span>")
if(I.use_tool(src, user, 40, volume=50))
obj_integrity = max_integrity
user.visible_message("[user.name] has repaired [src].", \
"<span class='notice'>You finish repairing the turret.</span>")
else
to_chat(user, "<span class='notice'>The turret doesn't need repairing.</span>")
/obj/machinery/porta_turret/process()
//the main machinery process
if(cover == null && anchored) //if it has no cover and is anchored
@@ -927,20 +947,19 @@
if(stat & BROKEN)
return
if (istype(I, /obj/item/multitool))
if(I.tool_behaviour == TOOL_MULTITOOL)
if(!multitool_check_buffer(user, I))
return
var/obj/item/multitool/M = I
if(M.buffer && istype(M.buffer, /obj/machinery/porta_turret))
turrets |= M.buffer
to_chat(user, "<span class='notice'>You link \the [M.buffer] with \the [src].</span>")
if(I.buffer && istype(I.buffer, /obj/machinery/porta_turret))
turrets |= I.buffer
to_chat(user, "<span class='notice'>You link \the [I.buffer] with \the [src].</span>")
return
if (issilicon(user))
if(issilicon(user))
return attack_hand(user)
if ( get_dist(src, user) == 0 ) // trying to unlock the interface
if (allowed(usr))
if(get_dist(src, user) == 0 ) // trying to unlock the interface
if(allowed(usr))
if(obj_flags & EMAGGED)
to_chat(user, "<span class='warning'>The turret control is unresponsive!</span>")
return
@@ -23,14 +23,14 @@
//this is a bit unwieldy but self-explanatory
switch(build_step)
if(PTURRET_UNSECURED) //first step
if(istype(I, /obj/item/wrench) && !anchored)
if(I.tool_behaviour == TOOL_WRENCH && !anchored)
I.play_tool_sound(src, 100)
to_chat(user, "<span class='notice'>You secure the external bolts.</span>")
setAnchored(TRUE)
build_step = PTURRET_BOLTED
return
else if(istype(I, /obj/item/crowbar) && !anchored)
else if(I.tool_behaviour == TOOL_CROWBAR && !anchored)
I.play_tool_sound(src, 75)
to_chat(user, "<span class='notice'>You dismantle the turret construction.</span>")
new /obj/item/stack/sheet/metal( loc, 5)
@@ -48,7 +48,7 @@
to_chat(user, "<span class='warning'>You need two sheets of metal to continue construction!</span>")
return
else if(istype(I, /obj/item/wrench))
else if(I.tool_behaviour == TOOL_WRENCH)
I.play_tool_sound(src, 75)
to_chat(user, "<span class='notice'>You unfasten the external bolts.</span>")
setAnchored(FALSE)
@@ -57,13 +57,13 @@
if(PTURRET_START_INTERNAL_ARMOUR)
if(istype(I, /obj/item/wrench))
if(I.tool_behaviour == TOOL_WRENCH)
I.play_tool_sound(src, 100)
to_chat(user, "<span class='notice'>You bolt the metal armor into place.</span>")
build_step = PTURRET_INTERNAL_ARMOUR_ON
return
else if(istype(I, /obj/item/weldingtool))
else if(I.tool_behaviour == TOOL_WELDER)
if(!I.tool_start_check(user, amount=5)) //uses up 5 fuel
return
@@ -89,7 +89,7 @@
build_step = PTURRET_GUN_EQUIPPED
return
else if(istype(I, /obj/item/wrench))
else if(I.tool_behaviour == TOOL_WRENCH)
I.play_tool_sound(src, 100)
to_chat(user, "<span class='notice'>You remove the turret's metal armor bolts.</span>")
build_step = PTURRET_START_INTERNAL_ARMOUR
@@ -106,7 +106,7 @@
if(PTURRET_SENSORS_ON)
if(istype(I, /obj/item/screwdriver))
if(I.tool_behaviour == TOOL_SCREWDRIVER)
I.play_tool_sound(src, 100)
build_step = PTURRET_CLOSED
to_chat(user, "<span class='notice'>You close the internal access hatch.</span>")
@@ -123,14 +123,14 @@
to_chat(user, "<span class='warning'>You need two sheets of metal to continue construction!</span>")
return
else if(istype(I, /obj/item/screwdriver))
else if(I.tool_behaviour == TOOL_SCREWDRIVER)
I.play_tool_sound(src, 100)
build_step = PTURRET_SENSORS_ON
to_chat(user, "<span class='notice'>You open the internal access hatch.</span>")
return
if(PTURRET_START_EXTERNAL_ARMOUR)
if(istype(I, /obj/item/weldingtool))
if(I.tool_behaviour == TOOL_WELDER)
if(!I.tool_start_check(user, amount=5))
return
@@ -153,7 +153,7 @@
qdel(src)
return
else if(istype(I, /obj/item/crowbar))
else if(I.tool_behaviour == TOOL_CROWBAR)
I.play_tool_sound(src, 75)
to_chat(user, "<span class='notice'>You pry off the turret's exterior armor.</span>")
new /obj/item/stack/sheet/metal(loc, 2)
@@ -37,7 +37,7 @@
/obj/machinery/porta_turret_cover/attackby(obj/item/I, mob/user, params)
if(istype(I, /obj/item/wrench) && !parent_turret.on)
if(I.tool_behaviour == TOOL_WRENCH && !parent_turret.on)
if(parent_turret.raised)
return
@@ -60,10 +60,9 @@
updateUsrDialog()
else
to_chat(user, "<span class='notice'>Access denied.</span>")
else if(istype(I, /obj/item/multitool) && !parent_turret.locked)
var/obj/item/multitool/M = I
M.buffer = parent_turret
to_chat(user, "<span class='notice'>You add [parent_turret] to multitool buffer.</span>")
else if(I.tool_behaviour == TOOL_MULTITOOL && !parent_turret.locked)
I.buffer = parent_turret
to_chat(user, "<span class='notice'>You add [parent_turret] to [I]'s buffer.</span>")
else
return ..()
@@ -25,7 +25,7 @@
switch(stat)
if(1)
// Stat 1
if(istype(W, /obj/item/weldingtool))
if(W.tool_behaviour == TOOL_WELDER)
if(weld(W, user))
to_chat(user, "<span class='notice'>You weld the fan assembly securely into place.</span>")
setAnchored(TRUE)
@@ -46,7 +46,7 @@
forceMove(F)
F.setDir(src.dir)
return
else if(istype(W, /obj/item/weldingtool))
else if(W.tool_behaviour == TOOL_WELDER)
if(weld(W, user))
to_chat(user, "<span class='notice'>You unweld the fan assembly from its place.</span>")
stat = 1
@@ -64,7 +64,9 @@
deconstruct()
return TRUE
/obj/machinery/fan_assembly/proc/weld(obj/item/weldingtool/W, mob/living/user)
/obj/machinery/fan_assembly/proc/weld(obj/item/W, mob/living/user)
if(!W.tool_behaviour == TOOL_WELDER)
return
if(!W.tool_start_check(user, amount=0))
return FALSE
switch(stat)
+6 -8
View File
@@ -55,19 +55,17 @@
return
if(panel_open)
if(istype(I, /obj/item/multitool))
var/obj/item/multitool/M = I
M.buffer = src
if(I.tool_behaviour == TOOL_MULTITOOL)
I.buffer = src
to_chat(user, "<span class='notice'>You save the data in [I]'s buffer. It can now be saved to pads with closed panels.</span>")
return TRUE
else if(istype(I, /obj/item/multitool))
var/obj/item/multitool/M = I
if(istype(M.buffer, /obj/machinery/quantumpad))
if(M.buffer == src)
else if(I.tool_behaviour == TOOL_MULTITOOL)
if(istype(I.buffer, /obj/machinery/quantumpad))
if(I.buffer == src)
to_chat(user, "<span class='warning'>You cannot link a pad to itself!</span>")
return TRUE
else
linked_pad = M.buffer
linked_pad = I.buffer
to_chat(user, "<span class='notice'>You link [src] to the one in [I]'s buffer.</span>")
return TRUE
else
+2 -2
View File
@@ -61,7 +61,7 @@
setCharging()
/obj/machinery/recharger/attackby(obj/item/G, mob/user, params)
if(istype(G, /obj/item/wrench))
if(G.tool_behaviour == TOOL_WRENCH)
if(charging)
to_chat(user, "<span class='notice'>Remove the charging item first!</span>")
return
@@ -102,7 +102,7 @@
if(default_deconstruction_screwdriver(user, "rechargeropen", "recharger0", G))
return
if(panel_open && istype(G, /obj/item/crowbar))
if(panel_open && G.tool_behaviour == TOOL_CROWBAR)
default_deconstruction_crowbar(G)
return
+2 -2
View File
@@ -502,7 +502,7 @@ GLOBAL_LIST_EMPTY(allConsoles)
messages += "<b>From:</b> [linkedsender]<br>[message]"
/obj/machinery/requests_console/attackby(obj/item/O, mob/user, params)
if(istype(O, /obj/item/crowbar))
if(O.tool_behaviour == TOOL_CROWBAR)
if(open)
to_chat(user, "<span class='notice'>You close the maintenance panel.</span>")
open = FALSE
@@ -511,7 +511,7 @@ GLOBAL_LIST_EMPTY(allConsoles)
open = TRUE
update_icon()
return
if(istype(O, /obj/item/screwdriver))
if(O.tool_behaviour == TOOL_SCREWDRIVER)
if(open)
hackState = !hackState
if(hackState)
+3 -3
View File
@@ -146,7 +146,7 @@
return
/obj/machinery/shieldgen/attackby(obj/item/W, mob/user, params)
if(istype(W, /obj/item/screwdriver))
if(W.tool_behaviour == TOOL_SCREWDRIVER)
W.play_tool_sound(src, 100)
panel_open = !panel_open
if(panel_open)
@@ -165,7 +165,7 @@
to_chat(user, "<span class='notice'>You repair \the [src].</span>")
update_icon()
else if(istype(W, /obj/item/wrench))
else if(W.tool_behaviour == TOOL_WRENCH)
if(locked)
to_chat(user, "<span class='warning'>The bolts are covered! Unlocking this would retract the covers.</span>")
return
@@ -343,7 +343,7 @@
return ..()
/obj/machinery/shieldwallgen/attackby(obj/item/W, mob/user, params)
if(istype(W, /obj/item/wrench))
if(W.tool_behaviour == TOOL_WRENCH)
default_unfasten_wrench(user, W, 0)
else if(W.GetID())
+1 -1
View File
@@ -164,7 +164,7 @@
else
to_chat(user, "<span class='warning'>The hatch must be open to insert a power cell!</span>")
return
else if(istype(I, /obj/item/screwdriver))
else if(I.tool_behaviour == TOOL_SCREWDRIVER)
panel_open = !panel_open
user.visible_message("\The [user] [panel_open ? "opens" : "closes"] the hatch on \the [src].", "<span class='notice'>You [panel_open ? "open" : "close"] the hatch on \the [src].</span>")
update_icon()
+1 -1
View File
@@ -75,7 +75,7 @@ GLOBAL_VAR_INIT(singularity_counter, 0)
to_chat(user, "<span class='warning'>You need to screw the beacon to the floor first!</span>")
/obj/machinery/power/singularity_beacon/attackby(obj/item/W, mob/user, params)
if(istype(W, /obj/item/screwdriver))
if(W.tool_behaviour == TOOL_SCREWDRIVER)
if(active)
to_chat(user, "<span class='warning'>You need to deactivate the beacon first!</span>")
return
+5 -5
View File
@@ -112,7 +112,7 @@
. = timer_set
/obj/machinery/syndicatebomb/attackby(obj/item/I, mob/user, params)
if(istype(I, /obj/item/wrench) && can_unanchor)
if(I.tool_behaviour == TOOL_WRENCH && can_unanchor)
if(!anchored)
if(!isturf(loc) || isspaceturf(loc))
to_chat(user, "<span class='notice'>The bomb must be placed on solid ground to attach it.</span>")
@@ -130,7 +130,7 @@
else
to_chat(user, "<span class='warning'>The bolts are locked down!</span>")
else if(istype(I, /obj/item/screwdriver))
else if(I.tool_behaviour == TOOL_SCREWDRIVER)
open_panel = !open_panel
update_icon()
to_chat(user, "<span class='notice'>You [open_panel ? "open" : "close"] the wire panel.</span>")
@@ -138,7 +138,7 @@
else if(is_wire_tool(I) && open_panel)
wires.interact(user)
else if(istype(I, /obj/item/crowbar))
else if(I.tool_behaviour == TOOL_CROWBAR)
if(open_panel && wires.is_all_cut())
if(payload)
to_chat(user, "<span class='notice'>You carefully pry out [payload].</span>")
@@ -158,7 +158,7 @@
to_chat(user, "<span class='notice'>You place [payload] into [src].</span>")
else
to_chat(user, "<span class='warning'>[payload] is already loaded into [src]! You'll have to remove it first.</span>")
else if(istype(I, /obj/item/weldingtool))
else if(I.tool_behaviour == TOOL_WELDER)
if(payload || !wires.is_all_cut() || !open_panel)
return
@@ -436,7 +436,7 @@
qdel(src)
/obj/item/bombcore/chemical/attackby(obj/item/I, mob/user, params)
if(istype(I, /obj/item/crowbar) && beakers.len > 0)
if(I.tool_behaviour == TOOL_CROWBAR && beakers.len > 0)
I.play_tool_sound(src)
for (var/obj/item/B in beakers)
B.forceMove(drop_location())

Some files were not shown because too many files have changed in this diff Show More