Merge branch 'malf-dynamic' into super-special-awesome-dynamic
This commit is contained in:
@@ -4,7 +4,7 @@ SUBSYSTEM_DEF(job)
|
||||
flags = SS_NO_FIRE
|
||||
|
||||
var/list/occupations = list() //List of all jobs
|
||||
var/list/name_occupations = list() //Dict of all jobs, keys are titles
|
||||
var/list/datum/job/name_occupations = list() //Dict of all jobs, keys are titles
|
||||
var/list/type_occupations = list() //Dict of all jobs, keys are types
|
||||
var/list/unassigned = list() //Players who need jobs
|
||||
var/initial_players_to_assign = 0 //used for checking against population caps
|
||||
@@ -14,6 +14,8 @@ SUBSYSTEM_DEF(job)
|
||||
|
||||
var/overflow_role = "Assistant"
|
||||
|
||||
var/list/level_order = list(JP_HIGH,JP_MEDIUM,JP_LOW)
|
||||
|
||||
/datum/controller/subsystem/job/Initialize(timeofday)
|
||||
SSmapping.HACK_LoadMapConfig()
|
||||
if(!occupations.len)
|
||||
@@ -119,7 +121,7 @@ SUBSYSTEM_DEF(job)
|
||||
if(player.mind && job.title in player.mind.restricted_roles)
|
||||
JobDebug("FOC incompatible with antagonist role, Player: [player]")
|
||||
continue
|
||||
if(player.client.prefs.job_preferences["[job.title]"] == level)
|
||||
if(player.client.prefs.job_preferences[job.title] == level)
|
||||
JobDebug("FOC pass, Player: [player], Level:[level]")
|
||||
candidates += player
|
||||
return candidates
|
||||
@@ -181,7 +183,7 @@ SUBSYSTEM_DEF(job)
|
||||
//it locates a head or runs out of levels to check
|
||||
//This is basically to ensure that there's atleast a few heads in the round
|
||||
/datum/controller/subsystem/job/proc/FillHeadPosition()
|
||||
for(var/level = 1 to 3)
|
||||
for(var/level in level_order)
|
||||
for(var/command_position in GLOB.command_positions)
|
||||
var/datum/job/job = GetJob(command_position)
|
||||
if(!job)
|
||||
@@ -218,7 +220,7 @@ SUBSYSTEM_DEF(job)
|
||||
if(!job)
|
||||
return 0
|
||||
for(var/i = job.total_positions, i > 0, i--)
|
||||
for(var/level = 1 to 3)
|
||||
for(var/level in level_order)
|
||||
var/list/candidates = list()
|
||||
candidates = FindOccupationCandidates(job, level)
|
||||
if(candidates.len)
|
||||
@@ -304,8 +306,7 @@ SUBSYSTEM_DEF(job)
|
||||
|
||||
// Loop through all levels from high to low
|
||||
var/list/shuffledoccupations = shuffle(occupations)
|
||||
var/list/levels = list(JP_HIGH,JP_MEDIUM,JP_LOW)
|
||||
for(var/level in levels)
|
||||
for(var/level in level_order)
|
||||
//Check the head jobs first each level
|
||||
CheckHeadPositions(level)
|
||||
|
||||
@@ -334,7 +335,7 @@ SUBSYSTEM_DEF(job)
|
||||
if(job.required_playtime_remaining(player.client))
|
||||
JobDebug("DO player not enough xp, Player: [player], Job:[job.title]")
|
||||
continue
|
||||
|
||||
|
||||
if(!player.client.prefs.pref_species.qualifies_for_rank(job.title, player.client.prefs.features))
|
||||
JobDebug("DO non-human failed, Player: [player], Job:[job.title]")
|
||||
continue
|
||||
@@ -344,7 +345,7 @@ SUBSYSTEM_DEF(job)
|
||||
continue
|
||||
|
||||
// If the player wants that job on this level, then try give it to him.
|
||||
if(player.client.prefs.job_preferences["[job.title]"] == level)
|
||||
if(player.client.prefs.job_preferences[job.title] == level)
|
||||
// If the job isn't filled
|
||||
if((job.current_positions < job.spawn_positions) || job.spawn_positions == -1)
|
||||
JobDebug("DO pass, Player: [player], Level:[level], Job:[job.title]")
|
||||
@@ -475,7 +476,6 @@ SUBSYSTEM_DEF(job)
|
||||
to_chat(M, "<b>[job.custom_spawn_text]</b>")
|
||||
if(CONFIG_GET(number/minimal_access_threshold))
|
||||
to_chat(M, "<span class='notice'><B>As this station was initially staffed with a [CONFIG_GET(flag/jobs_have_minimal_access) ? "full crew, only your job's necessities" : "skeleton crew, additional access may"] have been added to your ID card.</B></span>")
|
||||
|
||||
if(job && H)
|
||||
if(job.dresscodecompliant)// CIT CHANGE - dress code compliance
|
||||
equip_loadout(N, H) // CIT CHANGE - allows players to spawn with loadout items
|
||||
@@ -551,7 +551,7 @@ SUBSYSTEM_DEF(job)
|
||||
if(job.required_playtime_remaining(player.client))
|
||||
young++
|
||||
continue
|
||||
switch(player.client.prefs.job_preferences["[job.title]"])
|
||||
switch(player.client.prefs.job_preferences[job.title])
|
||||
if(JP_HIGH)
|
||||
high++
|
||||
if(JP_MEDIUM)
|
||||
@@ -698,4 +698,4 @@ SUBSYSTEM_DEF(job)
|
||||
. |= player.mind
|
||||
|
||||
/datum/controller/subsystem/job/proc/JobDebug(message)
|
||||
log_job_debug(message)
|
||||
log_job_debug(message)
|
||||
@@ -3,6 +3,7 @@ SUBSYSTEM_DEF(jukeboxes)
|
||||
wait = 5
|
||||
var/list/songs = list()
|
||||
var/list/activejukeboxes = list()
|
||||
var/list/freejukeboxchannels = list()
|
||||
|
||||
/datum/track
|
||||
var/song_name = "generic"
|
||||
@@ -21,23 +22,39 @@ SUBSYSTEM_DEF(jukeboxes)
|
||||
/datum/controller/subsystem/jukeboxes/proc/addjukebox(obj/jukebox, datum/track/T, jukefalloff = 1)
|
||||
if(!istype(T))
|
||||
CRASH("[src] tried to play a song with a nonexistant track")
|
||||
var/channeltoreserve = CHANNEL_JUKEBOX_START + activejukeboxes.len - 1
|
||||
if(channeltoreserve > CHANNEL_JUKEBOX)
|
||||
var/channeltoreserve = pick(freejukeboxchannels)
|
||||
if(!channeltoreserve)
|
||||
return FALSE
|
||||
freejukeboxchannels -= channeltoreserve
|
||||
var/list/youvegotafreejukebox = list(T, channeltoreserve, jukebox, jukefalloff)
|
||||
activejukeboxes.len++
|
||||
activejukeboxes[activejukeboxes.len] = list(T, channeltoreserve, jukebox, jukefalloff)
|
||||
activejukeboxes[activejukeboxes.len] = youvegotafreejukebox
|
||||
|
||||
//Due to changes in later versions of 512, SOUND_UPDATE no longer properly plays audio when a file is defined in the sound datum. As such, we are now required to init the audio before we can actually do anything with it.
|
||||
//Downsides to this? This means that you can *only* hear the jukebox audio if you were present on the server when it started playing, and it means that it's now impossible to add loops to the jukebox track list.
|
||||
var/sound/song_to_init = sound(T.song_path)
|
||||
song_to_init.status = SOUND_MUTE
|
||||
for(var/mob/M in GLOB.player_list)
|
||||
if(!M.client)
|
||||
continue
|
||||
if(!(M.client.prefs.toggles & SOUND_INSTRUMENTS))
|
||||
continue
|
||||
|
||||
M.playsound_local(M, null, 100, channel = youvegotafreejukebox[2], S = song_to_init)
|
||||
return activejukeboxes.len
|
||||
|
||||
/datum/controller/subsystem/jukeboxes/proc/removejukebox(IDtoremove)
|
||||
if(islist(activejukeboxes[IDtoremove]))
|
||||
var/jukechannel = activejukeboxes[IDtoremove][2]
|
||||
for(var/mob/M in GLOB.player_list)
|
||||
if(!M.client)
|
||||
continue
|
||||
M.stop_sound_channel(activejukeboxes[IDtoremove][2])
|
||||
M.stop_sound_channel(jukechannel)
|
||||
freejukeboxchannels |= jukechannel
|
||||
activejukeboxes.Cut(IDtoremove, IDtoremove+1)
|
||||
return TRUE
|
||||
else
|
||||
to_chat(world, "<span class='warning'>If you see this, screenshot it and send it to a dev. Tried to remove jukebox with invalid ID</span>")
|
||||
CRASH("Tried to remove jukebox with invalid ID")
|
||||
|
||||
/datum/controller/subsystem/jukeboxes/proc/findjukeboxindex(obj/jukebox)
|
||||
if(activejukeboxes.len)
|
||||
@@ -57,6 +74,8 @@ SUBSYSTEM_DEF(jukeboxes)
|
||||
T.song_beat = text2num(L[3])
|
||||
T.song_associated_id = L[4]
|
||||
songs |= T
|
||||
for(var/i in CHANNEL_JUKEBOX_START to CHANNEL_JUKEBOX)
|
||||
freejukeboxchannels |= i
|
||||
return ..()
|
||||
|
||||
/datum/controller/subsystem/jukeboxes/fire()
|
||||
@@ -64,14 +83,15 @@ SUBSYSTEM_DEF(jukeboxes)
|
||||
return
|
||||
for(var/list/jukeinfo in activejukeboxes)
|
||||
if(!jukeinfo.len)
|
||||
to_chat(world, "<span class='warning'>If you see this, screenshot it and send it to a dev. Active jukebox without any associated metadata</span>")
|
||||
EXCEPTION("Active jukebox without any associated metadata.")
|
||||
continue
|
||||
var/datum/track/juketrack = jukeinfo[1]
|
||||
if(!istype(juketrack))
|
||||
to_chat(world, "<span class='warning'>If you see this, screenshot it and send it to a dev. After jukebox track grabbing</span>")
|
||||
EXCEPTION("Invalid jukebox track datum.")
|
||||
continue
|
||||
var/obj/jukebox = jukeinfo[3]
|
||||
if(!istype(jukebox))
|
||||
to_chat(world, "<span class='warning'>If you see this, screenshot it and send it to a dev. Nonexistant or invalid jukebox in active jukebox list")
|
||||
EXCEPTION("Nonexistant or invalid object associated with jukebox.")
|
||||
continue
|
||||
var/sound/song_played = sound(juketrack.song_path)
|
||||
var/area/currentarea = get_area(jukebox)
|
||||
|
||||
@@ -54,6 +54,8 @@ SUBSYSTEM_DEF(mapping)
|
||||
if(!config || config.defaulted)
|
||||
to_chat(world, "<span class='boldannounce'>Unable to load next or default map config, defaulting to Box Station</span>")
|
||||
config = old_config
|
||||
GLOB.year_integer += config.year_offset
|
||||
GLOB.announcertype = (config.announcertype == "standard" ? (prob(1) ? "medibot" : "classic") : config.announcertype)
|
||||
loadWorld()
|
||||
repopulate_sorted_areas()
|
||||
process_teleport_locs() //Sets up the wizard teleport locations
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
SUBSYSTEM_DEF(npcpool)
|
||||
name = "NPC Pool"
|
||||
flags = SS_POST_FIRE_TIMING|SS_NO_INIT|SS_BACKGROUND
|
||||
flags = SS_KEEP_TIMING | SS_NO_INIT
|
||||
priority = FIRE_PRIORITY_NPC
|
||||
runlevels = RUNLEVEL_GAME | RUNLEVEL_POSTGAME
|
||||
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
#define FILE_ANTAG_REP "data/AntagReputation.json"
|
||||
#define MAX_RECENT_MAP_RECORD 10
|
||||
|
||||
SUBSYSTEM_DEF(persistence)
|
||||
name = "Persistence"
|
||||
@@ -11,6 +12,7 @@ SUBSYSTEM_DEF(persistence)
|
||||
var/list/obj/structure/chisel_message/chisel_messages = list()
|
||||
var/list/saved_messages = list()
|
||||
var/list/saved_modes = list(1,2,3)
|
||||
var/list/saved_maps
|
||||
var/list/saved_trophies = list()
|
||||
var/list/spawned_objects = list()
|
||||
var/list/antag_rep = list()
|
||||
@@ -25,6 +27,7 @@ SUBSYSTEM_DEF(persistence)
|
||||
LoadChiselMessages()
|
||||
LoadTrophies()
|
||||
LoadRecentModes()
|
||||
LoadRecentMaps()
|
||||
LoadPhotoPersistence()
|
||||
if(CONFIG_GET(flag/use_antag_rep))
|
||||
LoadAntagReputation()
|
||||
@@ -163,6 +166,15 @@ SUBSYSTEM_DEF(persistence)
|
||||
return
|
||||
saved_modes = json["data"]
|
||||
|
||||
/datum/controller/subsystem/persistence/proc/LoadRecentMaps()
|
||||
var/json_file = file("data/RecentMaps.json")
|
||||
if(!fexists(json_file))
|
||||
return
|
||||
var/list/json = json_decode(file2text(json_file))
|
||||
if(!json)
|
||||
return
|
||||
saved_maps = json["maps"]
|
||||
|
||||
/datum/controller/subsystem/persistence/proc/LoadAntagReputation()
|
||||
var/json = file2text(FILE_ANTAG_REP)
|
||||
if(!json)
|
||||
@@ -204,6 +216,7 @@ SUBSYSTEM_DEF(persistence)
|
||||
CollectSecretSatchels()
|
||||
CollectTrophies()
|
||||
CollectRoundtype()
|
||||
RecordMaps()
|
||||
SavePhotoPersistence() //THIS IS PERSISTENCE, NOT THE LOGGING PORTION.
|
||||
if(CONFIG_GET(flag/use_antag_rep))
|
||||
CollectAntagReputation()
|
||||
@@ -359,6 +372,15 @@ SUBSYSTEM_DEF(persistence)
|
||||
fdel(json_file)
|
||||
WRITE_FILE(json_file, json_encode(file_data))
|
||||
|
||||
/datum/controller/subsystem/persistence/proc/RecordMaps()
|
||||
saved_maps = saved_maps?.len ? list("[SSmapping.config.map_name]") | saved_maps : list("[SSmapping.config.map_name]")
|
||||
var/json_file = file("data/RecentMaps.json")
|
||||
var/list/file_data = list()
|
||||
file_data["maps"] = saved_maps
|
||||
fdel(json_file)
|
||||
WRITE_FILE(json_file, json_encode(file_data))
|
||||
|
||||
|
||||
/datum/controller/subsystem/persistence/proc/CollectAntagReputation()
|
||||
var/ANTAG_REP_MAXIMUM = CONFIG_GET(number/antag_rep_maximum)
|
||||
|
||||
|
||||
@@ -373,7 +373,7 @@ SUBSYSTEM_DEF(shuttle)
|
||||
emergency.setTimer(emergencyDockTime)
|
||||
priority_announce("Hostile environment resolved. \
|
||||
You have 3 minutes to board the Emergency Shuttle.",
|
||||
null, 'sound/ai/shuttledock.ogg', "Priority")
|
||||
null, "shuttledock", "Priority")
|
||||
|
||||
//try to move/request to dockHome if possible, otherwise dockAway. Mainly used for admin buttons
|
||||
/datum/controller/subsystem/shuttle/proc/toggleShuttle(shuttleId, dockHome, dockAway, timed)
|
||||
|
||||
@@ -43,6 +43,7 @@ SUBSYSTEM_DEF(throwing)
|
||||
var/atom/movable/thrownthing
|
||||
var/atom/target
|
||||
var/turf/target_turf
|
||||
var/target_zone
|
||||
var/init_dir
|
||||
var/maxrange
|
||||
var/speed
|
||||
|
||||
@@ -303,7 +303,7 @@ SUBSYSTEM_DEF(ticker)
|
||||
SSdbcore.SetRoundStart()
|
||||
|
||||
to_chat(world, "<span class='notice'><B>Welcome to [station_name()], enjoy your stay!</B></span>")
|
||||
SEND_SOUND(world, sound('sound/ai/welcome.ogg'))
|
||||
SEND_SOUND(world, sound(get_announcer_sound("welcome")))
|
||||
|
||||
current_state = GAME_STATE_PLAYING
|
||||
Master.SetRunLevel(RUNLEVEL_GAME)
|
||||
|
||||
@@ -223,9 +223,19 @@ SUBSYSTEM_DEF(vote)
|
||||
if("gamemode")
|
||||
choices.Add(config.votable_modes)
|
||||
if("map")
|
||||
choices.Add(config.maplist)
|
||||
for(var/i in choices)//this is necessary because otherwise we'll end up with a bunch of /datum/map_config's as the default vote value instead of 0 as intended
|
||||
choices[i] = 0
|
||||
var/players = GLOB.clients.len
|
||||
var/list/lastmaps = SSpersistence.saved_maps?.len ? list("[SSmapping.config.map_name]") | SSpersistence.saved_maps : list("[SSmapping.config.map_name]")
|
||||
for(var/M in config.maplist) //This is a typeless loop due to the finnicky nature of keyed lists in this kind of context
|
||||
var/datum/map_config/targetmap = config.maplist[M]
|
||||
if(!istype(targetmap))
|
||||
continue
|
||||
if(!targetmap.voteweight)
|
||||
continue
|
||||
if((targetmap.config_min_users && players < targetmap.config_min_users) || (targetmap.config_max_users && players > targetmap.config_max_users))
|
||||
continue
|
||||
if(targetmap.max_round_search_span && count_occurences_of_value(lastmaps, M, targetmap.max_round_search_span) >= targetmap.max_rounds_played)
|
||||
continue
|
||||
choices |= M
|
||||
if("roundtype") //CIT CHANGE - adds the roundstart secret/extended vote
|
||||
choices.Add("secret", "extended")
|
||||
if("dynamic")
|
||||
|
||||
Reference in New Issue
Block a user