Merge branch 'master' into revenant_TK

This commit is contained in:
Artur
2021-01-20 18:27:11 +02:00
414 changed files with 6097 additions and 2811 deletions
+62 -5
View File
@@ -45,6 +45,7 @@ NOTE: there are two lists of areas in the end of this file: centcom and station
ambientsounds = SPACE
blob_allowed = FALSE //Eating up space doesn't count for victory as a blob.
considered_hull_exterior = TRUE
sound_environment = SOUND_AREA_SPACE
/area/space/nearstation
icon_state = "space_near"
@@ -70,6 +71,7 @@ NOTE: there are two lists of areas in the end of this file: centcom and station
blob_allowed = FALSE //Nope, no winning on the asteroid as a blob. Gotta eat the station.
valid_territory = FALSE
ambientsounds = MINING
sound_environment = SOUND_AREA_ASTEROID
/area/asteroid/nearstation
dynamic_lighting = DYNAMIC_LIGHTING_FORCED
@@ -107,7 +109,7 @@ NOTE: there are two lists of areas in the end of this file: centcom and station
/area/maintenance
ambientsounds = MAINTENANCE
valid_territory = FALSE
sound_environment = SOUND_AREA_TUNNEL_ENCLOSED
//Departments
@@ -122,6 +124,7 @@ NOTE: there are two lists of areas in the end of this file: centcom and station
/area/maintenance/department/crew_quarters/bar
name = "Bar Maintenance"
icon_state = "maint_bar"
sound_environment = SOUND_AREA_WOODFLOOR
/area/maintenance/department/crew_quarters/dorms
name = "Dormitory Maintenance"
@@ -265,6 +268,7 @@ NOTE: there are two lists of areas in the end of this file: centcom and station
/area/hallway
nightshift_public_area = NIGHTSHIFT_AREA_PUBLIC
sound_environment = SOUND_AREA_STANDARD_STATION
/area/hallway/primary/aft
name = "Aft Primary Hallway"
@@ -333,30 +337,36 @@ NOTE: there are two lists of areas in the end of this file: centcom and station
name = "Bridge"
icon_state = "bridge"
music = "signal"
sound_environment = SOUND_AREA_STANDARD_STATION
/area/bridge/meeting_room
name = "Heads of Staff Meeting Room"
icon_state = "meeting"
music = null
sound_environment = SOUND_AREA_MEDIUM_SOFTFLOOR
/area/bridge/meeting_room/council
name = "Council Chamber"
icon_state = "meeting"
music = null
sound_environment = SOUND_AREA_MEDIUM_SOFTFLOOR
/area/bridge/showroom/corporate
name = "Corporate Showroom"
icon_state = "showroom"
music = null
sound_environment = SOUND_AREA_MEDIUM_SOFTFLOOR
/area/crew_quarters/heads/captain
name = "Captain's Office"
icon_state = "captain"
clockwork_warp_allowed = FALSE
sound_environment = SOUND_AREA_WOODFLOOR
/area/crew_quarters/heads/captain/private
name = "Captain's Quarters"
icon_state = "captain"
sound_environment = SOUND_AREA_WOODFLOOR
/area/crew_quarters/heads/chief
name = "Chief Engineer's Office"
@@ -401,10 +411,12 @@ NOTE: there are two lists of areas in the end of this file: centcom and station
/area/comms
name = "Communications Relay"
icon_state = "tcomsatcham"
sound_environment = SOUND_AREA_STANDARD_STATION
/area/server
name = "Messaging Server Room"
icon_state = "server"
sound_environment = SOUND_AREA_STANDARD_STATION
//Crew
@@ -413,6 +425,7 @@ NOTE: there are two lists of areas in the end of this file: centcom and station
icon_state = "Sleep"
safe = TRUE
nightshift_public_area = NIGHTSHIFT_AREA_RECREATION
sound_environment = SOUND_AREA_STANDARD_STATION
/area/crew_quarters/dorms/male
name = "Male Dorm"
@@ -431,6 +444,7 @@ NOTE: there are two lists of areas in the end of this file: centcom and station
/area/crew_quarters/toilet
name = "Dormitory Toilets"
icon_state = "toilet"
sound_environment = SOUND_AREA_SMALL_ENCLOSED
/area/crew_quarters/toilet/auxiliary
name = "Auxiliary Restrooms"
@@ -465,6 +479,7 @@ NOTE: there are two lists of areas in the end of this file: centcom and station
name = "Lounge"
icon_state = "yellow"
nightshift_public_area = NIGHTSHIFT_AREA_RECREATION
sound_environment = SOUND_AREA_SMALL_SOFTFLOOR
/area/crew_quarters/arcade
name = "Arcade"
@@ -502,15 +517,18 @@ NOTE: there are two lists of areas in the end of this file: centcom and station
/area/crew_quarters/kitchen/backroom
name = "Kitchen Coldroom"
icon_state = "kitchen"
sound_environment = SOUND_AREA_SMALL_ENCLOSED
/area/crew_quarters/bar
name = "Bar"
icon_state = "bar"
nightshift_public_area = NIGHTSHIFT_AREA_RECREATION
sound_environment = SOUND_AREA_WOODFLOOR
/area/crew_quarters/bar/atrium
name = "Atrium"
icon_state = "bar"
sound_environment = SOUND_AREA_WOODFLOOR
/area/crew_quarters/electronic_marketing_den
name = "Electronic Marketing Den"
@@ -526,6 +544,7 @@ NOTE: there are two lists of areas in the end of this file: centcom and station
/area/crew_quarters/theatre
name = "Theatre"
icon_state = "Theatre"
sound_environment = SOUND_AREA_WOODFLOOR
/area/crew_quarters/theatre/abandoned
name = "Abandoned Theatre"
@@ -546,10 +565,12 @@ NOTE: there are two lists of areas in the end of this file: centcom and station
icon_state = "library"
flags_1 = NONE
nightshift_public_area = NIGHTSHIFT_AREA_RECREATION
sound_environment = SOUND_AREA_LARGE_SOFTFLOOR
/area/library/lounge
name = "Library Lounge"
icon_state = "library"
sound_environment = SOUND_AREA_SMALL_SOFTFLOOR
/area/library/abandoned
name = "Abandoned Library"
@@ -564,6 +585,7 @@ NOTE: there are two lists of areas in the end of this file: centcom and station
clockwork_warp_allowed = FALSE
clockwork_warp_fail = "The consecration here prevents you from warping in."
nightshift_public_area = NIGHTSHIFT_AREA_RECREATION
sound_environment = SOUND_AREA_LARGE_ENCLOSED
/area/chapel/main
name = "Chapel"
@@ -579,6 +601,7 @@ NOTE: there are two lists of areas in the end of this file: centcom and station
/area/chapel/asteroid
name = "Chapel Asteroid"
icon_state = "explored"
sound_environment = SOUND_AREA_ASTEROID
/area/chapel/asteroid/monastery
name = "Monastery Asteroid"
@@ -590,12 +613,14 @@ NOTE: there are two lists of areas in the end of this file: centcom and station
/area/lawoffice
name = "Law Office"
icon_state = "law"
sound_environment = SOUND_AREA_SMALL_SOFTFLOOR
//Engineering
/area/engine
ambientsounds = ENGINEERING
sound_environment = SOUND_AREA_LARGE_ENCLOSED
/area/engine/engine_smes
name = "Engineering SMES"
@@ -613,14 +638,17 @@ NOTE: there are two lists of areas in the end of this file: centcom and station
/area/engine/atmospherics_engine
name = "Atmospherics Engine"
icon_state = "atmos_engine"
sound_environment = SOUND_AREA_LARGE_ENCLOSED
/area/engine/supermatter
name = "Supermatter Engine"
icon_state = "engine_sm"
sound_environment = SOUND_AREA_SMALL_ENCLOSED
/area/engine/break_room
name = "Engineering Foyer"
icon_state = "engine_foyer"
sound_environment = SOUND_AREA_SMALL_ENCLOSED
/area/engine/gravity_generator
name = "Gravity Generator Room"
@@ -635,6 +663,7 @@ NOTE: there are two lists of areas in the end of this file: centcom and station
/area/engine/storage
name = "Engineering Storage"
icon_state = "engi_storage"
sound_environment = SOUND_AREA_SMALL_ENCLOSED
/area/engine/storage_shared
name = "Shared Engineering Storage"
@@ -654,10 +683,12 @@ NOTE: there are two lists of areas in the end of this file: centcom and station
blob_allowed = FALSE
flags_1 = NONE
ambientsounds = ENGINEERING
sound_environment = SOUND_AREA_SPACE
/area/solar/fore
name = "Fore Solar Array"
icon_state = "yellow"
sound_environment = SOUND_AREA_STANDARD_STATION
/area/solar/aft
name = "Aft Solar Array"
@@ -763,6 +794,7 @@ NOTE: there are two lists of areas in the end of this file: centcom and station
icon_state = "gateway"
music = "signal"
ambientsounds = ENGINEERING
sound_environment = SOUND_AREA_STANDARD_STATION
//MedBay
@@ -770,6 +802,7 @@ NOTE: there are two lists of areas in the end of this file: centcom and station
name = "Medical"
icon_state = "medbay3"
ambientsounds = MEDICAL
sound_environment = SOUND_AREA_STANDARD_STATION
/area/medical/clinic
name = "Clinic"
@@ -780,6 +813,7 @@ NOTE: there are two lists of areas in the end of this file: centcom and station
name = "Abandoned Medbay"
icon_state = "medbay3"
music = 'sound/ambience/signal.ogg'
sound_environment = SOUND_AREA_SMALL_ENCLOSED
/area/medical/medbay/central
name = "Medbay Central"
@@ -821,6 +855,7 @@ NOTE: there are two lists of areas in the end of this file: centcom and station
/area/medical/patients_rooms
name = "Patients' Rooms"
icon_state = "patients"
sound_environment = SOUND_AREA_SMALL_SOFTFLOOR
/area/medical/patients_rooms/room_a
name = "Patient Room A"
@@ -839,6 +874,7 @@ NOTE: there are two lists of areas in the end of this file: centcom and station
name = "Morgue"
icon_state = "morgue"
ambientsounds = SPOOKY
sound_environment = SOUND_AREA_SMALL_ENCLOSED
/area/medical/chemistry
name = "Chemistry"
@@ -879,6 +915,7 @@ NOTE: there are two lists of areas in the end of this file: centcom and station
name = "Security"
icon_state = "security"
ambientsounds = HIGHSEC
sound_environment = SOUND_AREA_STANDARD_STATION
/area/security/main
name = "Security Office"
@@ -891,6 +928,7 @@ NOTE: there are two lists of areas in the end of this file: centcom and station
/area/security/courtroom
name = "Courtroom"
icon_state = "courtroom"
sound_environment = SOUND_AREA_LARGE_ENCLOSED
/area/security/prison
name = "Prison Wing"
@@ -903,10 +941,12 @@ NOTE: there are two lists of areas in the end of this file: centcom and station
/area/security/processing/cremation
name = "Security Crematorium"
icon_state = "sec_prison"
sound_environment = SOUND_AREA_SMALL_ENCLOSED
/area/security/warden
name = "Brig Control"
icon_state = "Warden"
sound_environment = SOUND_AREA_SMALL_SOFTFLOOR
/area/security/armory
name = "Armory"
@@ -920,6 +960,7 @@ NOTE: there are two lists of areas in the end of this file: centcom and station
/area/security/detectives_office/private_investigators_office
name = "Private Investigator's Office"
icon_state = "detective"
sound_environment = SOUND_AREA_SMALL_SOFTFLOOR
/area/security/range
name = "Firing Range"
@@ -997,18 +1038,17 @@ NOTE: there are two lists of areas in the end of this file: centcom and station
/area/quartermaster
name = "Quartermasters"
icon_state = "quart"
///////////WORK IN PROGRESS//////////
sound_environment = SOUND_AREA_STANDARD_STATION
/area/quartermaster/sorting
name = "Delivery Office"
icon_state = "cargo_delivery"
sound_environment = SOUND_AREA_STANDARD_STATION
/area/quartermaster/warehouse
name = "Warehouse"
icon_state = "cargo_warehouse"
////////////WORK IN PROGRESS//////////
sound_environment = SOUND_AREA_LARGE_ENCLOSED
/area/quartermaster/office
name = "Cargo Office"
@@ -1017,6 +1057,7 @@ NOTE: there are two lists of areas in the end of this file: centcom and station
/area/quartermaster/storage
name = "Cargo Bay"
icon_state = "cargo_bay"
sound_environment = SOUND_AREA_LARGE_ENCLOSED
/area/quartermaster/qm
name = "Quartermaster's Office"
@@ -1046,6 +1087,7 @@ NOTE: there are two lists of areas in the end of this file: centcom and station
name = "Custodial Closet"
icon_state = "janitor"
flags_1 = NONE
sound_environment = SOUND_AREA_SMALL_ENCLOSED
/area/janitor/aux
name = "Auxiliary Custodial Closet"
@@ -1055,6 +1097,7 @@ NOTE: there are two lists of areas in the end of this file: centcom and station
/area/hydroponics
name = "Hydroponics"
icon_state = "hydro"
sound_environment = SOUND_AREA_STANDARD_STATION
/area/hydroponics/lobby
name = "Hydroponics Lobby"
@@ -1067,6 +1110,7 @@ NOTE: there are two lists of areas in the end of this file: centcom and station
/area/hydroponics/garden/abandoned
name = "Abandoned Garden"
icon_state = "abandoned_garden"
sound_environment = SOUND_AREA_SMALL_ENCLOSED
/area/hydroponics/garden/monastery
name = "Monastery Garden"
@@ -1077,6 +1121,7 @@ NOTE: there are two lists of areas in the end of this file: centcom and station
/area/science
name = "Science Division"
icon_state = "toxlab"
sound_environment = SOUND_AREA_STANDARD_STATION
/area/science/observatory
name = "Research Observatory"
@@ -1167,12 +1212,15 @@ NOTE: there are two lists of areas in the end of this file: centcom and station
/area/science/research/abandoned
name = "Abandoned Research Lab"
icon_state = "medresearch"
sound_environment = SOUND_AREA_SMALL_ENCLOSED
/area/science/nanite
name = "Nanite Lab"
icon_state = "toxmisc"
//Storage
/area/storage
sound_environment = SOUND_AREA_STANDARD_STATION
/area/storage/tools
name = "Auxiliary Tool Storage"
@@ -1242,6 +1290,7 @@ NOTE: there are two lists of areas in the end of this file: centcom and station
name = "Construction Area"
icon_state = "yellow"
ambientsounds = ENGINEERING
sound_environment = SOUND_AREA_STANDARD_STATION
/area/construction/minisat_exterior
name = "Minisat Exterior"
@@ -1250,6 +1299,7 @@ NOTE: there are two lists of areas in the end of this file: centcom and station
/area/construction/mining/aux_base
name = "Auxiliary Base Construction"
icon_state = "yellow"
sound_environment = SOUND_AREA_MEDIUM_SOFTFLOOR
/area/construction/mining/aux_base/closet
name = "Auxiliary Closet Construction"
@@ -1305,6 +1355,8 @@ NOTE: there are two lists of areas in the end of this file: centcom and station
//AI
/area/ai_monitored
sound_environment = SOUND_AREA_STANDARD_STATION
/area/ai_monitored/security/armory
name = "Armory"
@@ -1329,10 +1381,12 @@ NOTE: there are two lists of areas in the end of this file: centcom and station
/area/ai_monitored/turret_protected/ai_upload
name = "AI Upload Chamber"
icon_state = "ai_upload"
sound_environment = SOUND_AREA_SMALL_ENCLOSED
/area/ai_monitored/turret_protected/ai_upload_foyer
name = "AI Upload Access"
icon_state = "ai_foyer"
sound_environment = SOUND_AREA_SMALL_ENCLOSED
/area/ai_monitored/turret_protected/ai
name = "AI Chamber"
@@ -1341,6 +1395,7 @@ NOTE: there are two lists of areas in the end of this file: centcom and station
/area/ai_monitored/turret_protected/aisat
name = "AI Satellite"
icon_state = "ai"
sound_environment = SOUND_ENVIRONMENT_ROOM
/area/ai_monitored/turret_protected/aisat/atmos
name = "AI Satellite Atmos"
@@ -1365,6 +1420,7 @@ NOTE: there are two lists of areas in the end of this file: centcom and station
/area/ai_monitored/turret_protected/aisat_interior
name = "AI Satellite Antechamber"
icon_state = "ai"
sound_environment = SOUND_AREA_LARGE_ENCLOSED
/area/ai_monitored/turret_protected/AIsatextFP
name = "AI Sat Ext"
@@ -1418,6 +1474,7 @@ NOTE: there are two lists of areas in the end of this file: centcom and station
/area/tcommsat/computer
name = "Telecomms Control Room"
icon_state = "tcomsatcomp"
sound_environment = SOUND_AREA_MEDIUM_SOFTFLOOR
/area/tcommsat/server
name = "Telecomms Server Room"
+1
View File
@@ -3,6 +3,7 @@
clockwork_warp_allowed = FALSE
var/list/obj/machinery/camera/motioncameras = list()
var/list/datum/weakref/motionTargets = list()
sound_environment = SOUND_ENVIRONMENT_ROOM
/area/ai_monitored/Initialize(mapload)
. = ..()
+157 -62
View File
@@ -1,16 +1,72 @@
// Areas.dm
/**
* # area
*
* A grouping of tiles into a logical space, mostly used by map editors
*/
/area
level = null
name = "Space"
icon = 'icons/turf/areas.dmi'
icon_state = "unknown"
layer = AREA_LAYER
plane = BLACKNESS_PLANE //Keeping this on the default plane, GAME_PLANE, will make area overlays fail to render on FLOOR_PLANE.
//Keeping this on the default plane, GAME_PLANE, will make area overlays fail to render on FLOOR_PLANE.
plane = BLACKNESS_PLANE
mouse_opacity = MOUSE_OPACITY_TRANSPARENT
invisibility = INVISIBILITY_LIGHTING
var/fire = null
///Whether there is an atmos alarm in this area
var/atmosalm = FALSE
var/poweralm = FALSE
var/lightswitch = TRUE
/// All beauty in this area combined, only includes indoor area.
var/totalbeauty = 0
/// Beauty average per open turf in the area
var/beauty = 0
/// If a room is too big it doesn't have beauty.
var/beauty_threshold = 150
/// For space, the asteroid, lavaland, etc. Used with blueprints or with weather to determine if we are adding a new area (vs editing a station room)
var/outdoors = FALSE
/// Size of the area in open turfs, only calculated for indoors areas.
var/areasize = 0
/// Bonus mood for being in this area
var/mood_bonus = 0
/// Mood message for being here, only shows up if mood_bonus != 0
var/mood_message = "<span class='nicegreen'>This area is pretty nice!\n</span>"
///Will objects this area be needing power?
var/requires_power = TRUE
/// This gets overridden to 1 for space in area/Initialize().
var/always_unpowered = FALSE
var/power_equip = TRUE
var/power_light = TRUE
var/power_environ = TRUE
var/has_gravity = FALSE
var/parallax_movedir = 0
var/list/ambientsounds = GENERIC
flags_1 = CAN_BE_DIRTY_1
var/list/firedoors
var/list/cameras
var/list/firealarms
var/firedoors_last_closed_on = 0
///This datum, if set, allows terrain generation behavior to be ran on Initialize()
// var/datum/map_generator/map_generator
///Used to decide what kind of reverb the area makes sound have
var/sound_environment = SOUND_ENVIRONMENT_NONE
/// CIT SPECIFIC VARS
/// Set in New(); preserves the name set by the map maker, even if renamed by the Blueprints.
var/map_name
@@ -41,29 +97,8 @@
/// Considered space for hull shielding
var/considered_hull_exterior = FALSE
var/fire = null
var/atmos = TRUE
var/atmosalm = FALSE
var/poweralm = TRUE
var/lightswitch = TRUE
var/totalbeauty = 0 //All beauty in this area combined, only includes indoor area.
var/beauty = 0 // Beauty average per open turf in the area
var/beauty_threshold = 150 //If a room is too big it doesn't have beauty.
var/requires_power = TRUE
/// This gets overridden to 1 for space in area/Initialize().
var/always_unpowered = FALSE
/// For space, the asteroid, lavaland, etc. Used with blueprints to determine if we are adding a new area (vs editing a station room)
var/outdoors = FALSE
/// Size of the area in open turfs, only calculated for indoors areas.
var/areasize = 0
var/power_equip = TRUE
var/power_light = TRUE
var/power_environ = TRUE
var/music = null
var/used_equip = 0
var/used_light = 0
@@ -72,7 +107,6 @@
var/static_light = 0
var/static_environ
var/has_gravity = 0
/// Are you forbidden from teleporting to the area? (centcom, mobs, wizard, hand teleporter)
var/noteleport = FALSE
/// Hides area from player Teleport function.
@@ -84,15 +118,6 @@
var/no_air = null
var/parallax_movedir = 0
var/list/ambientsounds = GENERIC
flags_1 = CAN_BE_DIRTY_1
var/list/firedoors
var/list/cameras
var/list/firealarms
var/firedoors_last_closed_on = 0
var/xenobiology_compatible = FALSE //Can the Xenobio management console transverse this area by default?
var/list/canSmoothWithAreas //typecache to limit the areas that atoms in this area can smooth with
@@ -111,10 +136,24 @@
var/nightshift_public_area = NIGHTSHIFT_AREA_NONE //considered a public area for nightshift
/*Adding a wizard area teleport list because motherfucking lag -- Urist*/
/*I am far too lazy to make it a proper list of areas so I'll just make it run the usual telepot routine at the start of the game*/
/**
* A list of teleport locations
*
* Adding a wizard area teleport list because motherfucking lag -- Urist
* I am far too lazy to make it a proper list of areas so I'll just make it run the usual telepot routine at the start of the game
*/
GLOBAL_LIST_EMPTY(teleportlocs)
/**
* Generate a list of turfs you can teleport to from the areas list
*
* Includes areas if they're not a shuttle or not not teleport or have no contents
*
* The chosen turf is the first item in the areas contents that is a station level
*
* The returned list of turfs is sorted by name
*/
/proc/process_teleport_locs()
for(var/V in GLOB.sortedAreas)
var/area/AR = V
@@ -128,11 +167,19 @@ GLOBAL_LIST_EMPTY(teleportlocs)
if (picked && is_station_level(picked.z))
GLOB.teleportlocs[AR.name] = AR
sortTim(GLOB.teleportlocs, /proc/cmp_text_dsc)
// ===
sortTim(GLOB.teleportlocs, /proc/cmp_text_asc)
/**
* Called when an area loads
*
* Adds the item to the GLOB.areas_by_type list based on area type
*/
/area/New()
// This interacts with the map loader, so it needs to be set immediately
// rather than waiting for atoms to initialize.
if (unique)
GLOB.areas_by_type[type] = src
if(!minimap_color) // goes in New() because otherwise it doesn't fucking work
// generate one using the icon_state
if(icon_state && icon_state != "unknown")
@@ -141,14 +188,18 @@ GLOBAL_LIST_EMPTY(teleportlocs)
minimap_color = I.GetPixel(1,1)
else // no icon state? use random.
minimap_color = rgb(rand(50,70),rand(50,70),rand(50,70)) // This interacts with the map loader, so it needs to be set immediately
// rather than waiting for atoms to initialize.
if (unique)
GLOB.areas_by_type[type] = src
return ..()
/**
* Initalize this area
*
* intializes the dynamic area lighting and also registers the area with the z level via
* reg_in_areas_in_z
*
* returns INITIALIZE_HINT_LATELOAD
*/
/area/Initialize()
icon_state = ""
layer = AREA_LAYER
map_name = name // Save the initial (the name set in the map) name of the area.
canSmoothWithAreas = typecacheof(canSmoothWithAreas)
@@ -202,29 +253,55 @@ GLOBAL_LIST_EMPTY(teleportlocs)
return INITIALIZE_HINT_LATELOAD
/**
* Sets machine power levels in the area
*/
/area/LateInitialize()
if(!base_area) //we don't want to run it twice.
power_change() // all machines set to current power level, also updates icon
update_beauty()
/area/proc/reg_in_areas_in_z()
if(contents.len)
var/list/areas_in_z = SSmapping.areas_in_z
var/z
update_areasize()
for(var/i in 1 to contents.len)
var/atom/thing = contents[i]
if(!thing)
continue
z = thing.z
break
if(!z)
WARNING("No z found for [src]")
return
if(!areas_in_z["[z]"])
areas_in_z["[z]"] = list()
areas_in_z["[z]"] += src
/// Soon &trade;
/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)
/area/proc/test_gen()
// 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
*
* Ensures the item is added to the SSmapping.areas_in_z list for this z
*/
/area/proc/reg_in_areas_in_z()
if(!length(contents))
return
var/list/areas_in_z = SSmapping.areas_in_z
update_areasize()
if(!z)
WARNING("No z found for [src]")
return
if(!areas_in_z["[z]"])
areas_in_z["[z]"] = list()
areas_in_z["[z]"] += src
/**
* Destroy an area and clean it up
*
* Removes the area from GLOB.areas_by_type and also stops it processing on SSobj
*
* This is despite the fact that no code appears to put it on SSobj, but
* who am I to argue with old coders
*/
/area/Destroy()
if(GLOB.areas_by_type[type] == src)
GLOB.areas_by_type[type] = null
@@ -244,6 +321,11 @@ GLOBAL_LIST_EMPTY(teleportlocs)
STOP_PROCESSING(SSobj, src)
return ..()
/**
* Generate a power alert for this area
*
* Sends to all ai players, alert consoles, drones and alarm monitor programs in the world
*/
/area/proc/poweralert(state, obj/source)
if (state != poweralm)
poweralm = state
@@ -525,6 +607,13 @@ GLOBAL_LIST_EMPTY(teleportlocs)
used_environ += amount
/**
* Call back when an atom enters an area
*
* Sends signals COMSIG_AREA_ENTERED and COMSIG_ENTER_AREA (to the atom)
*
* If the area has ambience, then it plays some ambience music to the ambience channel
*/
/area/Entered(atom/movable/M, atom/OldLoc)
set waitfor = FALSE
SEND_SIGNAL(src, COMSIG_AREA_ENTERED, M)
@@ -567,6 +656,12 @@ GLOBAL_LIST_EMPTY(teleportlocs)
return FALSE //Too big
beauty = totalbeauty / areasize
/**
* Called when an atom exits an area
*
* Sends signals COMSIG_AREA_EXITED and COMSIG_EXIT_AREA (to the atom)
*/
/area/Exited(atom/movable/M)
SEND_SIGNAL(src, COMSIG_AREA_EXITED, M)
SEND_SIGNAL(M, COMSIG_EXIT_AREA, src) //The atom that exits the area
+1
View File
@@ -9,6 +9,7 @@ Unused icons for new areas are "awaycontent1" ~ "awaycontent30"
icon_state = "away"
has_gravity = STANDARD_GRAVITY
ambientsounds = AWAY_MISSION
sound_environment = SOUND_ENVIRONMENT_ROOM
/area/awaymission/beach
name = "Beach"
+1
View File
@@ -4,6 +4,7 @@
dynamic_lighting = DYNAMIC_LIGHTING_DISABLED
flags_1 = 0
hidden = TRUE
sound_environment = SOUND_ENVIRONMENT_PADDED_CELL
var/obj/machinery/computer/holodeck/linked
var/restricted = 0 // if true, program goes on emag list
+3
View File
@@ -19,6 +19,7 @@
flags_1 = NONE
ambientsounds = MINING
flora_allowed = FALSE
sound_environment = SOUND_AREA_STANDARD_STATION
/area/mine/unexplored
name = "Mine"
@@ -86,6 +87,7 @@
has_gravity = STANDARD_GRAVITY
flags_1 = NONE
flora_allowed = TRUE
sound_environment = SOUND_AREA_LAVALAND
/area/lavaland/surface
name = "Lavaland"
@@ -139,6 +141,7 @@
flags_1 = NONE
flora_allowed = TRUE
blob_allowed = FALSE
sound_environment = SOUND_AREA_ICEMOON
/area/icemoon/surface
name = "Icemoon"
+1
View File
@@ -7,6 +7,7 @@
hidden = TRUE
dynamic_lighting = DYNAMIC_LIGHTING_FORCED
ambientsounds = RUINS
sound_environment = SOUND_ENVIRONMENT_STONEROOM
/area/ruin/unpowered
+1
View File
@@ -12,6 +12,7 @@
icon_state = "shuttle"
// Loading the same shuttle map at a different time will produce distinct area instances.
unique = FALSE
sound_environment = SOUND_ENVIRONMENT_ROOM
/area/shuttle/Initialize()
if(!canSmoothWithAreas)
+146 -27
View File
@@ -1,12 +1,22 @@
/**
* The base type for nearly all physical objects in SS13
* Lots and lots of functionality lives here, although in general we are striving to move
* as much as possible to the components/elements system
*/
/atom
layer = TURF_LAYER
plane = GAME_PLANE
var/level = 2
var/article // If non-null, overrides a/an/some in all cases
appearance_flags = TILE_BOUND
var/level = 2
///If non-null, overrides a/an/some in all cases
var/article
///First atom flags var
var/flags_1 = NONE
///Intearaction flags
var/interaction_flags_atom = NONE
var/datum/reagents/reagents = null
var/flags_ricochet = NONE
@@ -15,35 +25,52 @@
///When a projectile ricochets off this atom, it deals the normal damage * this modifier to this atom
var/ricochet_damage_mod = 0.33
//This atom's HUD (med/sec, etc) images. Associative list.
///Reagents holder
var/datum/reagents/reagents = null
///This atom's HUD (med/sec, etc) images. Associative list.
var/list/image/hud_list = null
//HUD images that this atom can provide.
///HUD images that this atom can provide.
var/list/hud_possible
//Value used to increment ex_act() if reactionary_explosions is on
///Value used to increment ex_act() if reactionary_explosions is on
var/explosion_block = 0
var/list/atom_colours //used to store the different colors on an atom
//its inherent color, the colored paint applied on it, special color effect etc...
/**
* used to store the different colors on an atom
*
* its inherent color, the colored paint applied on it, special color effect etc...
*/
var/list/atom_colours
var/list/remove_overlays // a very temporary list of overlays to remove
var/list/add_overlays // a very temporary list of overlays to add
var/list/managed_vis_overlays //vis overlays managed by SSvis_overlays to automaticaly turn them like other overlays
///overlays managed by update_overlays() to prevent removing overlays that weren't added by the same proc
/// a very temporary list of overlays to remove
var/list/remove_overlays
/// a very temporary list of overlays to add
var/list/add_overlays
///vis overlays managed by SSvis_overlays to automaticaly turn them like other overlays
var/list/managed_vis_overlays
///overlays managed by [update_overlays][/atom/proc/update_overlays] to prevent removing overlays that weren't added by the same proc
var/list/managed_overlays
///Proximity monitor associated with this atom
var/datum/proximity_monitor/proximity_monitor
///Last fingerprints to touch this atom
var/fingerprintslast
var/list/filter_data //For handling persistent filters
///Price of an item in a vending machine, overriding the base vending machine price. Define in terms of paycheck defines as opposed to raw numbers.
var/custom_price
///Price of an item in a vending machine, overriding the premium vending machine price. Define in terms of paycheck defines as opposed to raw numbers.
var/custom_premium_price
//List of datums orbiting this atom
var/datum/component/orbiter/orbiters
var/rad_flags = NONE // Will move to flags_1 when i can be arsed to
/// Radiation insulation types
var/rad_insulation = RAD_NO_INSULATION
///The custom materials this atom is made of, used by a lot of things like furniture, walls, and floors (if I finish the functionality, that is.)
@@ -72,6 +99,16 @@
///Mobs that are currently do_after'ing this atom, to be cleared from on Destroy()
var/list/targeted_by
/**
* Called when an atom is created in byond (built in engine proc)
*
* Not a lot happens here in SS13 code, as we offload most of the work to the
* [Intialization][/atom/proc/Initialize] proc, mostly we run the preloader
* if the preloader is being used and then call [InitAtom][/datum/controller/subsystem/atoms/proc/InitAtom] of which the ultimate
* result is that the Intialize proc is called.
*
* We also generate a tag here if the DF_USE_TAG flag is set on the atom
*/
/atom/New(loc, ...)
//atom creation method that preloads variables at creation
if(GLOB.use_preloader && (src.type == GLOB._preloader.target_path))//in case the instanciated atom is creating other atoms in New()
@@ -87,24 +124,50 @@
//we were deleted
return
//Called after New if the map is being loaded. mapload = TRUE
//Called from base of New if the map is not being loaded. mapload = FALSE
//This base must be called or derivatives must set initialized to TRUE
//must not sleep
//Other parameters are passed from New (excluding loc), this does not happen if mapload is TRUE
//Must return an Initialize hint. Defined in __DEFINES/subsystems.dm
//Note: the following functions don't call the base for optimization and must copypasta:
// /turf/Initialize
// /turf/open/space/Initialize
/**
* The primary method that objects are setup in SS13 with
*
* we don't use New as we have better control over when this is called and we can choose
* to delay calls or hook other logic in and so forth
*
* During roundstart map parsing, atoms are queued for intialization in the base atom/New(),
* After the map has loaded, then Initalize is called on all atoms one by one. NB: this
* is also true for loading map templates as well, so they don't Initalize until all objects
* in the map file are parsed and present in the world
*
* If you're creating an object at any point after SSInit has run then this proc will be
* immediately be called from New.
*
* mapload: This parameter is true if the atom being loaded is either being intialized during
* the Atom subsystem intialization, or if the atom is being loaded from the map template.
* If the item is being created at runtime any time after the Atom subsystem is intialized then
* it's false.
*
* You must always call the parent of this proc, otherwise failures will occur as the item
* will not be seen as initalized (this can lead to all sorts of strange behaviour, like
* the item being completely unclickable)
*
* You must not sleep in this proc, or any subprocs
*
* Any parameters from new are passed through (excluding loc), naturally if you're loading from a map
* there are no other arguments
*
* Must return an [initialization hint][INITIALIZE_HINT_NORMAL] or a runtime will occur.
*
* Note: the following functions don't call the base for optimization and must copypasta handling:
* * [/turf/proc/Initialize]
* * [/turf/open/space/proc/Initialize]
*/
/atom/proc/Initialize(mapload, ...)
// SHOULD_NOT_SLEEP(TRUE)
SHOULD_CALL_PARENT(TRUE)
if(flags_1 & INITIALIZED_1)
stack_trace("Warning: [src]([type]) initialized multiple times!")
flags_1 |= INITIALIZED_1
if(loc)
SEND_SIGNAL(loc, COMSIG_ATOM_CREATED, src) /// Sends a signal that the new atom `src`, has been created at `loc`
//atom color stuff
if(color)
add_atom_colour(color, FIXED_COLOUR_PRIORITY)
@@ -126,14 +189,34 @@
return INITIALIZE_HINT_NORMAL
//called if Initialize returns INITIALIZE_HINT_LATELOAD
/**
* Late Intialization, for code that should run after all atoms have run Intialization
*
* To have your LateIntialize proc be called, your atoms [Initalization][/atom/proc/Initialize]
* proc must return the hint
* [INITIALIZE_HINT_LATELOAD] otherwise you will never be called.
*
* useful for doing things like finding other machines on GLOB.machines because you can guarantee
* that all atoms will actually exist in the "WORLD" at this time and that all their Intialization
* code has been run
*/
/atom/proc/LateInitialize()
return
set waitfor = FALSE
// Put your AddComponent() calls here
/// Put your [AddComponent] calls here
/atom/proc/ComponentInitialize()
return
/**
* Top level of the destroy chain for most atoms
*
* Cleans up the following:
* * Removes alternate apperances from huds that see them
* * qdels the reagent holder from atoms if it exists
* * clears the orbiters list
* * clears overlays and priority overlays
* * clears the light object
*/
/atom/Destroy()
if(alternate_appearances)
for(var/K in alternate_appearances)
@@ -143,6 +226,8 @@
if(reagents)
qdel(reagents)
orbiters = null // The component is attached to us normaly and will be deleted elsewhere
LAZYCLEARLIST(overlays)
for(var/i in targeted_by)
@@ -179,6 +264,16 @@
/atom/proc/CanPass(atom/movable/mover, turf/target)
return !density
/**
* Is this atom currently located on centcom
*
* Specifically, is it on the z level and within the centcom areas
*
* You can also be in a shuttleshuttle during endgame transit
*
* Used in gamemode to identify mobs who have escaped and for some other areas of the code
* who don't want atoms where they shouldn't be
*/
/atom/proc/onCentCom()
var/turf/T = get_turf(src)
if(!T)
@@ -209,6 +304,13 @@
if(T in shuttle_area)
return TRUE
/**
* Is the atom in any of the centcom syndicate areas
*
* Either in the syndie base on centcom, or any of their shuttles
*
* Also used in gamemode code for win conditions
*/
/atom/proc/onSyndieBase()
var/turf/T = get_turf(src)
if(!T)
@@ -222,6 +324,23 @@
return FALSE
/**
* Is the atom in an away mission
*
* Must be in the away mission z-level to return TRUE
*
* Also used in gamemode code for win conditions
*/
/atom/proc/onAwayMission()
var/turf/T = get_turf(src)
if(!T)
return FALSE
if(is_away_level(T.z))
return TRUE
return FALSE
/atom/proc/attack_hulk(mob/living/carbon/human/user, does_attack_animation = FALSE)
SEND_SIGNAL(src, COMSIG_ATOM_HULK_ATTACK, user)
if(does_attack_animation)
@@ -415,7 +534,7 @@
/// Updates the overlays of the atom
/atom/proc/update_overlays()
SHOULD_CALL_PARENT(1)
SHOULD_CALL_PARENT(TRUE)
. = list()
SEND_SIGNAL(src, COMSIG_ATOM_UPDATE_OVERLAYS, .)
+199 -111
View File
@@ -1,5 +1,7 @@
/atom/movable
layer = OBJ_LAYER
glide_size = 8
SET_APPEARANCE_FLAGS(TILE_BOUND | PIXEL_SCALE)
var/last_move = null
var/last_move_time = 0
var/anchored = FALSE
@@ -28,8 +30,6 @@
var/atom/movable/moving_from_pull //attempt to resume grab after moving instead of before.
var/list/client_mobs_in_contents // This contains all the client mobs within this container
var/list/acted_explosions //for explosion dodging
glide_size = 8
appearance_flags = TILE_BOUND|PIXEL_SCALE
var/datum/forced_movement/force_moving = null //handled soley by forced_movement.dm
var/movement_type = GROUND //Incase you have multiple types, you automatically use the most useful one. IE: Skating on ice, flippers on water, flying over chasm/space, etc.
var/atom/movable/pulling
@@ -59,6 +59,42 @@
em_block = new(src, render_target)
vis_contents += em_block
/atom/movable/Destroy(force)
QDEL_NULL(proximity_monitor)
QDEL_NULL(language_holder)
QDEL_NULL(em_block)
unbuckle_all_mobs(force = TRUE)
if(loc)
//Restore air flow if we were blocking it (movables with ATMOS_PASS_PROC will need to do this manually if necessary)
if(((CanAtmosPass == ATMOS_PASS_DENSITY && density) || CanAtmosPass == ATMOS_PASS_NO) && isturf(loc))
CanAtmosPass = ATMOS_PASS_YES
air_update_turf(TRUE)
loc.handle_atom_del(src)
// if(opacity)
// RemoveElement(/datum/element/light_blocking)
invisibility = INVISIBILITY_ABSTRACT
if(pulledby)
pulledby.stop_pulling()
if(orbiting)
orbiting.end_orbit(src)
orbiting = null
. = ..()
for(var/movable_content in contents)
qdel(movable_content)
LAZYCLEARLIST(client_mobs_in_contents)
moveToNullspace()
/atom/movable/proc/update_emissive_block()
if(blocks_emissive != EMISSIVE_BLOCK_GENERIC)
return
@@ -113,40 +149,52 @@
return FALSE
return T.zPassOut(src, direction, destination) && destination.zPassIn(src, direction, T)
/atom/movable/vv_edit_var(var_name, var_value)
var/static/list/banned_edits = list("step_x", "step_y", "step_size")
var/static/list/careful_edits = list("bound_x", "bound_y", "bound_width", "bound_height")
if(var_name in banned_edits)
/atom/movable/vv_edit_var(var_name, var_value, massedit)
var/static/list/banned_edits = list("step_x" = TRUE, "step_y" = TRUE, "step_size" = TRUE, "bounds" = TRUE)
var/static/list/careful_edits = list("bound_x" = TRUE, "bound_y" = TRUE, "bound_width" = TRUE, "bound_height" = TRUE)
if(banned_edits[var_name])
return FALSE //PLEASE no.
if((var_name in careful_edits) && (var_value % world.icon_size) != 0)
if((careful_edits[var_name]) && (var_value % world.icon_size) != 0)
return FALSE
switch(var_name)
if(NAMEOF(src, x))
var/turf/T = locate(var_value, y, z)
if(T)
forceMove(T)
admin_teleport(T, !massedit)
return TRUE
return FALSE
if(NAMEOF(src, y))
var/turf/T = locate(x, var_value, z)
if(T)
forceMove(T)
admin_teleport(T, !massedit)
return TRUE
return FALSE
if(NAMEOF(src, z))
var/turf/T = locate(x, y, var_value)
if(T)
forceMove(T)
admin_teleport(T, !massedit)
return TRUE
return FALSE
if(NAMEOF(src, loc))
if(istype(var_value, /atom))
forceMove(var_value)
return TRUE
else if(isnull(var_value))
moveToNullspace()
if(isatom(var_value) || isnull(var_value))
admin_teleport(var_value, !massedit)
return TRUE
return FALSE
if(NAMEOF(src, anchored))
set_anchored(var_value)
. = TRUE
if(NAMEOF(src, pulledby))
set_pulledby(var_value)
. = TRUE
if(NAMEOF(src, glide_size))
set_glide_size(var_value)
. = TRUE
if(!isnull(.))
datum_flags |= DF_VAR_EDITED
return
return ..()
/atom/movable/proc/start_pulling(atom/movable/AM, state, force = move_force, supress_message = FALSE)
@@ -168,48 +216,73 @@
AMob.grabbedby(src)
return TRUE
stop_pulling()
// SEND_SIGNAL(src, COMSIG_ATOM_START_PULL, AM, state, force)
if(AM.pulledby)
log_combat(AM, AM.pulledby, "pulled from", src)
AM.pulledby.stop_pulling() //an object can't be pulled by two mobs at once.
pulling = AM
AM.pulledby = src
AM.set_pulledby(src)
setGrabState(state)
if(ismob(AM))
var/mob/M = AM
log_combat(src, M, "grabbed", addition="passive grab")
if(!supress_message)
visible_message("<span class='warning'>[src] has grabbed [M] passively!</span>")
M.visible_message("<span class='warning'>[src] grabs [M] passively.</span>", \
"<span class='danger'>[src] grabs you passively.</span>")
return TRUE
/atom/movable/proc/stop_pulling()
if(!pulling)
return
pulling.pulledby = null
pulling.set_pulledby(null)
var/mob/living/ex_pulled = pulling
setGrabState(GRAB_PASSIVE)
pulling = null
setGrabState(0)
if(isliving(ex_pulled))
var/mob/living/L = ex_pulled
L.update_mobility()// mob gets up if it was lyng down in a chokehold
///Reports the event of the change in value of the pulledby variable.
/atom/movable/proc/set_pulledby(new_pulledby)
if(new_pulledby == pulledby)
return FALSE //null signals there was a change, be sure to return FALSE if none happened here.
. = pulledby
pulledby = new_pulledby
/atom/movable/proc/Move_Pulled(atom/A)
if(!pulling)
return
return FALSE
if(pulling.anchored || pulling.move_resist > move_force || !pulling.Adjacent(src))
stop_pulling()
return
return FALSE
if(isliving(pulling))
var/mob/living/L = pulling
if(L.buckled && L.buckled.buckle_prevents_pull) //if they're buckled to something that disallows pulling, prevent it
stop_pulling()
return
return FALSE
if(A == loc && pulling.density)
return
if(!Process_Spacemove(get_dir(pulling.loc, A)))
return
step(pulling, get_dir(pulling.loc, A))
return FALSE
var/move_dir = get_dir(pulling.loc, A)
if(!Process_Spacemove(move_dir))
return FALSE
pulling.Move(get_step(pulling.loc, move_dir), move_dir, glide_size)
return TRUE
/**
* Recursively set glide size for atom's pulled things
*/
/atom/movable/proc/recursive_pulled_glidesize_update()
var/list/ran = list()
var/atom/movable/updating = pulling
while(updating)
if(ran[updating])
return
updating.set_glide_size(glide_size, FALSE)
ran[updating] = TRUE
updating = updating.pulling
/atom/movable/proc/check_pulling()
if(pulling)
var/atom/movable/pullee = pulling
@@ -229,54 +302,57 @@
if(pulledby && moving_diagonally != FIRST_DIAG_STEP && get_dist(src, pulledby) > 1) //separated from our puller and not in the middle of a diagonal move.
pulledby.stop_pulling()
/atom/movable/Destroy(force)
QDEL_NULL(proximity_monitor)
QDEL_NULL(language_holder)
QDEL_NULL(em_block)
/atom/movable/proc/set_glide_size(target = 8, recursive = TRUE)
#ifdef SMOOTH_MOVEMENT
// SEND_SIGNAL(src, COMSIG_MOVABLE_UPDATE_GLIDE_SIZE, target)
glide_size = target
unbuckle_all_mobs(force=1)
for(var/m in buckled_mobs)
var/mob/buckled_mob = m
buckled_mob.set_glide_size(target)
. = ..()
if(recursive)
recursive_pulled_glidesize_update()
#else
return
#endif
if(loc)
//Restore air flow if we were blocking it (movables with ATMOS_PASS_PROC will need to do this manually if necessary)
if(((CanAtmosPass == ATMOS_PASS_DENSITY && density) || CanAtmosPass == ATMOS_PASS_NO) && isturf(loc))
CanAtmosPass = ATMOS_PASS_YES
air_update_turf(TRUE)
loc.handle_atom_del(src)
for(var/atom/movable/AM in contents)
qdel(AM)
moveToNullspace()
invisibility = INVISIBILITY_ABSTRACT
if(pulledby)
pulledby.stop_pulling()
if(orbiting)
orbiting.end_orbit(src)
orbiting = null
///Sets the anchored var and returns if it was sucessfully changed or not.
/atom/movable/proc/set_anchored(anchorvalue)
SHOULD_CALL_PARENT(TRUE)
if(anchored == anchorvalue)
return
. = anchored
anchored = anchorvalue
// SEND_SIGNAL(src, COMSIG_MOVABLE_SET_ANCHORED, anchorvalue)
/atom/movable/proc/throw_impact(atom/hit_atom, datum/thrownthing/throwingdatum)
set waitfor = 0
set waitfor = FALSE
var/hitpush = TRUE
var/impact_signal = SEND_SIGNAL(src, COMSIG_MOVABLE_IMPACT, hit_atom, throwingdatum)
if(impact_signal & COMPONENT_MOVABLE_IMPACT_FLIP_HITPUSH)
hitpush = FALSE // hacky, tie this to something else or a proper workaround later
if(impact_signal & ~COMPONENT_MOVABLE_IMPACT_NEVERMIND) // in case a signal interceptor broke or deleted the thing before we could process our hit
return hit_atom.hitby(src, throwingdatum = throwingdatum, hitpush = hitpush)
if(!(impact_signal && (impact_signal & COMPONENT_MOVABLE_IMPACT_NEVERMIND))) // in case a signal interceptor broke or deleted the thing before we could process our hit
return hit_atom.hitby(src, throwingdatum=throwingdatum, hitpush=hitpush)
/atom/movable/hitby(atom/movable/AM, skipcatch, hitpush = TRUE, blocked, datum/thrownthing/throwingdatum)
if(!anchored && hitpush && (!throwingdatum || (throwingdatum.force >= (move_resist * MOVE_FORCE_PUSH_RATIO))))
step(src, AM.dir)
..()
/atom/movable/proc/safe_throw_at(atom/target, range, speed, mob/thrower, spin = TRUE, diagonals_first = FALSE, datum/callback/callback, force = INFINITY, messy_throw = TRUE)
/atom/movable/proc/safe_throw_at(atom/target, range, speed, mob/thrower, spin = TRUE, diagonals_first = FALSE, datum/callback/callback, force = MOVE_FORCE_STRONG, gentle = FALSE)
if((force < (move_resist * MOVE_FORCE_THROW_RATIO)) || (move_resist == INFINITY))
return
return throw_at(target, range, speed, thrower, spin, diagonals_first, callback, force, messy_throw)
return throw_at(target, range, speed, thrower, spin, diagonals_first, callback, force, gentle)
/atom/movable/proc/throw_at(atom/target, range, speed, mob/thrower, spin = TRUE, diagonals_first = FALSE, datum/callback/callback, force = INFINITY, messy_throw = TRUE) //If this returns FALSE then callback will not be called.
///If this returns FALSE then callback will not be called.
/atom/movable/proc/throw_at(atom/target, range, speed, mob/thrower, spin = TRUE, diagonals_first = FALSE, datum/callback/callback, force = MOVE_FORCE_STRONG, gentle = FALSE, quickstart = TRUE)
. = FALSE
if(QDELETED(src))
CRASH("Qdeleted thing being thrown around.")
if (!target || speed <= 0)
return
@@ -288,7 +364,7 @@
//They are moving! Wouldn't it be cool if we calculated their momentum and added it to the throw?
if (thrower && thrower.last_move && thrower.client && thrower.client.move_delay >= world.time + world.tick_lag*2)
var/user_momentum = thrower.movement_delay()
var/user_momentum = thrower.movement_delay() //cached_multiplicative_slowdown
if (!user_momentum) //no movement_delay, this means they move once per byond tick, lets calculate from that instead.
user_momentum = world.tick_lag
@@ -312,19 +388,13 @@
. = TRUE // No failure conditions past this point.
var/datum/thrownthing/TT = new()
TT.thrownthing = src
TT.target = target
TT.target_turf = get_turf(target)
TT.init_dir = get_dir(src, target)
TT.maxrange = range
TT.speed = speed
TT.thrower = thrower
TT.diagonals_first = diagonals_first
TT.force = force
TT.callback = callback
if(!QDELETED(thrower))
TT.target_zone = thrower.zone_selected
var/target_zone
if(QDELETED(thrower))
thrower = null //Let's not pass a qdeleting reference if any.
else
target_zone = thrower.zone_selected
var/datum/thrownthing/TT = new(src, target, get_turf(target), get_dir(src, target), range, speed, thrower, diagonals_first, force, gentle, callback, target_zone)
var/dist_x = abs(target.x - src.x)
var/dist_y = abs(target.y - src.y)
@@ -359,7 +429,8 @@
SSthrowing.processing[src] = TT
if (SSthrowing.state == SS_PAUSED && length(SSthrowing.currentrun))
SSthrowing.currentrun[src] = TT
TT.tick()
if (quickstart)
TT.tick()
/atom/movable/proc/force_pushed(atom/movable/pusher, force = MOVE_FORCE_DEFAULT, direction)
return FALSE
@@ -382,13 +453,13 @@
return TRUE
return ..()
// called when this atom is removed from a storage item, which is passed on as S. The loc variable is already set to the new destination before this is called.
/atom/movable/proc/on_exit_storage(datum/component/storage/concrete/S)
return
/// called when this atom is removed from a storage item, which is passed on as S. The loc variable is already set to the new destination before this is called.
/atom/movable/proc/on_exit_storage(datum/component/storage/concrete/S) // rename S to master_storage
// SEND_SIGNAL(src, COMSIG_STORAGE_EXITED, master_storage)
// called when this atom is added into a storage item, which is passed on as S. The loc variable is already set to the storage item.
/// called when this atom is added into a storage item, which is passed on as S. The loc variable is already set to the storage item.
/atom/movable/proc/on_enter_storage(datum/component/storage/concrete/S)
return
// SEND_SIGNAL(src, COMSIG_STORAGE_ENTERED, master_storage)
/atom/movable/proc/get_spacemove_backup()
var/atom/movable/dense_object_backup
@@ -422,24 +493,26 @@
return //don't do an animation if attacking self
var/pixel_x_diff = 0
var/pixel_y_diff = 0
var/turn_dir = 1
var/direction = get_dir(src, A)
if(direction & NORTH)
pixel_y_diff = 8
turn_dir = prob(50) ? -1 : 1
else if(direction & SOUTH)
pixel_y_diff = -8
turn_dir = prob(50) ? -1 : 1
if(direction & EAST)
pixel_x_diff = 8
else if(direction & WEST)
pixel_x_diff = -8
turn_dir = -1
var/matrix/OM = matrix(transform)
var/matrix/M = matrix(transform)
M.Turn(pixel_x_diff ? pixel_x_diff*2 : pick(-16, 16))
animate(src, pixel_x = pixel_x + pixel_x_diff, pixel_y = pixel_y + pixel_y_diff, transform = M, time = 2)
animate(src, pixel_x = pixel_x - pixel_x_diff, pixel_y = pixel_y - pixel_y_diff, transform = OM, time = 2)
var/matrix/initial_transform = matrix(transform)
var/matrix/rotated_transform = transform.Turn(15 * turn_dir)
animate(src, pixel_x = pixel_x + pixel_x_diff, pixel_y = pixel_y + pixel_y_diff, transform=rotated_transform, time = 1, easing=BACK_EASING|EASE_IN)
animate(pixel_x = pixel_x - pixel_x_diff, pixel_y = pixel_y - pixel_y_diff, transform=initial_transform, time = 2, easing=SINE_EASING)
/atom/movable/proc/do_item_attack_animation(atom/A, visual_effect_icon, obj/item/used_item)
var/image/I
@@ -450,21 +523,21 @@
I.plane = GAME_PLANE
// Scale the icon.
I.transform *= 0.75
I.transform *= 0.4
// The icon should not rotate.
I.appearance_flags = APPEARANCE_UI_IGNORE_ALPHA
// Set the direction of the icon animation.
var/direction = get_dir(src, A)
if(direction & NORTH)
I.pixel_y = -16
I.pixel_y = -12
else if(direction & SOUTH)
I.pixel_y = 16
I.pixel_y = 12
if(direction & EAST)
I.pixel_x = -16
I.pixel_x = -14
else if(direction & WEST)
I.pixel_x = 16
I.pixel_x = 14
if(!direction) // Attacked self?!
I.pixel_z = 16
@@ -472,10 +545,12 @@
if(!I)
return
flick_overlay(I, GLOB.clients, 5) // 5 ticks/half a second
flick_overlay(I, GLOB.clients, 10)
// And animate the attack!
animate(I, alpha = 175, pixel_x = 0, pixel_y = 0, pixel_z = 0, time = 3)
animate(I, alpha = 175, transform = matrix() * 0.75, pixel_x = 0, pixel_y = 0, pixel_z = 0, time = 3)
animate(time = 1)
animate(alpha = 0, time = 3, easing = CIRCULAR_EASING|EASE_OUT)
/atom/movable/vv_get_dropdown()
. = ..()
@@ -495,16 +570,14 @@
/atom/movable/proc/float(on, throw_override)
if(throwing || !throw_override)
return
if(on && (!(movement_type & FLOATING) || floating_need_update))
animate(src, pixel_y = pixel_y + 2, time = 10, loop = -1)
sleep(10)
animate(src, pixel_y = pixel_y - 2, time = 10, loop = -1)
if(!(movement_type & FLOATING))
setMovetype(movement_type | FLOATING)
else if (!on && movement_type & FLOATING)
if(on && !(movement_type & FLOATING))
animate(src, pixel_y = 2, time = 10, loop = -1, flags = ANIMATION_RELATIVE)
animate(pixel_y = -2, time = 10, loop = -1, flags = ANIMATION_RELATIVE)
setMovetype(movement_type | FLOATING)
else if (!on && (movement_type & FLOATING))
animate(src, pixel_y = initial(pixel_y), time = 10)
setMovetype(movement_type & ~FLOATING)
floating_need_update = FALSE
floating_need_update = FALSE // assume it's done
/* Language procs
* Unless you are doing something very specific, these are the ones you want to use.
@@ -611,10 +684,32 @@
return FALSE
return TRUE
/// Updates the grab state of the movable
/// This exists to act as a hook for behaviour
/**
* Updates the grab state of the movable
*
* This exists to act as a hook for behaviour
*/
/atom/movable/proc/setGrabState(newstate)
if(newstate == grab_state)
return
// SEND_SIGNAL(src, COMSIG_MOVABLE_SET_GRAB_STATE, newstate)
. = grab_state
grab_state = newstate
// switch(grab_state) // Current state.
// if(GRAB_PASSIVE)
// REMOVE_TRAIT(pulling, TRAIT_IMMOBILIZED, CHOKEHOLD_TRAIT)
// REMOVE_TRAIT(pulling, TRAIT_HANDS_BLOCKED, CHOKEHOLD_TRAIT)
// if(. >= GRAB_NECK) // Previous state was a a neck-grab or higher.
// REMOVE_TRAIT(pulling, TRAIT_FLOORED, CHOKEHOLD_TRAIT)
// if(GRAB_AGGRESSIVE)
// if(. >= GRAB_NECK) // Grab got downgraded.
// REMOVE_TRAIT(pulling, TRAIT_FLOORED, CHOKEHOLD_TRAIT)
// else // Grab got upgraded from a passive one.
// ADD_TRAIT(pulling, TRAIT_IMMOBILIZED, CHOKEHOLD_TRAIT)
// ADD_TRAIT(pulling, TRAIT_HANDS_BLOCKED, CHOKEHOLD_TRAIT)
// if(GRAB_NECK, GRAB_KILL)
// if(. <= GRAB_AGGRESSIVE)
// ADD_TRAIT(pulling, TRAIT_FLOORED, CHOKEHOLD_TRAIT)
/obj/item/proc/do_pickup_animation(atom/target)
set waitfor = FALSE
@@ -626,31 +721,24 @@
I.appearance_flags = APPEARANCE_UI_IGNORE_ALPHA
var/turf/T = get_turf(src)
var/direction
var/to_x = 0
var/to_y = 0
var/to_x = initial(target.pixel_x)
var/to_y = initial(target.pixel_y)
if(!QDELETED(T) && !QDELETED(target))
direction = get_dir(T, target)
if(direction & NORTH)
to_y = 32
to_y += 32
else if(direction & SOUTH)
to_y = -32
to_y -= 32
if(direction & EAST)
to_x = 32
to_x += 32
else if(direction & WEST)
to_x = -32
to_x -= 32
if(!direction)
to_y = 16
to_y += 16
flick_overlay(I, GLOB.clients, 6)
var/matrix/M = new
M.Turn(pick(-30, 30))
animate(I, alpha = 175, pixel_x = to_x, pixel_y = to_y, time = 3, transform = M, easing = CUBIC_EASING)
sleep(1)
animate(I, alpha = 0, transform = matrix(), time = 1)
/atom/movable/proc/set_anchored(anchorvalue) //literally only for plumbing ran
SHOULD_CALL_PARENT(TRUE)
if(anchored == anchorvalue)
return
. = anchored
anchored = anchorvalue
+61 -40
View File
@@ -5,8 +5,7 @@
// Here's where we rewrite how byond handles movement except slightly different
// To be removed on step_ conversion
// All this work to prevent a second bump
/atom/movable/Move(atom/newloc, direct=0)
set waitfor = FALSE //n o
/atom/movable/Move(atom/newloc, direct=0, glide_size_override = 0)
. = FALSE
if(!newloc || newloc == loc)
return
@@ -52,8 +51,7 @@
//
////////////////////////////////////////
/atom/movable/Move(atom/newloc, direct)
set waitfor = FALSE //n o
/atom/movable/Move(atom/newloc, direct, glide_size_override = 0)
var/atom/movable/pullee = pulling
var/turf/T = loc
if(!moving_from_pull)
@@ -61,6 +59,9 @@
if(!loc || !newloc)
return FALSE
var/atom/oldloc = loc
//Early override for some cases like diagonal movement
if(glide_size_override)
set_glide_size(glide_size_override, FALSE)
if(loc != newloc)
if (!(direct & (direct - 1))) //Cardinal move
@@ -120,32 +121,38 @@
return
if(!loc || (loc == oldloc && oldloc != newloc))
last_move = NONE
last_move = 0
return
setDir(direct)
if(.)
last_move = direct
setDir(direct)
if(has_buckled_mobs() && !handle_buckled_mob_movement(loc,direct)) //movement failed due to buckled mob(s)
return FALSE
if(pulling && pulling == pullee && pulling != moving_from_pull) //we were pulling a thing and didn't lose it during our move.
if(pulling.anchored)
stop_pulling()
else
var/pull_dir = get_dir(src, pulling)
//puller and pullee more than one tile away or in diagonal position
if(get_dist(src, pulling) > 1 || (moving_diagonally != SECOND_DIAG_STEP && ((pull_dir - 1) & pull_dir)))
pulling.moving_from_pull = src
pulling.Move(T, get_dir(pulling, T)) //the pullee tries to reach our previous position
pulling.moving_from_pull = null
Moved(oldloc, direct)
if(. && pulling && pulling == pullee && pulling != moving_from_pull) //we were pulling a thing and didn't lose it during our move.
if(pulling.anchored)
stop_pulling()
else
var/pull_dir = get_dir(src, pulling)
//puller and pullee more than one tile away or in diagonal position
if(get_dist(src, pulling) > 1 || (moving_diagonally != SECOND_DIAG_STEP && ((pull_dir - 1) & pull_dir)))
pulling.moving_from_pull = src
pulling.Move(T, get_dir(pulling, T), glide_size) //the pullee tries to reach our previous position
pulling.moving_from_pull = null
check_pulling()
/atom/movable/proc/handle_buckled_mob_movement(newloc,direct)
//glide_size strangely enough can change mid movement animation and update correctly while the animation is playing
//This means that if you don't override it late like this, it will just be set back by the movement update that's called when you move turfs.
if(glide_size_override)
set_glide_size(glide_size_override, FALSE)
last_move = direct
if(. && has_buckled_mobs() && !handle_buckled_mob_movement(loc, direct, glide_size_override)) //movement failed due to buckled mob(s)
return FALSE
/atom/movable/proc/handle_buckled_mob_movement(newloc, direct, glide_size_override)
for(var/m in buckled_mobs)
var/mob/living/buckled_mob = m
if(!buckled_mob.Move(newloc, direct))
if(!buckled_mob.Move(newloc, direct, glide_size_override))
forceMove(buckled_mob.loc)
last_move = buckled_mob.last_move
inertia_dir = last_move
@@ -155,6 +162,7 @@
//Called after a successful Move(). By this point, we've already moved
/atom/movable/proc/Moved(atom/OldLoc, Dir, Forced = FALSE)
SHOULD_CALL_PARENT(TRUE)
SEND_SIGNAL(src, COMSIG_MOVABLE_MOVED, OldLoc, Dir, Forced)
if (!inertia_moving)
inertia_next_move = world.time + inertia_move_delay
@@ -174,6 +182,8 @@
//oldloc = old location on atom, inserted when forceMove is called and ONLY when forceMove is called!
/atom/movable/Crossed(atom/movable/AM, oldloc)
// SHOULD_CALL_PARENT(TRUE)
. = ..()
SEND_SIGNAL(src, COMSIG_MOVABLE_CROSSED, AM)
/atom/movable/Uncross(atom/movable/AM, atom/newloc)
@@ -204,7 +214,11 @@
var/atom/movable/AM = item
AM.onTransitZ(old_z,new_z)
///Proc to modify the movement_type and hook behavior associated with it changing.
/atom/movable/proc/setMovetype(newval)
if(movement_type == newval)
return
. = movement_type
movement_type = newval
///////////// FORCED MOVEMENT /////////////
@@ -268,37 +282,44 @@
old_area.Exited(src, null)
loc = null
//Called whenever an object moves and by mobs when they attempt to move themselves through space
//And when an object or action applies a force on src, see newtonian_move() below
//Return 0 to have src start/keep drifting in a no-grav area and 1 to stop/not start drifting
//Mobs should return 1 if they should be able to move of their own volition, see client/Move() in mob_movement.dm
//movement_dir == 0 when stopping or any dir when trying to move
/**
* Called whenever an object moves and by mobs when they attempt to move themselves through space
* And when an object or action applies a force on src, see [newtonian_move][/atom/movable/proc/newtonian_move]
*
* Return 0 to have src start/keep drifting in a no-grav area and 1 to stop/not start drifting
*
* Mobs should return 1 if they should be able to move of their own volition, see [/client/proc/Move]
*
* Arguments:
* * movement_dir - 0 when stopping or any dir when trying to move
*/
/atom/movable/proc/Process_Spacemove(movement_dir = 0)
if(has_gravity(src))
return 1
return TRUE
if(pulledby)
return 1
if(pulledby && (pulledby.pulledby != src || moving_from_pull))
return TRUE
if(throwing)
return 1
return TRUE
if(!isturf(loc))
return 1
return TRUE
if(locate(/obj/structure/lattice) in range(1, get_turf(src))) //Not realistic but makes pushing things in space easier
return 1
return TRUE
return 0
return FALSE
/atom/movable/proc/newtonian_move(direction) //Only moves the object if it's under no gravity
if(!loc || Process_Spacemove(0))
/// Only moves the object if it's under no gravity
/atom/movable/proc/newtonian_move(direction)
if(!isturf(loc) || Process_Spacemove(0))
inertia_dir = 0
return 0
return FALSE
inertia_dir = direction
if(!direction)
return 1
return TRUE
inertia_last_loc = loc
SSspacedrift.processing[src] = src
return 1
return TRUE
+1 -1
View File
@@ -109,4 +109,4 @@
else if (world.time > detectTime)
detectTime = 0
for(var/obj/machinery/computer/security/telescreen/entertainment/TV in GLOB.machines)
TV.notify(FALSE)
TV.notify(FALSE)
+10 -10
View File
@@ -60,7 +60,7 @@
blocked = TRUE
var/attackamt = rand(2,6)
temp = "You attack for [attackamt] damage!"
playsound(loc, 'sound/arcade/hit.ogg', 50, 1, extrarange = -3, falloff = 10)
playsound(loc, 'sound/arcade/hit.ogg', 50, TRUE, extrarange = -3)
updateUsrDialog()
if(turtle > 0)
turtle--
@@ -74,7 +74,7 @@
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, 1, extrarange = -3, falloff = 10)
playsound(loc, 'sound/arcade/heal.ogg', 50, TRUE, extrarange = -3)
updateUsrDialog()
turtle++
@@ -89,7 +89,7 @@
blocked = TRUE
var/chargeamt = rand(4,7)
temp = "You regain [chargeamt] points"
playsound(loc, 'sound/arcade/mana.ogg', 50, 1, extrarange = -3, falloff = 10)
playsound(loc, 'sound/arcade/mana.ogg', 50, TRUE, extrarange = -3)
player_mp += chargeamt
if(turtle > 0)
turtle--
@@ -124,7 +124,7 @@
if(!gameover)
gameover = TRUE
temp = "[enemy_name] has fallen! Rejoice!"
playsound(loc, 'sound/arcade/win.ogg', 50, 1, extrarange = -3, falloff = 10)
playsound(loc, 'sound/arcade/win.ogg', 50, TRUE, extrarange = -3)
if(obj_flags & EMAGGED)
new /obj/effect/spawner/newbomb/timer/syndicate(loc)
@@ -141,13 +141,13 @@
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, 1, extrarange = -3, falloff = 10)
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, 1, extrarange = -3, falloff = 10)
playsound(loc, 'sound/arcade/steal.ogg', 50, TRUE, extrarange = -3)
player_mp -= stealamt
updateUsrDialog()
@@ -155,27 +155,27 @@
gameover = TRUE
sleep(turn_speed)
temp = "You have been drained! GAME OVER"
playsound(loc, 'sound/arcade/lose.ogg', 50, 1, extrarange = -3, falloff = 10)
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, 1, extrarange = -3, falloff = 10)
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, 1, extrarange = -3, falloff = 10)
playsound(loc, 'sound/arcade/hit.ogg', 50, TRUE, extrarange = -3)
player_hp -= attackamt
if ((player_mp <= 0) || (player_hp <= 0))
gameover = TRUE
temp = "You have been crushed! GAME OVER"
playsound(loc, 'sound/arcade/lose.ogg', 50, 1, extrarange = -3, falloff = 10)
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", "hp", (obj_flags & EMAGGED ? "emagged":"normal")))
@@ -78,7 +78,7 @@
columns = 0
mine_placed = 0
if(href_list["Easy"])
playsound(loc, startup_sound, 50, 0, extrarange = -3, falloff = 10)
playsound(loc, startup_sound, 50, FALSE, extrarange = -3)
flag_text = "OFF"
game_status = MINESWEEPER_GAME_PLAYING
reset_board = TRUE
@@ -87,7 +87,7 @@
columns = 10
mine_limit = 10
if(href_list["Intermediate"])
playsound(loc, startup_sound, 50, 0, extrarange = -3, falloff = 10)
playsound(loc, startup_sound, 50, FALSE, extrarange = -3)
flag_text = "OFF"
game_status = MINESWEEPER_GAME_PLAYING
reset_board = TRUE
@@ -96,7 +96,7 @@
columns = 17
mine_limit = 40
if(href_list["Hard"])
playsound(loc, startup_sound, 50, 0, extrarange = -3, falloff = 10)
playsound(loc, startup_sound, 50, FALSE, extrarange = -3)
flag_text = "OFF"
game_status = MINESWEEPER_GAME_PLAYING
reset_board = TRUE
@@ -110,9 +110,9 @@
game_status = MINESWEEPER_GAME_PLAYING
reset_board = TRUE
difficulty = "Custom"
playsound(loc, startup_sound, 50, 0, extrarange = -3, falloff = 10)
playsound(loc, startup_sound, 50, FALSE, extrarange = -3)
if(href_list["Flag"])
playsound(loc, 'sound/arcade/minesweeper_boardpress.ogg', 50, 0, extrarange = -3, falloff = 10)
playsound(loc, 'sound/arcade/minesweeper_boardpress.ogg', 50, FALSE, extrarange = -3)
if(!flagging)
flagging = TRUE
flag_text = "ON"
@@ -122,10 +122,10 @@
if(game_status == MINESWEEPER_GAME_MAIN_MENU)
if(CHECK_BITFIELD(obj_flags, EMAGGED))
playsound(loc, 'sound/arcade/minesweeper_emag2.ogg', 50, 0, extrarange = -3, falloff = 10)
playsound(loc, 'sound/arcade/minesweeper_emag2.ogg', 50, FALSE, extrarange = -3)
web += "<font size='2'>Explode in the game, explode in real life!<br>What difficulty do you want to play?<br><br><br><br><b><a href='byond://?src=[REF(src)];Easy=1'><font color='#cc66ff'>Easy (9x9 board, 10 mines)</font></a><br><a href='byond://?src=[REF(src)];Intermediate=1'><font color='#cc66ff'>Intermediate (16x16 board, 40 mines)</font></a><br><a href='byond://?src=[REF(src)];Hard=1'><font color='#cc66ff'>Hard (16x30 board, 99 mines)</font></a><br><a href='byond://?src=[REF(src)];Custom=1'><font color='#cc66ff'>Custom</font>"
else
playsound(loc, 'sound/arcade/minesweeper_startup.ogg', 50, 0, extrarange = -3, falloff = 10)
playsound(loc, 'sound/arcade/minesweeper_startup.ogg', 50, FALSE, extrarange = -3)
web += web_difficulty_menu
if(game_status == MINESWEEPER_GAME_PLAYING)
@@ -152,7 +152,7 @@
if(table[y1][x1] < 10 && table[y1][x1] >= 0) //Check that it's not already revealed, and stop flag removal if we're out of flag mode
table[y1][x1] += 10
if(table[y1][x1] != 10)
playsound(loc, 'sound/arcade/minesweeper_boardpress.ogg', 50, 0, extrarange = -3, falloff = 10)
playsound(loc, 'sound/arcade/minesweeper_boardpress.ogg', 50, FALSE, extrarange = -3)
else
if(game_status != MINESWEEPER_GAME_LOST && game_status != MINESWEEPER_GAME_WON)
game_status = MINESWEEPER_GAME_LOST
@@ -164,14 +164,14 @@
if(mine_sound)
switch(rand(1,3)) //Play every time a mine is hit
if(1)
playsound(loc, 'sound/arcade/minesweeper_explosion1.ogg', 50, 0, extrarange = -3, falloff = 10)
playsound(loc, 'sound/arcade/minesweeper_explosion1.ogg', 50, FALSE, extrarange = -3)
if(2)
playsound(loc, 'sound/arcade/minesweeper_explosion2.ogg', 50, 0, extrarange = -3, falloff = 10)
playsound(loc, 'sound/arcade/minesweeper_explosion2.ogg', 50, FALSE, extrarange = -3)
if(3)
playsound(loc, 'sound/arcade/minesweeper_explosion3.ogg', 50, 0, extrarange = -3, falloff = 10)
playsound(loc, 'sound/arcade/minesweeper_explosion3.ogg', 50, FALSE, extrarange = -3)
mine_sound = FALSE
else
playsound(loc, 'sound/arcade/minesweeper_boardpress.ogg', 50, 0, extrarange = -3, falloff = 10)
playsound(loc, 'sound/arcade/minesweeper_boardpress.ogg', 50, FALSE, extrarange = -3)
if(table[y1][x1] >= 0) //Check that it's not already flagged
table[y1][x1] -= 10
else if(table[y1][x1] < 0) //If flagged, remove the flag
@@ -182,7 +182,7 @@
game_status = MINESWEEPER_GAME_PLAYING
if(table[y1][x1] >= 10) //If revealed, become unrevealed!
if(mine_sound)
playsound(loc, 'sound/arcade/minesweeper_menuselect.ogg', 50, 0, extrarange = -3, falloff = 10)
playsound(loc, 'sound/arcade/minesweeper_menuselect.ogg', 50, FALSE, extrarange = -3)
mine_sound = FALSE
table[y1][x1] -= 10
if(table[y1][x1] > 10 && !reset_board)
@@ -243,10 +243,10 @@
if(safe_squares_revealed >= win_condition && game_status == MINESWEEPER_GAME_PLAYING)
game_status = MINESWEEPER_GAME_WON
if(rows < 10 || columns < 10) //If less than easy difficulty
playsound(loc, 'sound/arcade/minesweeper_winfail.ogg', 50, 0, extrarange = -3, falloff = 10)
playsound(loc, 'sound/arcade/minesweeper_winfail.ogg', 50, FALSE, extrarange = -3)
say("You cleared the board of all mines, but you picked too small of a board! Try again with at least a 9x9 board!")
else
playsound(loc, 'sound/arcade/minesweeper_win.ogg', 50, 0, extrarange = -3, falloff = 10)
playsound(loc, 'sound/arcade/minesweeper_win.ogg', 50, FALSE, extrarange = -3)
say("You cleared the board of all mines! Congratulations!")
if(CHECK_BITFIELD(obj_flags, EMAGGED))
var/itemname
@@ -299,32 +299,32 @@
ENABLE_BITFIELD(obj_flags, EMAGGED)
if(game_status == MINESWEEPER_GAME_MAIN_MENU)
to_chat(user, "<span class='warning'>An ominous tune plays from the arcade's speakers!</span>")
playsound(user, 'sound/arcade/minesweeper_emag1.ogg', 100, 0, extrarange = 3, falloff = 10)
playsound(user, 'sound/arcade/minesweeper_emag1.ogg', 100, FALSE, extrarange = 3)
else //Can't let you do that, star fox!
to_chat(user, "<span class='warning'>The machine buzzes and sparks... the game has been reset!</span>")
playsound(user, 'sound/machines/buzz-sigh.ogg', 100, 0, extrarange = 3, falloff = 10) //Loud buzz
playsound(user, 'sound/machines/buzz-sigh.ogg', 100, FALSE, extrarange = 3) //Loud buzz
game_status = MINESWEEPER_GAME_MAIN_MENU
return TRUE
/obj/machinery/computer/arcade/minesweeper/proc/custom_generation(mob/user)
playsound(loc, 'sound/arcade/minesweeper_menuselect.ogg', 50, 0, extrarange = -3, falloff = 10) //Entered into the menu so ping sound
playsound(loc, 'sound/arcade/minesweeper_menuselect.ogg', 50, FALSE, extrarange = -3) //Entered into the menu so ping sound
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)
playsound(loc, 'sound/arcade/minesweeper_menuselect.ogg', 50, 0, extrarange = -3, falloff = 10)
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)
playsound(loc, 'sound/arcade/minesweeper_menuselect.ogg', 50, 0, extrarange = -3, falloff = 10)
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)
var/upper_limit = round(grid_area*0.85)
var/new_mine_limit = input(user, "How many mines do you want? (Minimum: [lower_limit], Maximum: [upper_limit])", "Minesweeper Mines") as null|num
if(!new_mine_limit || !user.canUseTopic(src, !hasSiliconAccessInArea(user)))
return FALSE
playsound(loc, 'sound/arcade/minesweeper_menuselect.ogg', 50, 0, extrarange = -3, falloff = 10)
playsound(loc, 'sound/arcade/minesweeper_menuselect.ogg', 50, FALSE, extrarange = -3)
rows = new_rows
columns = new_columns
mine_limit = clamp(new_mine_limit, lower_limit, upper_limit)
@@ -17,14 +17,14 @@
to_chat(c_user, "<span class='warning'>You move your hand towards the machine, and begin to hesitate as a bloodied guillotine emerges from inside of it...</span>")
if(do_after(c_user, 50, target = src))
to_chat(c_user, "<span class='userdanger'>The guillotine drops on your arm, and the machine sucks it in!</span>")
playsound(loc, 'sound/weapons/slice.ogg', 25, 1, -1)
playsound(loc, 'sound/weapons/slice.ogg', 25, TRUE, -1)
var/which_hand = BODY_ZONE_L_ARM
if(!(c_user.active_hand_index % 2))
which_hand = BODY_ZONE_R_ARM
var/obj/item/bodypart/chopchop = c_user.get_bodypart(which_hand)
chopchop.dismember()
qdel(chopchop)
playsound(loc, 'sound/arcade/win.ogg', 50, 1, extrarange = -3, falloff = 10)
playsound(loc, 'sound/arcade/win.ogg', 50, TRUE, extrarange = -3)
for(var/i=1; i<=rand(3,5); i++)
prizevend(user)
else
+1 -1
View File
@@ -23,7 +23,7 @@
. = ..()
SSradio.remove_object(src, air_frequency)
air_connection = SSradio.add_object(src, air_frequency, RADIO_TO_AIRALARM)
open()
INVOKE_ASYNC(src, .proc/open)
/obj/machinery/door/airlock/alarmlock/receive_signal(datum/signal/signal)
..()
+3 -3
View File
@@ -130,7 +130,7 @@
/obj/machinery/quantumpad/proc/doteleport(mob/user, obj/machinery/quantumpad/target_pad = linked_pad)
if(target_pad)
playsound(get_turf(src), 'sound/weapons/flash.ogg', 25, 1)
playsound(get_turf(src), 'sound/weapons/flash.ogg', 25, TRUE)
teleporting = TRUE
spawn(teleport_speed)
@@ -155,9 +155,9 @@
target_pad.sparks()
flick("qpad-beam", src)
playsound(get_turf(src), 'sound/weapons/emitter2.ogg', 25, 1, extrarange = 3, falloff = 5)
playsound(get_turf(src), 'sound/weapons/emitter2.ogg', 25, TRUE)
flick("qpad-beam", target_pad)
playsound(get_turf(target_pad), 'sound/weapons/emitter2.ogg', 25, 1, extrarange = 3, falloff = 5)
playsound(get_turf(target_pad), 'sound/weapons/emitter2.ogg', 25, TRUE)
for(var/atom/movable/ROI in get_turf(src))
if(QDELETED(ROI))
continue //sleeps in CHECK_TICK
+41 -38
View File
@@ -100,51 +100,54 @@
eat(AM)
. = ..()
/obj/machinery/recycler/proc/eat(atom/AM0)
if(stat & (BROKEN|NOPOWER) || safety_mode)
/obj/machinery/recycler/proc/eat(atom/movable/AM0, sound=TRUE)
if(stat & (BROKEN|NOPOWER))
return
if(safety_mode)
return
if(!isturf(AM0.loc))
return //I don't know how you called Crossed() but stop it.
var/list/to_eat
var/list/to_eat = AM0.GetAllContents()
to_eat = list(AM0)
var/living_detected = FALSE //technically includes silicons as well but eh
var/list/nom = list()
var/list/crunchy_nom = list() //Mobs have to be handled differently so they get a different list instead of checking them multiple times.
var/items_recycled = 0
var/buzz = FALSE
for(var/i in to_eat)
var/atom/movable/AM = i
if(QDELETED(AM))
continue
var/obj/item/bodypart/head/as_head = AM
var/obj/item/mmi/as_mmi = AM
var/brain_holder = istype(AM, /obj/item/organ/brain) || (istype(as_head) && as_head.brain) || (istype(as_mmi) && as_mmi.brain) || istype(AM, /obj/item/dullahan_relay)
if(brain_holder)
if(obj_flags & EMAGGED)
continue
else
emergency_stop(AM)
return
if(istype(AM, /obj/item))
var/obj/item/bodypart/head/as_head = AM
var/obj/item/mmi/as_mmi = AM
if(istype(AM, /obj/item/organ/brain) || (istype(as_head) && as_head.brain) || (istype(as_mmi) && as_mmi.brain) || istype(AM, /obj/item/dullahan_relay))
living_detected = TRUE
nom += AM
else if(isliving(AM))
if((obj_flags & EMAGGED)||((!allowed(AM))&&(!ishuman(AM))))
to_eat += crush_living(AM)
else
emergency_stop(AM)
return
else if(isitem(AM))
var/obj/O = AM
if(O.resistance_flags & INDESTRUCTIBLE)
buzz = TRUE
O.forceMove(loc)
else
to_eat += recycle_item(AM)
items_recycled++
else
buzz = TRUE
AM.forceMove(loc)
if(items_recycled)
playsound(src, item_recycle_sound, 50, 1)
if(buzz)
playsound(src, 'sound/machines/buzz-sigh.ogg', 50, 0)
living_detected = TRUE
crunchy_nom += AM
var/not_eaten = to_eat.len - nom.len - crunchy_nom.len
if(living_detected) // First, check if we have any living beings detected.
if(obj_flags & EMAGGED)
for(var/CRUNCH in crunchy_nom) // Eat them and keep going because we don't care about safety.
if(isliving(CRUNCH)) // MMIs and brains will get eaten like normal items
crush_living(CRUNCH)
else // Stop processing right now without eating anything.
emergency_stop()
return
for(var/nommed in nom)
recycle_item(nommed)
if(nom.len && sound)
playsound(src, item_recycle_sound, (50 + nom.len*5), TRUE, nom.len, ignore_walls = (nom.len - 10)) // As a substitute for playing 50 sounds at once.
if(not_eaten)
playsound(src, 'sound/machines/buzz-sigh.ogg', (50 + not_eaten*5), FALSE, not_eaten, ignore_walls = (not_eaten - 10)) // Ditto.
if(!ismob(AM0))
AM0.moveToNullspace()
qdel(AM0)
else // Lets not move a mob to nullspace and qdel it, yes?
for(var/i in AM0.contents)
var/atom/movable/content = i
content.moveToNullspace()
qdel(content)
/obj/machinery/recycler/proc/recycle_item(obj/item/I)
+118 -72
View File
@@ -11,6 +11,8 @@
#define SPIN_TIME 65 //As always, deciseconds.
#define REEL_DEACTIVATE_DELAY 7
#define SEVEN "<font color='red'>7</font>"
#define HOLOCHIP 1
#define COIN 2
/obj/machinery/computer/slot_machine
name = "slot machine"
@@ -21,40 +23,48 @@
use_power = IDLE_POWER_USE
idle_power_usage = 50
circuit = /obj/item/circuitboard/computer/slot_machine
light_color = LIGHT_COLOR_BROWN
var/money = 3000 //How much money it has CONSUMED
var/plays = 0
var/working = 0
var/working = FALSE
var/balance = 0 //How much money is in the machine, ready to be CONSUMED.
var/jackpots = 0
var/paymode = HOLOCHIP //toggles between HOLOCHIP/COIN, defined above
var/cointype = /obj/item/coin/iron //default cointype
var/list/coinvalues = list()
var/list/reels = list(list("", "", "") = 0, list("", "", "") = 0, list("", "", "") = 0, list("", "", "") = 0, list("", "", "") = 0)
var/list/symbols = list(SEVEN = 1, "<font color='orange'>&</font>" = 2, "<font color='yellow'>@</font>" = 2, "<font color='green'>$</font>" = 2, "<font color='blue'>?</font>" = 2, "<font color='grey'>#</font>" = 2, "<font color='white'>!</font>" = 2, "<font color='fuchsia'>%</font>" = 2) //if people are winning too much, multiply every number in this list by 2 and see if they are still winning too much.
light_color = LIGHT_COLOR_BROWN
/obj/machinery/computer/slot_machine/Initialize()
. = ..()
jackpots = rand(1, 4) //false hope
plays = rand(75, 200)
toggle_reel_spin(1) //The reels won't spin unless we activate them
INVOKE_ASYNC(src, .proc/toggle_reel_spin, TRUE)//The reels won't spin unless we activate them
var/list/reel = reels[1]
for(var/i = 0, i < reel.len, i++) //Populate the reels.
randomize_reels()
toggle_reel_spin(0)
INVOKE_ASYNC(src, .proc/toggle_reel_spin, FALSE)
for(cointype in typesof(/obj/item/coin))
var/obj/item/coin/C = new cointype
coinvalues["[cointype]"] = C.get_item_credit_value()
qdel(C) //Sigh
/obj/machinery/computer/slot_machine/Destroy()
if(balance)
give_coins(balance)
give_payout(balance)
return ..()
/obj/machinery/computer/slot_machine/process()
/obj/machinery/computer/slot_machine/process(delta_time)
. = ..() //Sanity checks.
if(!.)
return .
money++ //SPESSH MAJICKS
money += round(delta_time / 2) //SPESSH MAJICKS
/obj/machinery/computer/slot_machine/update_icon_state()
if(stat & NOPOWER)
@@ -69,27 +79,46 @@
else
icon_state = "slots1"
/obj/machinery/computer/slot_machine/power_change()
..()
update_icon()
/obj/machinery/computer/slot_machine/attackby(obj/item/I, mob/living/user, params)
if(istype(I, /obj/item/coin))
var/obj/item/coin/C = I
if(prob(2))
if(!user.transferItemToLoc(C, drop_location()))
return
C.throw_at(user, 3, 10)
if(prob(10))
balance = max(balance - SPIN_PRICE, 0)
to_chat(user, "<span class='warning'>[src] spits your coin back out!</span>")
if(paymode == COIN)
if(prob(2))
if(!user.transferItemToLoc(C, drop_location()))
return
C.throw_at(user, 3, 10)
if(prob(10))
balance = max(balance - SPIN_PRICE, 0)
to_chat(user, "<span class='warning'>[src] spits your coin back out!</span>")
else
if(!user.temporarilyRemoveItemFromInventory(C))
return
to_chat(user, "<span class='notice'>You insert [C] into [src]'s slot!</span>")
balance += C.value
qdel(C)
else
if(!user.temporarilyRemoveItemFromInventory(C))
to_chat(user, "<span class='warning'>This machine is only accepting holochips!</span>")
else if(istype(I, /obj/item/holochip))
if(paymode == HOLOCHIP)
var/obj/item/holochip/H = I
if(!user.temporarilyRemoveItemFromInventory(H))
return
to_chat(user, "<span class='notice'>You insert [C] into [src]'s slot!</span>")
balance += C.value
qdel(C)
to_chat(user, "<span class='notice'>You insert [H.credits] holocredits into [src]'s slot!</span>")
balance += H.credits
qdel(H)
else
to_chat(user, "<span class='warning'>This machine is only accepting coins!</span>")
else if(I.tool_behaviour == TOOL_MULTITOOL)
if(balance > 0)
visible_message("<b>[src]</b> says, 'ERROR! Please empty the machine balance before altering paymode'") //Prevents converting coins into holocredits and vice versa
else
if(paymode == HOLOCHIP)
paymode = COIN
visible_message("<b>[src]</b> says, 'This machine now works with COINS!'")
else
paymode = HOLOCHIP
visible_message("<b>[src]</b> says, 'This machine now works with HOLOCHIPS!'")
else
return ..()
@@ -101,8 +130,7 @@
var/datum/effect_system/spark_spread/spark_system = new /datum/effect_system/spark_spread()
spark_system.set_up(4, 0, src.loc)
spark_system.start()
playsound(src, "sparks", 50, 1)
return TRUE
playsound(src, "sparks", 50, TRUE)
/obj/machinery/computer/slot_machine/ui_interact(mob/living/user)
. = ..()
@@ -127,8 +155,9 @@
<A href='?src=[REF(src)];spin=1'>Play!</A><BR>
<BR>
[reeltext]
<BR>
<font size='1'><A href='?src=[REF(src)];refund=1'>Refund balance</A><BR>"}
<BR>"}
if(balance > 0)
dat+="<font size='1'><A href='?src=[REF(src)];refund=1'>Refund balance</A><BR>"
var/datum/browser/popup = new(user, "slotmachine", "Slot Machine")
popup.set_content(dat)
@@ -143,21 +172,22 @@
spin(usr)
else if(href_list["refund"])
give_coins(balance)
balance = 0
if(balance > 0)
give_payout(balance)
balance = 0
/obj/machinery/computer/slot_machine/emp_act(severity)
. = ..()
if(stat & (NOPOWER|BROKEN) || . & EMP_PROTECT_SELF)
return
if(prob(1500 / severity))
if(prob(15 * severity))
return
if(prob(1 * severity/100)) // :^)
if(prob(1)) // :^)
obj_flags |= EMAGGED
var/severity_ascending = 4 - severity
money = max(rand(money - (200 * severity_ascending), money + (200 * severity_ascending)), 0)
balance = max(rand(balance - (50 * severity_ascending), balance + (50 * severity_ascending)), 0)
money -= max(0, give_coins(min(rand(-50, 100 * severity_ascending)), money)) //This starts at -50 because it shouldn't always dispense coins yo
money -= max(0, give_payout(min(rand(-50, 100 * severity_ascending)), money)) //This starts at -50 because it shouldn't always dispense coins yo
spin()
/obj/machinery/computer/slot_machine/proc/spin(mob/user)
@@ -174,37 +204,43 @@
balance -= SPIN_PRICE
money += SPIN_PRICE
plays += 1
working = 1
working = TRUE
toggle_reel_spin(1)
update_icon()
updateDialog()
spawn(0)
while(working)
randomize_reels()
updateDialog()
sleep(2)
var/spin_loop = addtimer(CALLBACK(src, .proc/do_spin), 2, TIMER_LOOP|TIMER_STOPPABLE)
spawn(SPIN_TIME - (REEL_DEACTIVATE_DELAY * reels.len)) //WARNING: no sanity checking for user since it's not needed and would complicate things (machine should still spin even if user is gone), be wary of this if you're changing this code.
toggle_reel_spin(0, REEL_DEACTIVATE_DELAY)
working = 0
give_prizes(the_name, user)
update_icon()
updateDialog()
addtimer(CALLBACK(src, .proc/finish_spinning, spin_loop, user, the_name), SPIN_TIME - (REEL_DEACTIVATE_DELAY * reels.len))
//WARNING: no sanity checking for user since it's not needed and would complicate things (machine should still spin even if user is gone), be wary of this if you're changing this code.
/obj/machinery/computer/slot_machine/proc/do_spin()
randomize_reels()
updateDialog()
/obj/machinery/computer/slot_machine/proc/finish_spinning(spin_loop, mob/user, the_name)
toggle_reel_spin(0, REEL_DEACTIVATE_DELAY)
working = FALSE
deltimer(spin_loop)
give_prizes(the_name, user)
update_icon()
updateDialog()
/obj/machinery/computer/slot_machine/proc/can_spin(mob/user)
if(stat & NOPOWER)
to_chat(user, "<span class='warning'>The slot machine has no power!</span>")
return FALSE
if(stat & BROKEN)
to_chat(user, "<span class='warning'>The slot machine is broken!</span>")
return FALSE
if(working)
to_chat(user, "<span class='warning'>You need to wait until the machine stops spinning before you can play again!</span>")
return 0
return FALSE
if(balance < SPIN_PRICE)
to_chat(user, "<span class='warning'>Insufficient money to play!</span>")
return 0
return 1
return FALSE
return TRUE
/obj/machinery/computer/slot_machine/proc/toggle_reel_spin(value, delay = 0) //value is 1 or 0 aka on or off
for(var/list/reel in reels)
@@ -223,23 +259,25 @@
var/linelength = get_lines()
if(reels[1][2] + reels[2][2] + reels[3][2] + reels[4][2] + reels[5][2] == "[SEVEN][SEVEN][SEVEN][SEVEN][SEVEN]")
visible_message("<b>[src]</b> says, 'JACKPOT! You win [money] credits worth of coins!'")
visible_message("<b>[src]</b> says, 'JACKPOT! You win [money] credits!'")
priority_announce("Congratulations to [user ? user.real_name : usrname] for winning the jackpot at the slot machine in [get_area(src)]!")
jackpots += 1
balance += money - give_coins(JACKPOT)
balance += money - give_payout(JACKPOT)
money = 0
for(var/i = 0, i < 5, i++)
var/cointype = pick(subtypesof(/obj/item/coin))
var/obj/item/coin/C = new cointype(loc)
random_step(C, 2, 50)
if(paymode == HOLOCHIP)
new /obj/item/holochip(loc,JACKPOT)
else
for(var/i = 0, i < 5, i++)
cointype = pick(subtypesof(/obj/item/coin))
var/obj/item/coin/C = new cointype(loc)
random_step(C, 2, 50)
else if(linelength == 5)
visible_message("<b>[src]</b> says, 'Big Winner! You win a thousand credits worth of coins!'")
visible_message("<b>[src]</b> says, 'Big Winner! You win a thousand credits!'")
give_money(BIG_PRIZE)
else if(linelength == 4)
visible_message("<b>[src]</b> says, 'Winner! You win four hundred credits worth of coins!'")
visible_message("<b>[src]</b> says, 'Winner! You win four hundred credits!'")
give_money(SMALL_PRIZE)
else if(linelength == 3)
@@ -271,12 +309,15 @@
/obj/machinery/computer/slot_machine/proc/give_money(amount)
var/amount_to_give = money >= amount ? amount : money
var/surplus = amount_to_give - give_coins(amount_to_give)
var/surplus = amount_to_give - give_payout(amount_to_give)
money = max(0, money - amount)
balance += surplus
/obj/machinery/computer/slot_machine/proc/give_coins(amount)
var/cointype = obj_flags & EMAGGED ? /obj/item/coin/iron : /obj/item/coin/silver
/obj/machinery/computer/slot_machine/proc/give_payout(amount)
if(paymode == HOLOCHIP)
cointype = /obj/item/holochip
else
cointype = obj_flags & EMAGGED ? /obj/item/coin/iron : /obj/item/coin/silver
if(!(obj_flags & EMAGGED))
amount = dispense(amount, cointype, null, 0)
@@ -288,22 +329,25 @@
return amount
/obj/machinery/computer/slot_machine/proc/dispense(amount = 0, cointype = /obj/item/coin/silver, mob/living/target, throwit = FALSE)
var/value = GLOB.coin_values[cointype] || GLOB.coin_values[/obj/item/coin/iron]
INVOKE_ASYNC(src, .proc/become_rich, amount, value, cointype, target, throwit)
return amount % value
/obj/machinery/computer/slot_machine/proc/dispense(amount = 0, cointype = /obj/item/coin/silver, mob/living/target, throwit = 0)
if(paymode == HOLOCHIP)
var/obj/item/holochip/H = new /obj/item/holochip(loc,amount)
/obj/machinery/computer/slot_machine/proc/become_rich(amount, value, cointype = /obj/item/coin/silver, mob/living/target, throwit = FALSE)
if(value <= 0)
return
while(amount >= value && !QDELETED(src))
var/obj/item/coin/C = new cointype(loc) //DOUBLE THE PAIN
amount -= value
if(throwit && target)
C.throw_at(target, 3, 10)
else
random_step(C, 2, 40)
CHECK_TICK
H.throw_at(target, 3, 10)
else
var/value = coinvalues["[cointype]"]
if(value <= 0)
CRASH("Coin value of zero, refusing to payout in dispenser")
while(amount >= value)
var/obj/item/coin/C = new cointype(loc) //DOUBLE THE PAIN
amount -= value
if(throwit && target)
C.throw_at(target, 3, 10)
else
random_step(C, 2, 40)
return amount
#undef SEVEN
#undef SPIN_TIME
@@ -311,3 +355,5 @@
#undef BIG_PRIZE
#undef SMALL_PRIZE
#undef SPIN_PRICE
#undef HOLOCHIP
#undef COIN
+1
View File
@@ -578,6 +578,7 @@
/obj/mecha/proc/mechstep(direction)
var/current_dir = dir
set_glide_size(DELAY_TO_GLIDE_SIZE(step_in))
var/result = step(src,direction)
if(strafe)
setDir(current_dir)
+18 -9
View File
@@ -14,6 +14,9 @@
if(.)
return
if(can_buckle && has_buckled_mobs())
if(ishuman(src)) //prevent people from unbuckling fireman-carried/piggybacked people unless on disarm or harm intents
if(act_intent == INTENT_HELP || act_intent == INTENT_GRAB)
return
if(buckled_mobs.len > 1)
var/unbuckled = input(user, "Who do you wish to unbuckle?","Unbuckle Who?") as null|mob in buckled_mobs
if(user_unbuckle_mob(unbuckled,user))
@@ -84,16 +87,22 @@
M.IgniteMob()
/atom/movable/proc/unbuckle_mob(mob/living/buckled_mob, force=FALSE)
if(istype(buckled_mob) && buckled_mob.buckled == src && (buckled_mob.can_unbuckle() || force))
. = buckled_mob
buckled_mob.buckled = null
buckled_mob.anchored = initial(buckled_mob.anchored)
buckled_mob.update_mobility()
buckled_mob.clear_alert("buckled")
buckled_mobs -= buckled_mob
SEND_SIGNAL(src, COMSIG_MOVABLE_UNBUCKLE, buckled_mob, force)
if(!isliving(buckled_mob))
CRASH("Non-living [buckled_mob] thing called unbuckle_mob() for source.")
if(buckled_mob.buckled != src)
CRASH("[buckled_mob] called unbuckle_mob() for source while having buckled as [buckled_mob.buckled].")
if(!force && !buckled_mob.can_unbuckle())
return
. = buckled_mob
buckled_mob.buckled = null
buckled_mob.anchored = initial(buckled_mob.anchored)
buckled_mob.update_mobility()
buckled_mob.clear_alert("buckled")
buckled_mob.set_glide_size(DELAY_TO_GLIDE_SIZE(buckled_mob.total_multiplicative_slowdown()))
buckled_mobs -= buckled_mob
SEND_SIGNAL(src, COMSIG_MOVABLE_UNBUCKLE, buckled_mob, force)
post_unbuckle_mob(.)
post_unbuckle_mob(.)
/atom/movable/proc/unbuckle_all_mobs(force=FALSE)
if(!has_buckled_mobs())
+1
View File
@@ -53,6 +53,7 @@
return 0
/obj/effect/acid/Crossed(AM as mob|obj)
. = ..()
if(isliving(AM))
var/mob/living/L = AM
if(L.movement_type & FLYING)
+1 -1
View File
@@ -138,7 +138,7 @@
/obj/effect/anomaly/grav/high/Initialize(mapload, new_lifespan)
. = ..()
setup_grav_field()
INVOKE_ASYNC(src, .proc/setup_grav_field)
/obj/effect/anomaly/grav/high/proc/setup_grav_field()
grav_field = make_field(/datum/proximity_monitor/advanced/gravity, list("current_range" = 7, "host" = src, "gravity_value" = rand(0,3)))
@@ -69,4 +69,5 @@
persistent = FALSE
/obj/effect/decal/cleanable/oil/slippery/Initialize()
. = ..()
AddComponent(/datum/component/slippery, 80, (NO_SLIP_WHEN_WALKING | SLIDE))
+7 -1
View File
@@ -5,6 +5,7 @@
var/list/checkers //list of /obj/effect/abstract/proximity_checkers
var/current_range
var/ignore_if_not_on_turf //don't check turfs in range if the host's loc isn't a turf
var/wire = FALSE
/datum/proximity_monitor/New(atom/_host, range, _ignore_if_not_on_turf = TRUE)
checkers = list()
@@ -35,6 +36,8 @@
return ..()
/datum/proximity_monitor/proc/HandleMove()
SIGNAL_HANDLER
var/atom/_host = host
var/atom/new_host_loc = _host.loc
if(last_host_loc != new_host_loc)
@@ -58,6 +61,8 @@
var/atom/_host = host
var/atom/loc_to_use = ignore_if_not_on_turf ? _host.loc : get_turf(_host)
if(wire && !isturf(loc_to_use)) //it makes assemblies attached on wires work
loc_to_use = get_turf(loc_to_use)
if(!isturf(loc_to_use)) //only check the host's loc
if(range)
var/obj/effect/abstract/proximity_checker/pc
@@ -109,4 +114,5 @@
/obj/effect/abstract/proximity_checker/Crossed(atom/movable/AM)
set waitfor = FALSE
monitor?.hasprox_receiver.HasProximity(AM)
. = ..()
monitor?.hasprox_receiver?.HasProximity(AM)
@@ -170,6 +170,7 @@
/obj/item/clothing/under/rank/civilian/mime/sexy)
/obj/effect/spawner/bundle/crate/Initialize(mapload)
SHOULD_CALL_PARENT(FALSE)
if(items && items.len)
var/turf/T = get_turf(src)
var/obj/structure/closet/LC = locate(/obj/structure/closet) in T
@@ -664,9 +664,8 @@
lootcount = 1
spawn_on_turf = FALSE
loot = list("" = 50,
/obj/item/weaponcrafting/improvised_parts/rifle_receiver = 13,
/obj/item/weaponcrafting/improvised_parts/shotgun_receiver = 13,
/obj/item/weaponcrafting/improvised_parts/trigger_assembly = 12,
/obj/item/weaponcrafting/receiver = 25,
/obj/item/weaponcrafting/stock = 25,
)
/obj/effect/spawner/lootdrop/weapon_parts
@@ -674,8 +673,8 @@
lootcount = 1
spawn_on_turf = FALSE
loot = list("" = 80,
/obj/item/weaponcrafting/improvised_parts/rifle_receiver = 5,
/obj/item/weaponcrafting/improvised_parts/trigger_assembly = 5,
/obj/item/weaponcrafting/receiver = 5,
/obj/item/weaponcrafting/stock = 5,
)
/obj/effect/spawner/lootdrop/ammo
@@ -15,5 +15,5 @@
message_admins("An alien egg has been delivered to [ADMIN_VERBOSEJMP(T)].")
log_game("An alien egg has been delivered to [AREACOORD(T)]")
var/message = "Attention [station_name()], we have entrusted you with a research specimen in [get_area_name(T, TRUE)]. Remember to follow all safety precautions when dealing with the specimen."
SSticker.OnRoundstart(CALLBACK(GLOBAL_PROC, /proc/addtimer, CALLBACK(GLOBAL_PROC, /proc/print_command_report, message), announcement_time))
SSticker.OnRoundstart(CALLBACK(GLOBAL_PROC, /proc/_addtimer, CALLBACK(GLOBAL_PROC, /proc/print_command_report, message), announcement_time))
return INITIALIZE_HINT_QDEL
+30 -17
View File
@@ -428,18 +428,19 @@ GLOBAL_VAR_INIT(embedpocalypse, FALSE) // if true, all items will be able to emb
/obj/item/proc/talk_into(mob/M, input, channel, spans, datum/language/language)
return ITALICS | REDUCE_RANGE
/obj/item/proc/dropped(mob/user)
/// Called when a mob drops an item.
/obj/item/proc/dropped(mob/user, silent = FALSE)
SHOULD_CALL_PARENT(TRUE)
current_equipped_slot = null
for(var/X in actions)
var/datum/action/A = X
A.Remove(user)
if(item_flags & DROPDEL)
qdel(src)
item_flags &= ~IN_INVENTORY
if(SEND_SIGNAL(src, COMSIG_ITEM_DROPPED,user) & COMPONENT_DROPPED_RELOCATION)
. = ITEM_RELOCATED_BY_DROPPED
user.update_equipment_speed_mods()
SEND_SIGNAL(src, COMSIG_ITEM_DROPPED,user)
// if(!silent)
// playsound(src, drop_sound, DROP_SOUND_VOLUME, ignore_walls = FALSE)
user?.update_equipment_speed_mods()
// called just as an item is picked up (loc is not yet changed)
/obj/item/proc/pickup(mob/user)
@@ -478,23 +479,33 @@ GLOBAL_VAR_INIT(embedpocalypse, FALSE) // if true, all items will be able to emb
over.MouseDrop_T(src,usr)
return
// called after an item is placed in an equipment slot
// user is mob that equipped it
// slot uses the slot_X defines found in setup.dm
// for items that can be placed in multiple slots
// note this isn't called during the initial dressing of a player
/obj/item/proc/equipped(mob/user, slot)
/**
* Called after an item is placed in an equipment slot.
*
* Note that hands count as slots.
*
* Arguments:
* * user is mob that equipped it
* * slot uses the slot_X defines found in setup.dm for items that can be placed in multiple slots
* * Initial is used to indicate whether or not this is the initial equipment (job datums etc) or just a player doing it
*/
/obj/item/proc/equipped(mob/user, slot, initial = FALSE)
SHOULD_CALL_PARENT(TRUE)
. = SEND_SIGNAL(src, COMSIG_ITEM_EQUIPPED, user, slot)
SEND_SIGNAL(src, COMSIG_ITEM_EQUIPPED, user, slot)
current_equipped_slot = slot
if(!(. & COMPONENT_NO_GRANT_ACTIONS))
for(var/X in actions)
var/datum/action/A = X
if(item_action_slot_check(slot, user, A)) //some items only give their actions buttons when in a specific slot.
A.Grant(user)
for(var/X in actions)
var/datum/action/A = X
if(item_action_slot_check(slot, user, A)) //some items only give their actions buttons when in a specific slot.
A.Grant(user)
item_flags |= IN_INVENTORY
// if(!initial)
// if(equip_sound && (slot_flags & slot))
// playsound(src, equip_sound, EQUIP_SOUND_VOLUME, TRUE, ignore_walls = FALSE)
// else if(slot == ITEM_SLOT_HANDS)
// playsound(src, pickup_sound, PICKUP_SOUND_VOLUME, ignore_walls = FALSE)
user.update_equipment_speed_mods()
//Overlays for the worn overlay so you can overlay while you overlay
//eg: ammo counters, primed grenade flashing, etc.
//"icon_file" is used automatically for inhands etc. to make sure it gets the right inhand file
@@ -661,6 +672,8 @@ GLOBAL_VAR_INIT(embedpocalypse, FALSE) // if true, all items will be able to emb
else
playsound(hit_atom, 'sound/weapons/throwtap.ogg', 1, volume, -1)
// else
// playsound(src, drop_sound, YEET_SOUND_VOLUME, ignore_walls = FALSE)
return hit_atom.hitby(src, 0, itempush, throwingdatum=throwingdatum)
/obj/item/throw_at(atom/target, range, speed, mob/thrower, spin=1, diagonals_first = 0, datum/callback/callback, force, messy_throw = TRUE)
@@ -263,6 +263,7 @@
/obj/machinery/vending/cola = "Robust Softdrinks",
/obj/machinery/vending/cigarette = "ShadyCigs Deluxe",
/obj/machinery/vending/games = "\improper Good Clean Fun",
/obj/machinery/vending/kink = "KinkMate",
/obj/machinery/vending/autodrobe = "AutoDrobe",
/obj/machinery/vending/assist = "\improper Vendomat",
/obj/machinery/vending/engivend = "\improper Engi-Vend",
@@ -347,9 +347,9 @@
last_hearcheck = world.time
for(var/mob/H in hearing_mobs)
if(!istype(H.loc, /obj/item/dogborg/sleeper))
H.playsound_local(source, null, 45, falloff = 0, S = pred_death)
H.playsound_local(source, null, 45, S = pred_death)
else if(H in contents)
H.playsound_local(source, null, 65, falloff = 0, S = prey_death)
H.playsound_local(source, null, 65, S = prey_death)
for(var/belly in T.vore_organs)
var/obj/belly/B = belly
for(var/atom/movable/thing in B)
@@ -391,9 +391,9 @@
last_hearcheck = world.time
for(var/mob/H in hearing_mobs)
if(!istype(H.loc, /obj/item/dogborg/sleeper))
H.playsound_local(source, null, 45, falloff = 0, S = pred_digest)
H.playsound_local(source, null, 45, S = pred_digest)
else if(H in contents)
H.playsound_local(source, null, 65, falloff = 0, S = prey_digest)
H.playsound_local(source, null, 65, S = prey_digest)
update_gut(hound)
@@ -85,6 +85,7 @@
/obj/item/grenade/plastic/Crossed(atom/movable/AM)
if(nadeassembly)
nadeassembly.Crossed(AM)
. = ..()
/obj/item/grenade/plastic/on_found(mob/finder)
if(nadeassembly)
+1
View File
@@ -803,6 +803,7 @@
force = 4
throwforce = 0
attack_verb = list("whipped", "repented", "lashed", "flagellated")
slot_flags = ITEM_SLOT_BELT
var/praying = FALSE
var/deity_name = "Coderbus" //This is the default, hopefully won't actually appear if the religion subsystem is running properly
+1
View File
@@ -466,6 +466,7 @@ GLOBAL_LIST_INIT(valid_plushie_paths, valid_plushie_paths())
can_random_spawn = FALSE
/obj/item/toy/plush/random/Initialize()
SHOULD_CALL_PARENT(FALSE)
var/newtype
var/list/snowflake_list = CONFIG_GET(keyed_list/snowflake_plushies)
+1 -1
View File
@@ -134,7 +134,7 @@
/obj/item/pressure_plate/hologrid/Crossed(atom/movable/AM)
. = ..()
if(trigger_item && istype(AM, specific_item) && !claimed)
AM.anchored = TRUE
AM.set_anchored(TRUE)
flick("laserbox_burn", AM)
trigger()
QDEL_IN(src, 15)
+57 -5
View File
@@ -173,11 +173,11 @@
"<span class='italics'>You hear cutting.</span>")
use(2)
else if(I.is_drainable() && I.reagents.has_reagent(/datum/reagent/space_cleaner/sterilizine))
if(!I.reagents.has_reagent(/datum/reagent/space_cleaner/sterilizine, 10))
if(!I.reagents.has_reagent(/datum/reagent/space_cleaner/sterilizine, 5))
to_chat(user, "<span class='warning'>There's not enough sterilizine in [I] to sterilize [src]!</span>")
return
user.visible_message("<span class='notice'>[user] pours the contents of [I] onto [src], sterilizing it.</span>", "<span class='notice'>You pour the contents of [I] onto [src], sterilizing it.</span>")
I.reagents.remove_reagent(/datum/reagent/space_cleaner/sterilizine, 10)
user.visible_message("<span class='notice'>[user] sterilizes [src] with the contents of [I].</span>", "<span class='notice'>You pour the contents of [I] onto [src], sterilizing it.</span>")
I.reagents.remove_reagent(/datum/reagent/space_cleaner/sterilizine, 5)
new /obj/item/stack/medical/gauze/adv/one(user.drop_location())
use(1)
else
@@ -187,6 +187,9 @@
user.visible_message("<span class='suicide'>[user] begins tightening \the [src] around [user.p_their()] neck! It looks like [user.p_they()] forgot how to use medical supplies!</span>")
return OXYLOSS
/obj/item/stack/medical/gauze/one
amount = 1
/obj/item/stack/medical/gauze/improvised
name = "improvised gauze"
singular_name = "improvised gauze"
@@ -204,8 +207,9 @@
heal_brute = 6
self_delay = 45
other_delay = 15
absorption_rate = 0.4
absorption_capacity = 6
absorption_rate = 0.5
absorption_capacity = 12
splint_factor = 0.15
/obj/item/stack/medical/gauze/adv/one
amount = 1
@@ -472,3 +476,51 @@
return TRUE
to_chat(user, "<span class='warning'>You can't heal [M] with the \the [src]!</span>")
/obj/item/stack/medical/nanogel
name = "nanogel"
singular_name = "nanogel"
desc = "A highly advanced gel that when applied on a sufficiently repaired robotic limb will neutralize internal damage if present, allowing further repairs without the need for surgery."
self_delay = 150 //Agonizingly slow if used on self, but, not completely forbidden because antags with robolimbs need a way to handle their thresholds.
other_delay = 30 //Pretty fast if used on others.
amount = 12
max_amount = 12 //Two synths worth of fixing, if every single bodypart of them has internal damage. Usually, probably more like 6-12.
icon_state = "nanogel"
var/being_applied = FALSE //No doafter stacking.
/obj/item/stack/medical/nanogel/try_heal(mob/living/M, mob/user, silent = FALSE)
if(being_applied)
to_chat(user, "<span class='warning'>You are already applying [src]!</span>")
return
if(!iscarbon(M))
to_chat(user, "<span class='warning'>This won't work on [M]!</span>")
return
being_applied = TRUE
..()
being_applied = FALSE
/obj/item/stack/medical/nanogel/heal(mob/living/M, mob/user)
var/mob/living/carbon/C = M //Only carbons should be able to get here
if(!C)
return
var/obj/item/bodypart/affecting = C.get_bodypart(check_zone(user.zone_selected))
if(!affecting) //Missing limb?
to_chat(user, "<span class='warning'>[C] doesn't have \a [parse_zone(user.zone_selected)]!</span>")
return
if(!affecting.is_robotic_limb())
to_chat(user, "<span class='warning'>This won't work on nonrobotic limbs!</span>")
return
if(!affecting.threshhold_brute_passed && !affecting.threshhold_burn_passed)
to_chat(user, "<span class='warning'>There is no need to use this on [affecting]</span>")
return
if(affecting.threshhold_brute_passed && affecting.brute_dam == affecting.threshhold_passed_mindamage)
. = TRUE
affecting.threshhold_brute_passed = FALSE
if(affecting.threshhold_burn_passed && affecting.burn_dam == affecting.threshhold_passed_mindamage)
. = TRUE
affecting.threshhold_burn_passed = FALSE
if(.)
user.visible_message("<span class='green'>The nanogel gets to work on [C], repairing [affecting]'s internal damage.</span>", "<span_class='green'>You watch as the nanogel gets to work on fixing the internal damage in [affecting]</span>")
return
//If it gets here: It failed, lets tell the user why.
to_chat(user, "<span class='warning'>[src] fails to work on [affecting] due to residual [(affecting.threshhold_burn_passed && affecting.threshhold_burn_passed) ? "brute and burn" : "[affecting.threshhold_burn_passed ? "burn" : "brute"]"] damage! Perform some external repairs before using this.</span>")
@@ -246,7 +246,6 @@ GLOBAL_LIST_INIT(wood_recipes, list ( \
new /datum/stack_recipe("pew (right)", /obj/structure/chair/pew/right, 3, one_per_turf = TRUE, on_floor = TRUE),\
)),
null, \
new/datum/stack_recipe("wooden firearm body", /obj/item/weaponcrafting/improvised_parts/wooden_body, 10, time = 20), \
new/datum/stack_recipe("rifle stock", /obj/item/weaponcrafting/stock, 10, time = 20), \
new/datum/stack_recipe("rolling pin", /obj/item/kitchen/rollingpin, 2, time = 30), \
new/datum/stack_recipe("wooden bucket", /obj/item/reagent_containers/glass/bucket/wood, 2, time = 30), \
@@ -391,7 +390,7 @@ GLOBAL_LIST_INIT(cloth_recipes, list ( \
new/datum/stack_recipe("construction bag", /obj/item/storage/bag/construction, 4), \
null, \
new/datum/stack_recipe("string", /obj/item/weaponcrafting/string, 1, time = 10), \
new/datum/stack_recipe("improvised gauze", /obj/item/stack/medical/gauze/improvised, 1, 2, 6), \
new/datum/stack_recipe("improvised gauze", /obj/item/stack/medical/gauze/improvised, 1, 2, 10), \
new/datum/stack_recipe("rag", /obj/item/reagent_containers/rag, 1), \
new/datum/stack_recipe("towel", /obj/item/reagent_containers/rag/towel, 3), \
new/datum/stack_recipe("bedsheet", /obj/item/bedsheet, 3), \
+1 -1
View File
@@ -65,7 +65,7 @@
if(merge)
for(var/obj/item/stack/S in loc)
if(S.merge_type == merge_type)
merge(S)
INVOKE_ASYNC(src, .proc/merge, S)
var/list/temp_recipes = get_main_recipes()
recipes = temp_recipes.Copy()
if(material_type)
+4 -4
View File
@@ -196,7 +196,7 @@
return FALSE
stunpwr *= round(stuncharge/hitcost, 0.1)
if(!user.UseStaminaBuffer(getweight(user, STAM_COST_BATON_MOB_MULT), warn = TRUE))
if(user && !user.UseStaminaBuffer(getweight(user, STAM_COST_BATON_MOB_MULT), warn = TRUE))
return FALSE
if(!disarming)
@@ -317,12 +317,12 @@
/obj/item/melee/baton/boomerang
name = "\improper OZtek Boomerang"
desc = "A device invented in 2486 for the great Space Emu War by the confederacy of Australicus, these high-tech boomerangs also work exceptionally well at stunning crewmembers. Just be careful to catch it when thrown!"
throw_speed = 1
throw_speed = 1.5
icon_state = "boomerang"
item_state = "boomerang"
force = 5
throwforce = 5
throw_range = 5
throw_range = 10
hitcost = 2000
throw_hit_chance = 99 //Have you prayed today?
custom_materials = list(/datum/material/iron = 10000, /datum/material/glass = 4000, /datum/material/silver = 10000, /datum/material/gold = 2000)
@@ -331,7 +331,7 @@
if(turned_on)
if(ishuman(thrower))
var/mob/living/carbon/human/H = thrower
H.throw_mode_off() //so they can catch it on the return.
H.throw_mode_on() //so they can catch it on the return.
return ..()
/obj/item/melee/baton/boomerang/throw_impact(atom/hit_atom, datum/thrownthing/throwingdatum)
+1
View File
@@ -531,6 +531,7 @@
pop_burst()
/obj/item/toy/snappop/Crossed(H as mob|obj)
. = ..()
if(ishuman(H) || issilicon(H)) //i guess carp and shit shouldn't set them off
var/mob/living/carbon/M = H
if(issilicon(H) || M.m_intent == MOVE_INTENT_RUN)
@@ -96,7 +96,7 @@
new /obj/item/tank/internals/emergency_oxygen/engi(src)
new /obj/item/analyzer(src)
new /obj/item/holosign_creator/atmos(src)
new /obj/item/holosign_creator/firelock(src)
new /obj/item/holosign_creator/firelock(src) //what if atmos techs could test things they are meant to test, wild, innit?
new /obj/item/watertank/atmos(src)
new /obj/item/clothing/suit/fire/atmos(src)
new /obj/item/clothing/head/hardhat/atmos(src)
+1 -1
View File
@@ -269,13 +269,13 @@
UnregisterSignal(source, COMSIG_MOVABLE_MOVED)
/obj/structure/table/rolling/Moved(atom/OldLoc, Dir)
. = ..()
for(var/mob/M in OldLoc.contents)//Kidnap everyone on top
M.forceMove(loc)
for(var/x in attached_items)
var/atom/movable/AM = x
if(!AM.Move(loc))
RemoveItemFromTable(AM, AM.loc)
return TRUE
/*
* Glass tables
@@ -126,12 +126,13 @@
if(current_tube == null)
setDir(next_dir)
Move(get_step(loc, dir), dir) // Allow collisions when leaving the tubes.
Move(get_step(loc, dir), dir, DELAY_TO_GLIDE_SIZE(exit_delay)) // Allow collisions when leaving the tubes.
break
last_delay = current_tube.enter_delay(src, next_dir)
sleep(last_delay)
setDir(next_dir)
set_glide_size(DELAY_TO_GLIDE_SIZE(last_delay + exit_delay))
forceMove(next_loc) // When moving from one tube to another, skip collision and such.
density = current_tube.density
+2
View File
@@ -56,6 +56,7 @@
animate(src, alpha = initial(alpha), time = time_between_triggers)
/obj/structure/trap/Crossed(atom/movable/AM)
. = ..()
if(last_trigger + time_between_triggers > world.time)
return
// Don't want the traps triggered by sparks, ghosts or projectiles.
@@ -67,6 +68,7 @@
return
if(M.anti_magic_check())
flare()
return
if(charges <= 0)
return
flare()
+2 -1
View File
@@ -59,7 +59,7 @@ GLOBAL_LIST_INIT(freqtospan, list(
var/endspanpart = "</span>"
//Message
var/messagepart = " <span class='message'>[say_emphasis(lang_treat(speaker, message_language, raw_message, spans, message_mode))]</span></span>"
var/messagepart = " <span class='message'>[lang_treat(speaker, message_language, raw_message, spans, message_mode)]</span></span>"
var/languageicon = ""
var/datum/language/D = GLOB.language_datum_instances[message_language]
@@ -116,6 +116,7 @@ GLOBAL_LIST_INIT(freqtospan, list(
/atom/movable/proc/lang_treat(atom/movable/speaker, datum/language/language, raw_message, list/spans, message_mode, no_quote = FALSE)
if(has_language(language))
var/atom/movable/AM = speaker.GetSource()
raw_message = say_emphasis(raw_message)
if(AM) //Basically means "if the speaker is virtual"
return no_quote ? AM.quoteless_say_quote(raw_message, spans, message_mode) : AM.say_quote(raw_message, spans, message_mode)
else
+133 -37
View File
@@ -1,4 +1,49 @@
/proc/playsound(atom/source, soundin, vol as num, vary, extrarange as num, falloff, frequency = null, channel = 0, pressure_affected = TRUE, ignore_walls = TRUE, soundenvwet = -10000, soundenvdry = 0)
// /tg/ reverb disabled
/*
///Default override for echo
/sound
echo = list(
0, // Direct
0, // DirectHF
-10000, // Room, -10000 means no low frequency sound reverb
-10000, // RoomHF, -10000 means no high frequency sound reverb
0, // Obstruction
0, // ObstructionLFRatio
0, // Occlusion
0.25, // OcclusionLFRatio
1.5, // OcclusionRoomRatio
1.0, // OcclusionDirectRatio
0, // Exclusion
1.0, // ExclusionLFRatio
0, // OutsideVolumeHF
0, // DopplerFactor
0, // RolloffFactor
0, // RoomRolloffFactor
1.0, // AirAbsorptionFactor
0, // Flags (1 = Auto Direct, 2 = Auto Room, 4 = Auto RoomHF)
)
environment = SOUND_ENVIRONMENT_NONE //Default to none so sounds without overrides dont get reverb
*/
/*! playsound
playsound is a proc used to play a 3D sound in a specific range. This uses SOUND_RANGE + extra_range to determine that.
source - Origin of sound
soundin - Either a file, or a string that can be used to get an SFX
vol - The volume of the sound, excluding falloff and pressure affection.
vary - bool that determines if the sound changes pitch every time it plays
extrarange - modifier for sound range. This gets added on top of SOUND_RANGE
falloff_exponent - Rate of falloff for the audio. Higher means quicker drop to low volume. Should generally be over 1 to indicate a quick dive to 0 rather than a slow dive.
frequency - playback speed of audio
channel - The channel the sound is played at
pressure_affected - Whether or not difference in pressure affects the sound (E.g. if you can hear in space)
ignore_walls - Whether or not the sound can pass through walls.
falloff_distance - Distance at which falloff begins. Sound is at peak volume (in regards to falloff) aslong as it is in this range.
*/
/proc/playsound(atom/source, soundin, vol as num, vary, extrarange as num, falloff_exponent = SOUND_FALLOFF_EXPONENT, frequency = null, channel = 0, pressure_affected = TRUE, ignore_walls = TRUE, falloff_distance = SOUND_DEFAULT_FALLOFF_DISTANCE, envwet = -10000, envdry = 0)
if(isarea(source))
CRASH("playsound(): source is an area")
@@ -10,26 +55,60 @@
//allocate a channel if necessary now so its the same for everyone
channel = channel || SSsounds.random_available_channel()
// Looping through the player list has the added bonus of working for mobs inside containers
// Looping through the player list has the added bonus of working for mobs inside containers
var/sound/S = sound(get_sfx(soundin))
var/maxdistance = (world.view + extrarange)
var/z = turf_source.z
var/list/listeners = SSmobs.clients_by_zlevel[z]
var/maxdistance = SOUND_RANGE + extrarange
var/source_z = turf_source.z
var/list/listeners = SSmobs.clients_by_zlevel[source_z].Copy()
var/turf/above_turf = SSmapping.get_turf_above(turf_source)
var/turf/below_turf = SSmapping.get_turf_below(turf_source)
if(!ignore_walls) //these sounds don't carry through walls
listeners = listeners & hearers(maxdistance,turf_source)
if(above_turf && istransparentturf(above_turf))
listeners += hearers(maxdistance,above_turf)
if(below_turf && istransparentturf(turf_source))
listeners += hearers(maxdistance,below_turf)
else
if(above_turf && istransparentturf(above_turf))
listeners += SSmobs.clients_by_zlevel[above_turf.z]
if(below_turf && istransparentturf(turf_source))
listeners += SSmobs.clients_by_zlevel[below_turf.z]
for(var/P in listeners)
var/mob/M = P
if(get_dist(M, turf_source) <= maxdistance)
M.playsound_local(turf_source, soundin, vol, vary, frequency, falloff, channel, pressure_affected, S, soundenvwet, soundenvdry)
for(var/P in SSmobs.dead_players_by_zlevel[z])
M.playsound_local(turf_source, soundin, vol, vary, frequency, falloff_exponent, channel, pressure_affected, S, maxdistance, falloff_distance, null, envwet, envdry)
for(var/P in SSmobs.dead_players_by_zlevel[source_z])
var/mob/M = P
if(get_dist(M, turf_source) <= maxdistance)
M.playsound_local(turf_source, soundin, vol, vary, frequency, falloff, channel, pressure_affected, S, soundenvwet, soundenvdry)
M.playsound_local(turf_source, soundin, vol, vary, frequency, falloff_exponent, channel, pressure_affected, S, maxdistance, falloff_distance, null, envwet, envdry)
/mob/proc/playsound_local(turf/turf_source, soundin, vol as num, vary, frequency, falloff, channel = 0, pressure_affected = TRUE, sound/S, envwet = -10000, envdry = 0, manual_x, manual_y, distance_multiplier = 1)
if(audiovisual_redirect)
var/turf/T = get_turf(src)
audiovisual_redirect.playsound_local(turf_source, soundin, vol, vary, frequency, falloff, channel, pressure_affected, S, 0, -1000, turf_source.x - T.x, turf_source.y - T.y, distance_multiplier)
/*! playsound
playsound_local is a proc used to play a sound directly on a mob from a specific turf.
This is called by playsound to send sounds to players, in which case it also gets the max_distance of that sound.
turf_source - Origin of sound
soundin - Either a file, or a string that can be used to get an SFX
vol - The volume of the sound, excluding falloff
vary - bool that determines if the sound changes pitch every time it plays
frequency - playback speed of audio
falloff_exponent - Rate of falloff for the audio. Higher means quicker drop to low volume. Should generally be over 1 to indicate a quick dive to 0 rather than a slow dive.
channel - The channel the sound is played at
pressure_affected - Whether or not difference in pressure affects the sound (E.g. if you can hear in space)
max_distance - The peak distance of the sound, if this is a 3D sound
falloff_distance - Distance at which falloff begins, if this is a 3D sound
distance_multiplier - Can be used to multiply the distance at which the sound is heard
*/
/mob/proc/playsound_local(turf/turf_source, soundin, vol as num, vary, frequency, falloff_exponent = SOUND_FALLOFF_EXPONENT, channel = 0, pressure_affected = TRUE, sound/S, max_distance, falloff_distance = SOUND_DEFAULT_FALLOFF_DISTANCE, distance_multiplier = 1, envwet = -10000, envdry = 0)
if(!client || !can_hear())
return
@@ -39,7 +118,9 @@
S.wait = 0 //No queue
S.channel = channel || SSsounds.random_available_channel()
S.volume = vol
// CITADEL EDIT - Force citadel reverb
S.environment = 7
// End
if(vary)
if(frequency)
@@ -51,13 +132,13 @@
var/turf/T = get_turf(src)
//sound volume falloff with distance
var/distance = 0
if(!manual_x && !manual_y)
distance = get_dist(T, turf_source)
var/distance = get_dist(T, turf_source)
distance *= distance_multiplier
S.volume -= max(distance - world.view, 0) * 2 //multiplicative falloff to add on top of natural audio falloff.
if(max_distance) //If theres no max_distance we're not a 3D sound, so no falloff.
S.volume -= (max(distance - falloff_distance, 0) ** (1 / falloff_exponent)) / ((max(max_distance, distance) - falloff_distance) ** (1 / falloff_exponent)) * S.volume
//https://www.desmos.com/calculator/sqdfl8ipgf
if(pressure_affected)
//Atmosphere affects sound
@@ -72,42 +153,57 @@
else //space
pressure_factor = 0
S.echo = list(envdry, null, envwet, null, null, null, null, null, null, null, null, null, null, 1, 1, 1, null, null)
if(distance <= 1)
pressure_factor = max(pressure_factor, 0.15) //touching the source of the sound
S.volume *= pressure_factor
//End Atmosphere affecting sound
/// Citadel edit - Citadel reverb
S.echo = list(envdry, null, envwet, null, null, null, null, null, null, null, null, null, null, 1, 1, 1, null, null)
/// End
if(S.volume <= 0)
return //No sound
var/dx = 0 // Hearing from the right/left
if(!manual_x)
dx = turf_source.x - T.x
else
dx = manual_x
var/dx = turf_source.x - T.x // Hearing from the right/left
S.x = dx * distance_multiplier
var/dz = 0 // Hearing from infront/behind
if(!manual_x)
dz = turf_source.y - T.y
else
dz = manual_y
var/dz = turf_source.y - T.y // Hearing from infront/behind
S.z = dz * distance_multiplier
// The y value is for above your head, but there is no ceiling in 2d spessmens.
S.y = 1
S.falloff = (falloff ? falloff : FALLOFF_SOUNDS)
var/dy = (turf_source.z - T.z) * 5 * distance_multiplier // Hearing from above / below, multiplied by 5 because we assume height is further along coords.
S.y = dy
S.falloff = isnull(max_distance)? FALLOFF_SOUNDS : max_distance //use max_distance, else just use 1 as we are a direct sound so falloff isnt relevant.
/*
/// Tg reverb removed
if(S.environment == SOUND_ENVIRONMENT_NONE)
if(sound_environment_override != SOUND_ENVIRONMENT_NONE)
S.environment = sound_environment_override
else
var/area/A = get_area(src)
if(A.sound_environment != SOUND_ENVIRONMENT_NONE)
S.environment = A.sound_environment
if(use_reverb)
if(S.environment == SOUND_ENVIRONMENT_NONE) //We have reverb, reset our echo setting
S.environment = SOUND_ENVIRONMENT_CONCERT_HALL
S.echo = list(0, null, -10000, null, null, null, null, null, null, null, null, null, null, 1, 1, 1, null, null)
else
S.echo[3] = 0 //Room setting, 0 means normal reverb
S.echo[4] = 0 //RoomHF setting, 0 means normal reverb.
*/
///
SEND_SOUND(src, S)
/proc/sound_to_playing_players(soundin, volume = 100, vary = FALSE, frequency = 0, falloff = FALSE, channel = 0, pressure_affected = FALSE, sound/S)
/proc/sound_to_playing_players(soundin, volume = 100, vary = FALSE, frequency = 0, channel = 0, pressure_affected = FALSE, sound/S)
if(!S)
S = sound(get_sfx(soundin))
for(var/m in GLOB.player_list)
if(ismob(m) && !isnewplayer(m))
var/mob/M = m
M.playsound_local(M, null, volume, vary, frequency, falloff, channel, pressure_affected, S)
M.playsound_local(M, null, volume, vary, frequency, null, channel, pressure_affected, S)
/mob/proc/stop_sound_channel(chan)
SEND_SOUND(src, sound(null, repeat = 0, wait = 0, channel = chan))
@@ -130,14 +226,14 @@
/proc/get_sfx(soundin)
if(istext(soundin))
switch(soundin)
if ("explosion_creaking") // from skyrat-ss13/skyrat13/pull/3295
soundin = pick('sound/effects/explosioncreak1.ogg', 'sound/effects/explosioncreak2.ogg')
if ("hull_creaking") // from skyrat-ss13/skyrat13/pull/3295
soundin = pick('sound/effects/creak1.ogg', 'sound/effects/creak2.ogg', 'sound/effects/creak3.ogg')
if ("shatter")
soundin = pick('sound/effects/glassbr1.ogg','sound/effects/glassbr2.ogg','sound/effects/glassbr3.ogg')
if ("explosion")
soundin = pick('sound/effects/explosion1.ogg','sound/effects/explosion2.ogg')
if ("explosion_creaking")
soundin = pick('sound/effects/explosioncreak1.ogg', 'sound/effects/explosioncreak2.ogg')
if ("hull_creaking")
soundin = pick('sound/effects/creak1.ogg', 'sound/effects/creak2.ogg', 'sound/effects/creak3.ogg')
if ("sparks")
soundin = pick('sound/effects/sparks1.ogg','sound/effects/sparks2.ogg','sound/effects/sparks3.ogg','sound/effects/sparks4.ogg')
if ("rustle")
@@ -196,7 +196,7 @@
if(M.client && (is_servant_of_ratvar(M) || isobserver(M) || M.stat == DEAD))
viewing += M.client
flick_overlay(I, viewing, 8)
L.adjustToxLoss(-3, TRUE, TRUE)
L.adjustToxLoss(-3, TRUE, TRUE, toxins_type = TOX_OMNI)
/turf/open/floor/clockwork/try_replace_tile(obj/item/stack/tile/T, mob/user, params)
return
@@ -278,4 +278,4 @@
heavyfootstep = FOOTSTEP_RUST
/turf/open/floor/plating/rust/rust_heretic_act()
return
return
+32 -6
View File
@@ -25,7 +25,13 @@
//This is used to optimize the map loader
return
/**
* Space Initialize
*
* Doesn't call parent, see [/atom/proc/Initialize]
*/
/turf/open/space/Initialize()
SHOULD_CALL_PARENT(FALSE)
icon_state = SPACE_ICON_STATE
air = space_gas
update_air_ref()
@@ -36,6 +42,15 @@
stack_trace("Warning: [src]([type]) initialized multiple times!")
flags_1 |= INITIALIZED_1
// if (length(smoothing_groups))
// sortTim(smoothing_groups) //In case it's not properly ordered, let's avoid duplicate entries with the same values.
// SET_BITFLAG_LIST(smoothing_groups)
// if (length(canSmoothWith))
// sortTim(canSmoothWith)
// if(canSmoothWith[length(canSmoothWith)] > MAX_S_TURF) //If the last element is higher than the maximum turf-only value, then it must scan turf contents for smoothing targets.
// smoothing_flags |= SMOOTH_OBJ
// SET_BITFLAG_LIST(canSmoothWith)
var/area/A = loc
if(!IS_DYNAMIC_LIGHTING(src) && IS_DYNAMIC_LIGHTING(A))
add_overlay(/obj/effect/fullbright)
@@ -49,6 +64,13 @@
if (opacity)
has_opaque_atom = TRUE
var/turf/T = SSmapping.get_turf_above(src)
if(T)
T.multiz_turf_new(src, DOWN)
T = SSmapping.get_turf_below(src)
if(T)
T.multiz_turf_new(src, UP)
ComponentInitialize()
return INITIALIZE_HINT_NORMAL
@@ -74,6 +96,10 @@
/turf/open/space/Assimilate_Air()
return
//IT SHOULD RETURN NULL YOU MONKEY, WHY IN TARNATION WHAT THE FUCKING FUCK
/turf/open/space/remove_air(amount)
return null
/turf/open/space/proc/update_starlight()
if(CONFIG_GET(flag/starlight))
for(var/t in RANGE_TURFS(1,src)) //RANGE_TURFS is in code\__HELPERS\game.dm
@@ -90,9 +116,8 @@
/turf/open/space/proc/CanBuildHere()
return TRUE
/turf/open/space/handle_slip(mob/living/carbon/C, knockdown_amount, obj/O, lube)
if(lube & FLYING_DOESNT_HELP)
return ..()
/turf/open/space/handle_slip()
return // no lube bullshit, this is space
/turf/open/space/attackby(obj/item/C, mob/user, params)
..()
@@ -107,15 +132,16 @@
return
if(L)
if(R.use(1))
qdel(L)
to_chat(user, "<span class='notice'>You construct a catwalk.</span>")
playsound(src, 'sound/weapons/genhit.ogg', 50, 1)
playsound(src, 'sound/weapons/genhit.ogg', 50, TRUE)
new/obj/structure/lattice/catwalk(src)
else
to_chat(user, "<span class='warning'>You need two rods to build a catwalk!</span>")
return
if(R.use(1))
to_chat(user, "<span class='notice'>You construct a lattice.</span>")
playsound(src, 'sound/weapons/genhit.ogg', 50, 1)
playsound(src, 'sound/weapons/genhit.ogg', 50, TRUE)
ReplaceWithLattice()
else
to_chat(user, "<span class='warning'>You need one rod to build a lattice.</span>")
@@ -126,7 +152,7 @@
var/obj/item/stack/tile/plasteel/S = C
if(S.use(1))
qdel(L)
playsound(src, 'sound/weapons/genhit.ogg', 50, 1)
playsound(src, 'sound/weapons/genhit.ogg', 50, TRUE)
to_chat(user, "<span class='notice'>You build a floor.</span>")
PlaceOnTop(/turf/open/floor/plating, flags = CHANGETURF_INHERIT_AIR)
else
+47 -37
View File
@@ -1,8 +1,11 @@
GLOBAL_LIST_EMPTY(station_turfs)
/// Any floor or wall. What makes up the station and the rest of the map.
/turf
icon = 'icons/turf/floors.dmi'
level = 1
vis_flags = VIS_INHERIT_PLANE|VIS_INHERIT_ID //when this be added to vis_contents of something it inherit something.plane and be associatet with something on clicking,
//important for visualisation of turf in openspace and interraction with openspace that show you turf.
flags_1 = CAN_BE_DIRTY_1
vis_flags = VIS_INHERIT_ID|VIS_INHERIT_PLANE // Important for interaction with and visualization of openspace.
luminosity = 1
var/intact = 1
@@ -19,8 +22,6 @@
var/blocks_air = FALSE
flags_1 = CAN_BE_DIRTY_1
var/list/image/blueprint_data //for the station blueprints, images of objects eg: pipes
var/explosion_level = 0 //for preventing explosion dodging
@@ -41,7 +42,13 @@
return FALSE
. = ..()
/**
* Turf Initialize
*
* Doesn't call parent, see [/atom/proc/Initialize]
*/
/turf/Initialize(mapload)
SHOULD_CALL_PARENT(FALSE)
if(flags_1 & INITIALIZED_1)
stack_trace("Warning: [src]([type]) initialized multiple times!")
flags_1 |= INITIALIZED_1
@@ -49,7 +56,7 @@
// by default, vis_contents is inherited from the turf that was here before
vis_contents.Cut()
if(color)
if(color) // is this being used? This is here because parent isn't being called
add_atom_colour(color, FIXED_COLOUR_PRIORITY)
assemble_baseturfs()
@@ -57,6 +64,7 @@
levelupdate()
if(smooth)
queue_smooth(src)
visibilityChanged()
for(var/atom/movable/AM in src)
@@ -76,11 +84,10 @@
var/turf/T = SSmapping.get_turf_above(src)
if(T)
T.multiz_turf_new(src, DOWN)
SEND_SIGNAL(T, COMSIG_TURF_MULTIZ_NEW, src, DOWN)
T = SSmapping.get_turf_below(src)
if(T)
T.multiz_turf_new(src, UP)
SEND_SIGNAL(T, COMSIG_TURF_MULTIZ_NEW, src, UP)
if (opacity)
has_opaque_atom = TRUE
@@ -112,8 +119,6 @@
var/turf/B = new world.turf(src)
for(var/A in B.contents)
qdel(A)
for(var/I in B.vars)
B.vars[I] = null
return
SSair.remove_from_active(src)
visibilityChanged()
@@ -122,12 +127,14 @@
requires_activation = FALSE
..()
/turf/on_attack_hand(mob/user, act_intent = user.a_intent, unarmed_attack_flags)
/turf/on_attack_hand(mob/user)
user.Move_Pulled(src)
/turf/proc/multiz_turf_del(turf/T, dir)
// SEND_SIGNAL(src, COMSIG_TURF_MULTIZ_DEL, T, dir)
/turf/proc/multiz_turf_new(turf/T, dir)
SEND_SIGNAL(src, COMSIG_TURF_MULTIZ_NEW, T, dir)
//zPassIn doesn't necessarily pass an atom!
//direction is direction of travel of air
@@ -158,13 +165,14 @@
prev_turf.visible_message("<span class='danger'>[mov_name] falls through [prev_turf]!</span>")
if(flags & FALL_INTERCEPTED)
return
if(zFall(A, ++levels))
if(zFall(A, levels + 1))
return FALSE
A.visible_message("<span class='danger'>[A] crashes into [src]!</span>")
A.onZImpact(src, levels)
return TRUE
/turf/proc/can_zFall(atom/movable/A, levels = 1, turf/target)
SHOULD_BE_PURE(TRUE)
return zPassOut(A, DOWN, target) && target.zPassIn(A, DOWN, src)
/turf/proc/zFall(atom/movable/A, levels = 1, force = FALSE)
@@ -217,49 +225,54 @@
stack_trace("Non movable passed to turf CanPass : [mover]")
return FALSE
//There's a lot of QDELETED() calls here if someone can figure out how to optimize this but not runtime when something gets deleted by a Bump/CanPass/Cross call, lemme know or go ahead and fix this mess - kevinz000
/turf/Enter(atom/movable/mover, atom/oldloc)
// Do not call ..()
// Byond's default turf/Enter() doesn't have the behaviour we want with Bump()
// By default byond will call Bump() on the first dense object in contents
// Here's hoping it doesn't stay like this for years before we finish conversion to step_
var/atom/firstbump
if(!CanPass(mover, src))
firstbump = src
else
var/canPassSelf = CanPass(mover, src)
if(canPassSelf || (mover.movement_type & UNSTOPPABLE))
for(var/i in contents)
if(QDELETED(mover))
return FALSE //We were deleted, do not attempt to proceed with movement.
if(i == mover || i == mover.loc) // Multi tile objects and moving out of other objects
continue
if(QDELETED(mover))
break
var/atom/movable/thing = i
if(!thing.Cross(mover))
if(CHECK_BITFIELD(mover.movement_type, UNSTOPPABLE))
if(QDELETED(mover)) //Mover deleted from Cross/CanPass, do not proceed.
return FALSE
if((mover.movement_type & UNSTOPPABLE))
mover.Bump(thing)
continue
else
if(!firstbump || ((thing.layer > firstbump.layer || thing.flags_1 & ON_BORDER_1) && !(firstbump.flags_1 & ON_BORDER_1)))
firstbump = thing
if(QDELETED(mover)) //Mover deleted from Cross/CanPass/Bump, do not proceed.
return FALSE
if(!canPassSelf) //Even if mover is unstoppable they need to bump us.
firstbump = src
if(firstbump)
if(!QDELETED(mover))
mover.Bump(firstbump)
return CHECK_BITFIELD(mover.movement_type, UNSTOPPABLE)
mover.Bump(firstbump)
return (mover.movement_type & UNSTOPPABLE)
return TRUE
/turf/Exit(atom/movable/mover, atom/newloc)
. = ..()
if(!.)
if(!. || QDELETED(mover))
return FALSE
for(var/i in contents)
if(QDELETED(mover))
break
if(i == mover)
continue
var/atom/movable/thing = i
if(!thing.Uncross(mover, newloc))
if(thing.flags_1 & ON_BORDER_1)
mover.Bump(thing)
if(!CHECK_BITFIELD(mover.movement_type, UNSTOPPABLE))
if(!(mover.movement_type & UNSTOPPABLE))
return FALSE
if(QDELETED(mover))
return FALSE //We were deleted.
/turf/Entered(atom/movable/AM)
..()
@@ -271,6 +284,7 @@
has_opaque_atom = TRUE // Make sure to do this before reconsider_lights(), incase we're on instant updates. Guaranteed to be on in this case.
reconsider_lights()
/turf/open/Entered(atom/movable/AM)
..()
//melting
@@ -278,7 +292,6 @@
var/obj/O = AM
if(O.obj_flags & FROZEN)
O.make_unfrozen()
if(!AM.zfalling)
zFall(AM)
@@ -336,14 +349,13 @@
/turf/proc/levelupdate()
for(var/obj/O in src)
if(O.level == 1 && (O.flags_1 & INITIALIZED_1))
O.hide(src.intact)
if(O.flags_1 & INITIALIZED_1)
// SEND_SIGNAL(O, COMSIG_OBJ_HIDE, intact)
O.hide(intact)
// override for space turfs, since they should never hide anything
/turf/open/space/levelupdate()
for(var/obj/O in src)
if(O.level == 1 && (O.flags_1 & INITIALIZED_1))
O.hide(0)
return
// Removes all signs of lattice on the pos of the turf -Donkieyo
/turf/proc/RemoveLattice()
@@ -368,13 +380,13 @@
if(.)
return
if(length(src_object.contents()))
to_chat(user, "<span class='notice'>You start dumping out the contents...</span>")
if(!do_after(user,20,target=src_object.parent))
to_chat(usr, "<span class='notice'>You start dumping out the contents...</span>")
if(!do_after(usr,20,target=src_object.parent))
return FALSE
var/list/things = src_object.contents()
var/datum/progressbar/progress = new(user, things.len, src)
while (do_after(user, 10, TRUE, src, FALSE, CALLBACK(src_object, /datum/component/storage.proc/mass_remove_from_storage, src, things, progress)))
while (do_after(usr, 1 SECONDS, TRUE, src, FALSE, CALLBACK(src_object, /datum/component/storage.proc/mass_remove_from_storage, src, things, progress)))
stoplag(1)
qdel(progress)
@@ -494,10 +506,8 @@
I.loc = src
I.setDir(AM.dir)
I.alpha = 128
LAZYADD(blueprint_data, I)
/turf/proc/add_blueprints_preround(atom/movable/AM)
if(!SSticker.HasRoundStarted())
add_blueprints(AM)
@@ -531,7 +541,7 @@
if(!forced)
return
if(has_gravity(src))
playsound(src, "bodyfall", 50, 1)
playsound(src, "bodyfall", 50, TRUE)
faller.drop_all_held_items()
/turf/proc/photograph(limit=20)
+95 -47
View File
@@ -1,21 +1,46 @@
#define RESTART_COUNTER_PATH "data/round_counter.txt"
GLOBAL_VAR(restart_counter)
GLOBAL_VAR_INIT(tgs_initialized, FALSE)
GLOBAL_VAR(topic_status_lastcache)
GLOBAL_LIST(topic_status_cache)
//This happens after the Master subsystem new(s) (it's a global datum)
//So subsystems globals exist, but are not initialised
/**
* World creation
*
* Here is where a round itself is actually begun and setup.
* * db connection setup
* * config loaded from files
* * loads admins
* * Sets up the dynamic menu system
* * and most importantly, calls initialize on the master subsystem, starting the game loop that causes the rest of the game to begin processing and setting up
*
*
* Nothing happens until something moves. ~Albert Einstein
*
* For clarity, this proc gets triggered later in the initialization pipeline, it is not the first thing to happen, as it might seem.
*
* Initialization Pipeline:
* Global vars are new()'ed, (including config, glob, and the master controller will also new and preinit all subsystems when it gets new()ed)
* Compiled in maps are loaded (mainly centcom). all areas/turfs/objs/mobs(ATOMs) in these maps will be new()ed
* world/New() (You are here)
* Once world/New() returns, client's can connect.
* 1 second sleep
* Master Controller initialization.
* Subsystem initialization.
* Non-compiled-in maps are maploaded, all atoms are new()ed
* All atoms in both compiled and uncompiled maps are initialized()
*/
/world/New()
if (fexists(EXTOOLS))
call(EXTOOLS, "maptick_initialize")()
#ifdef EXTOOLS_LOGGING
#ifdef EXTOOLS_LOGGING
call(EXTOOLS, "init_logging")()
else
CRASH("[EXTOOLS] does not exist!")
#endif
#endif
enable_debugger()
#ifdef REFERENCE_TRACKING
enable_reference_tracking()
@@ -23,12 +48,11 @@ GLOBAL_LIST(topic_status_cache)
world.Profile(PROFILE_START)
log_world("World loaded at [TIME_STAMP("hh:mm:ss", FALSE)]!")
GLOB.config_error_log = GLOB.world_manifest_log = GLOB.world_pda_log = GLOB.world_job_debug_log = GLOB.sql_error_log = GLOB.world_href_log = GLOB.world_runtime_log = GLOB.world_attack_log = GLOB.world_game_log = "data/logs/config_error.[GUID()].log" //temporary file used to record errors with loading config, moved to log directory once logging is set bl
make_datum_references_lists() //initialises global lists for referencing frequently used datums (so that we only ever do it once)
log_world("World loaded at [TIME_STAMP("hh:mm:ss", FALSE)]!")
make_datum_references_lists() //initialises global lists for referencing frequently used datums (so that we only ever do it once)
GLOB.revdata = new
@@ -36,6 +60,9 @@ GLOBAL_LIST(topic_status_cache)
config.Load(params[OVERRIDE_CONFIG_DIRECTORY_PARAMETER])
load_admins()
load_mentors()
//SetupLogs depends on the RoundID, so lets check
//DB schema and set RoundID if we can
SSdbcore.CheckSchemaVersion()
@@ -49,14 +76,9 @@ GLOBAL_LIST(topic_status_cache)
world.log = file("[GLOB.log_directory]/dd.log") //not all runtimes trigger world/Error, so this is the only way to ensure we can see all of them.
#endif
load_admins()
load_mentors()
LoadVerbs(/datum/verbs/menu)
if(CONFIG_GET(flag/usewhitelist))
load_whitelist()
LoadBans()
initialize_global_loadout_items()
reload_custom_roundstart_items_list()//Cit change - loads donator items. Remind me to remove when I port over bay's loadout system
GLOB.timezoneOffset = text2num(time2text(0,"hh")) * 36000
@@ -67,10 +89,15 @@ GLOBAL_LIST(topic_status_cache)
if(NO_INIT_PARAMETER in params)
return
LoadBans()
initialize_global_loadout_items()
reload_custom_roundstart_items_list()//Cit change - loads donator items. Remind me to remove when I port over bay's loadout system
Master.Initialize(10, FALSE, TRUE)
if(TEST_RUN_PARAMETER in params)
HandleTestRun()
#ifdef UNIT_TESTS
HandleTestRun()
#endif
/world/proc/InitTgs()
TgsNew(new /datum/tgs_event_handler/impl, TGS_SECURITY_TRUSTED)
@@ -88,7 +115,7 @@ GLOBAL_LIST(topic_status_cache)
#else
cb = VARSET_CALLBACK(SSticker, force_ending, TRUE)
#endif
SSticker.OnRoundstart(CALLBACK(GLOBAL_PROC, /proc/addtimer, cb, 10 SECONDS))
SSticker.OnRoundstart(CALLBACK(GLOBAL_PROC, /proc/_addtimer, cb, 10 SECONDS))
/world/proc/SetupLogs()
var/override_dir = params[OVERRIDE_LOG_DIRECTORY_PARAMETER]
@@ -136,7 +163,7 @@ GLOBAL_LIST(topic_status_cache)
#ifdef UNIT_TESTS
GLOB.test_log = file("[GLOB.log_directory]/tests.log")
GLOB.test_log = "[GLOB.log_directory]/tests.log"
start_log(GLOB.test_log)
#endif
start_log(GLOB.world_game_log)
@@ -170,14 +197,6 @@ GLOBAL_LIST(topic_status_cache)
/world/Topic(T, addr, master, key)
TGS_TOPIC //redirect to server tools if necessary
if(!SSfail2topic)
return "Server not initialized."
else if(SSfail2topic.IsRateLimited(addr))
return "Rate limited."
if(length(T) > CONFIG_GET(number/topic_max_size))
return "Payload too large!"
var/static/list/topic_handlers = TopicHandlers()
var/list/input = params2list(T)
@@ -243,9 +262,10 @@ GLOBAL_LIST(topic_status_cache)
TgsReboot()
if(TEST_RUN_PARAMETER in params)
FinishTestRun()
return
#ifdef UNIT_TESTS
FinishTestRun()
return
#endif
if(TgsAvailable())
var/do_hard_reboot
@@ -280,11 +300,11 @@ GLOBAL_LIST(topic_status_cache)
var/list/features = list()
/*if(GLOB.master_mode) CIT CHANGE - hides the gamemode from the hub entry, removes some useless info from the hub entry
features += GLOB.master_mode
// if(GLOB.master_mode)
// features += GLOB.master_mode
if (!GLOB.enter_allowed)
features += "closed"*/
// if (!GLOB.enter_allowed)
// features += "closed"
var/s = ""
var/hostedby
@@ -292,25 +312,22 @@ GLOBAL_LIST(topic_status_cache)
var/server_name = CONFIG_GET(string/servername)
if (server_name)
s += "<b>[server_name]</b> &#8212; "
/*features += "[CONFIG_GET(flag/norespawn) ? "no " : ""]respawn" CIT CHANGE - removes some useless info from the hub entry
if(CONFIG_GET(flag/allow_vote_mode))
features += "vote"
if(CONFIG_GET(flag/allow_ai))
features += "AI allowed"*/
// features += "[CONFIG_GET(flag/norespawn) ? "no " : ""]respawn"
// if(CONFIG_GET(flag/allow_vote_mode))
// features += "vote"
// if(CONFIG_GET(flag/allow_ai))
// features += "AI allowed"
hostedby = CONFIG_GET(string/hostedby)
s += "<b>[station_name()]</b>";
s += " ("
s += "<a href=\"https://citadel-station.net/home/\">" //Change this to wherever you want the hub to link to. CIT CHANGE - links to cit's website on the hub
s += "Citadel" //Replace this with something else. Or ever better, delete it and uncomment the game version. CIT CHANGE - modifies the hub entry link
s += "<a href=\"https://citadel-station.net/home\">" //Change this to wherever you want the hub to link to.
s += "Citadel" //Replace this with something else. Or ever better, delete it and uncomment the game version.
s += "</a>"
s += ")\]" //CIT CHANGE - encloses the server title in brackets to make the hub entry fancier
s += "<br>[CONFIG_GET(string/servertagline)]<br>" //CIT CHANGE - adds a tagline!
var/n = 0
for (var/mob/M in GLOB.player_list)
if (M.client)
n++
var/players = GLOB.clients.len
if(SSmapping.config) // this just stops the runtime, honk.
features += "[SSmapping.config.map_name]" //CIT CHANGE - makes the hub entry display the current map
@@ -318,16 +335,23 @@ GLOBAL_LIST(topic_status_cache)
if(NUM2SECLEVEL(GLOB.security_level))//CIT CHANGE - makes the hub entry show the security level
features += "[NUM2SECLEVEL(GLOB.security_level)] alert"
if (n > 1)
features += "~[n] players"
else if (n > 0)
features += "~[n] player"
var/popcaptext = ""
var/popcap = max(CONFIG_GET(number/extreme_popcap), CONFIG_GET(number/hard_popcap), CONFIG_GET(number/soft_popcap))
if (popcap)
popcaptext = "/[popcap]"
if (players > 1)
features += "[players][popcaptext] players"
else if (players > 0)
features += "[players][popcaptext] player"
game_state = (CONFIG_GET(number/extreme_popcap) && players >= CONFIG_GET(number/extreme_popcap)) //tells the hub if we are full
if (!host && hostedby)
features += "hosted by <b>[hostedby]</b>"
if (features)
s += "\[[jointext(features, ", ")]" //CIT CHANGE - replaces the colon here with a left bracket
s += "\[[jointext(features, ", ")]"
status = s
@@ -346,4 +370,28 @@ GLOBAL_LIST(topic_status_cache)
SSidlenpcpool.MaxZChanged()
world.refresh_atmos_grid()
/// Extools atmos
/world/proc/refresh_atmos_grid()
/world/proc/change_fps(new_value = 20)
if(new_value <= 0)
CRASH("change_fps() called with [new_value] new_value.")
if(fps == new_value)
return //No change required.
fps = new_value
on_tickrate_change()
/world/proc/change_tick_lag(new_value = 0.5)
if(new_value <= 0)
CRASH("change_tick_lag() called with [new_value] new_value.")
if(tick_lag == new_value)
return //No change required.
tick_lag = new_value
on_tickrate_change()
/world/proc/on_tickrate_change()
SStimer?.reset_buckets()