Merge branch 'master' into mirror-38933

This commit is contained in:
kevinz000
2018-07-14 15:26:49 -07:00
committed by GitHub
1555 changed files with 162517 additions and 36374 deletions
+1 -1
View File
@@ -263,7 +263,7 @@ SUBSYSTEM_DEF(air)
currentrun |= T
if(blockchanges && T.excited_group)
T.excited_group.garbage_collect()
else if(T.initialized)
else if(T.flags_1 & INITIALIZED_1)
for(var/turf/S in T.atmos_adjacent_turfs)
add_to_active(S)
else if(map_loading)
+3 -3
View File
@@ -37,14 +37,14 @@ SUBSYSTEM_DEF(atoms)
count = atoms.len
for(var/I in atoms)
var/atom/A = I
if(!A.initialized)
if(!(A.flags_1 & INITIALIZED_1))
if(InitAtom(I, mapload_arg))
atoms -= I
CHECK_TICK
else
count = 0
for(var/atom/A in world)
if(!A.initialized)
if(!(A.flags_1 & INITIALIZED_1))
InitAtom(A, mapload_arg)
++count
CHECK_TICK
@@ -95,7 +95,7 @@ SUBSYSTEM_DEF(atoms)
if(!A) //possible harddel
qdeleted = TRUE
else if(!A.initialized)
else if(!(A.flags_1 & INITIALIZED_1))
BadInitializeCalls[the_type] |= BAD_INIT_DIDNT_INIT
return qdeleted || QDELING(A)
+62 -31
View File
@@ -20,10 +20,22 @@ SUBSYSTEM_DEF(blackbox)
record_feedback("amount", "random_seed", Master.random_seed)
record_feedback("amount", "dm_version", DM_VERSION)
record_feedback("amount", "byond_version", world.byond_version)
record_feedback("amount", "byond_build", world.byond_build)
. = ..()
//poll population
/datum/controller/subsystem/blackbox/fire()
set waitfor = FALSE //for population query
CheckPlayerCount()
if(CONFIG_GET(flag/use_exp_tracking))
if((triggertime < 0) || (world.time > (triggertime +3000))) //subsystem fires once at roundstart then once every 10 minutes. a 5 min check skips the first fire. The <0 is midnight rollover check
update_exp(10,FALSE)
/datum/controller/subsystem/blackbox/proc/CheckPlayerCount()
set waitfor = FALSE
if(!SSdbcore.Connect())
return
var/playercount = 0
@@ -33,11 +45,7 @@ SUBSYSTEM_DEF(blackbox)
var/admincount = GLOB.admins.len
var/datum/DBQuery/query_record_playercount = SSdbcore.NewQuery("INSERT INTO [format_table_name("legacy_population")] (playercount, admincount, time, server_ip, server_port, round_id) VALUES ([playercount], [admincount], '[SQLtime()]', INET_ATON(IF('[world.internet_address]' LIKE '', '0', '[world.internet_address]')), '[world.port]', '[GLOB.round_id]')")
query_record_playercount.Execute()
if(CONFIG_GET(flag/use_exp_tracking))
if((triggertime < 0) || (world.time > (triggertime +3000))) //subsystem fires once at roundstart then once every 10 minutes. a 5 min check skips the first fire. The <0 is midnight rollover check
update_exp(10,FALSE)
qdel(query_record_playercount)
/datum/controller/subsystem/blackbox/Recover()
feedback = SSblackbox.feedback
@@ -144,7 +152,7 @@ feedback data can be recorded in 5 formats:
SSblackbox.record_feedback("text", "example", 1, "other text")
json: {"data":["sample text","other text"]}
"amount"
used to record simple counts of data i.e. the number of ahelps recieved
used to record simple counts of data i.e. the number of ahelps received
further calls to the same key will add or subtract (if increment argument is a negative) from the saved amount
calls: SSblackbox.record_feedback("amount", "example", 8)
SSblackbox.record_feedback("amount", "example", 2)
@@ -255,40 +263,63 @@ Versioning
key_type = new_key_type
/datum/controller/subsystem/blackbox/proc/ReportDeath(mob/living/L)
set waitfor = FALSE
if(sealed)
return
if(!SSdbcore.Connect())
return
if(!L || !L.key || !L.mind)
return
var/area/placeofdeath = get_area(L)
var/sqlname = sanitizeSQL(L.real_name)
var/sqlkey = sanitizeSQL(L.ckey)
var/sqljob = sanitizeSQL(L.mind.assigned_role)
var/sqlspecial = sanitizeSQL(L.mind.special_role)
var/sqlpod = sanitizeSQL(placeofdeath.name)
var/laname = sanitizeSQL(L.lastattacker)
var/lakey = sanitizeSQL(L.lastattackerckey)
var/sqlbrute = sanitizeSQL(L.getBruteLoss())
var/sqlfire = sanitizeSQL(L.getFireLoss())
var/sqlbrain = sanitizeSQL(L.getBrainLoss())
var/sqloxy = sanitizeSQL(L.getOxyLoss())
var/sqltox = sanitizeSQL(L.getToxLoss())
var/sqlclone = sanitizeSQL(L.getCloneLoss())
var/sqlstamina = sanitizeSQL(L.getStaminaLoss())
var/x_coord = sanitizeSQL(L.x)
var/y_coord = sanitizeSQL(L.y)
var/z_coord = sanitizeSQL(L.z)
var/last_words = sanitizeSQL(L.last_words)
var/suicide = sanitizeSQL(L.suiciding)
var/map = sanitizeSQL(SSmapping.config.map_name)
if(!L.suiciding && !first_death.len)
first_death["name"] = "[(L.real_name == L.name) ? L.real_name : "[L.real_name] as [L.name]"]"
first_death["role"] = null
if(L.mind.assigned_role)
first_death["role"] = L.mind.assigned_role
first_death["area"] = "[get_area_name(L, TRUE)] [COORD(L)]"
first_death["damage"] = "<font color='#FF5555'>[sqlbrute]</font>/<font color='orange'>[sqlfire]</font>/<font color='lightgreen'>[sqltox]</font>/<font color='lightblue'>[sqloxy]</font>/<font color='pink'>[sqlclone]</font>"
first_death["area"] = "[AREACOORD(L)]"
first_death["damage"] = "<font color='#FF5555'>[L.getBruteLoss()]</font>/<font color='orange'>[L.getFireLoss()]</font>/<font color='lightgreen'>[L.getToxLoss()]</font>/<font color='lightblue'>[L.getOxyLoss()]</font>/<font color='pink'>[L.getCloneLoss()]</font>"
first_death["last_words"] = L.last_words
var/sqlname = L.real_name
var/sqlkey = L.ckey
var/sqljob = L.mind.assigned_role
var/sqlspecial = L.mind.special_role
var/sqlpod = get_area_name(L, TRUE)
var/laname = L.lastattacker
var/lakey = L.lastattackerckey
var/sqlbrute = L.getBruteLoss()
var/sqlfire = L.getFireLoss()
var/sqlbrain = L.getBrainLoss()
var/sqloxy = L.getOxyLoss()
var/sqltox = L.getToxLoss()
var/sqlclone = L.getCloneLoss()
var/sqlstamina = L.getStaminaLoss()
var/x_coord = L.x
var/y_coord = L.y
var/z_coord = L.z
var/last_words = L.last_words
var/suicide = L.suiciding
var/map = SSmapping.config.map_name
if(!SSdbcore.Connect())
return
sqlname = sanitizeSQL(sqlname)
sqlkey = sanitizeSQL(sqlkey)
sqljob = sanitizeSQL(sqljob)
sqlspecial = sanitizeSQL(sqlspecial)
sqlpod = sanitizeSQL(sqlpod)
laname = sanitizeSQL(laname)
lakey = sanitizeSQL(lakey)
sqlbrute = sanitizeSQL(sqlbrute)
sqlfire = sanitizeSQL(sqlfire)
sqlbrain = sanitizeSQL(sqlbrain)
sqloxy = sanitizeSQL(sqloxy)
sqltox = sanitizeSQL(sqltox)
sqlclone = sanitizeSQL(sqlclone)
sqlstamina = sanitizeSQL(sqlstamina)
x_coord = sanitizeSQL(x_coord)
y_coord = sanitizeSQL(y_coord)
z_coord = sanitizeSQL(z_coord)
last_words = sanitizeSQL(last_words)
suicide = sanitizeSQL(suicide)
map = sanitizeSQL(map)
var/datum/DBQuery/query_report_death = SSdbcore.NewQuery("INSERT INTO [format_table_name("death")] (pod, x_coord, y_coord, z_coord, mapname, server_ip, server_port, round_id, tod, job, special, name, byondkey, laname, lakey, bruteloss, fireloss, brainloss, oxyloss, toxloss, cloneloss, staminaloss, last_words, suicide) VALUES ('[sqlpod]', '[x_coord]', '[y_coord]', '[z_coord]', '[map]', INET_ATON(IF('[world.internet_address]' LIKE '', '0', '[world.internet_address]')), '[world.port]', [GLOB.round_id], '[SQLtime()]', '[sqljob]', '[sqlspecial]', '[sqlname]', '[sqlkey]', '[laname]', '[lakey]', [sqlbrute], [sqlfire], [sqlbrain], [sqloxy], [sqltox], [sqlclone], [sqlstamina], '[last_words]', [suicide])")
query_report_death.Execute()
qdel(query_report_death)
+1 -1
View File
@@ -26,7 +26,7 @@ SUBSYSTEM_DEF(communications)
priority_announce(html_decode(user.treat_message(input)), null, 'sound/misc/announce.ogg', "Captain")
nonsilicon_message_cooldown = world.time + COMMUNICATION_COOLDOWN
log_talk(user,"[key_name(user)] has made a priority announcement: [input]",LOGSAY)
message_admins("[key_name_admin(user)] has made a priority announcement.")
message_admins("[ADMIN_LOOKUPFLW(user)] has made a priority announcement.")
/datum/controller/subsystem/communications/proc/send_message(datum/comm_message/sending,print = TRUE,unique = FALSE)
for(var/obj/machinery/computer/communications/C in GLOB.machines)
+64 -22
View File
@@ -1,6 +1,7 @@
SUBSYSTEM_DEF(dbcore)
name = "Database"
flags = SS_NO_FIRE
flags = SS_BACKGROUND
wait = 1 MINUTES
init_order = INIT_ORDER_DBCORE
var/const/FAILED_DB_CONNECTION_CUTOFF = 5
@@ -25,6 +26,8 @@ SUBSYSTEM_DEF(dbcore)
var/_db_con// This variable contains a reference to the actual database connection.
var/failed_connections = 0
var/list/active_queries = list()
/datum/controller/subsystem/dbcore/PreInit()
if(!_db_con)
_db_con = _dm_db_new_con()
@@ -40,6 +43,15 @@ SUBSYSTEM_DEF(dbcore)
return ..()
/datum/controller/subsystem/dbcore/fire()
for(var/I in active_queries)
var/datum/DBQuery/Q = I
if(world.time - Q.last_activity_time > (5 MINUTES))
message_admins("Found undeleted query, please check the server logs and notify coders.")
log_sql("Undeleted query: \"[Q.sql]\" LA: [Q.last_activity] LAT: [Q.last_activity_time]")
qdel(Q)
if(MC_TICK_CHECK)
return
/datum/controller/subsystem/dbcore/Recover()
_db_con = SSdbcore._db_con
@@ -49,12 +61,13 @@ SUBSYSTEM_DEF(dbcore)
if(SSdbcore.Connect())
var/datum/DBQuery/query_round_shutdown = SSdbcore.NewQuery("UPDATE [format_table_name("round")] SET shutdown_datetime = Now(), end_state = '[sanitizeSQL(SSticker.end_state)]' WHERE id = [GLOB.round_id]")
query_round_shutdown.Execute()
qdel(query_round_shutdown)
if(IsConnected())
Disconnect()
//nu
/datum/controller/subsystem/dbcore/can_vv_get(var_name)
return var_name != "_db_con" && ..()
return var_name != NAMEOF(src, _db_con) && var_name != NAMEOF(src, active_queries) && ..()
/datum/controller/subsystem/dbcore/vv_edit_var(var_name, var_value)
if(var_name == "_db_con")
@@ -98,33 +111,38 @@ SUBSYSTEM_DEF(dbcore)
else
schema_mismatch = 2 //flag admin message about no schema version
log_sql("Could not get schema version from database")
qdel(query_db_version)
else
log_sql("Your server failed to establish a connection with the database.")
else
log_sql("Database is not enabled in configuration.")
/datum/controller/subsystem/dbcore/proc/SetRoundID()
if(CONFIG_GET(flag/sql_enabled))
if(SSdbcore.Connect())
var/datum/DBQuery/query_round_initialize = SSdbcore.NewQuery("INSERT INTO [format_table_name("round")] (initialize_datetime, server_ip, server_port) VALUES (Now(), INET_ATON(IF('[world.internet_address]' LIKE '', '0', '[world.internet_address]')), '[world.port]')")
query_round_initialize.Execute()
var/datum/DBQuery/query_round_last_id = SSdbcore.NewQuery("SELECT LAST_INSERT_ID()")
query_round_last_id.Execute()
if(query_round_last_id.NextRow())
GLOB.round_id = query_round_last_id.item[1]
if(!Connect())
return
var/datum/DBQuery/query_round_initialize = SSdbcore.NewQuery("INSERT INTO [format_table_name("round")] (initialize_datetime, server_ip, server_port) VALUES (Now(), INET_ATON(IF('[world.internet_address]' LIKE '', '0', '[world.internet_address]')), '[world.port]')")
query_round_initialize.Execute()
qdel(query_round_initialize)
var/datum/DBQuery/query_round_last_id = SSdbcore.NewQuery("SELECT LAST_INSERT_ID()")
query_round_last_id.Execute()
if(query_round_last_id.NextRow())
GLOB.round_id = query_round_last_id.item[1]
qdel(query_round_last_id)
/datum/controller/subsystem/dbcore/proc/SetRoundStart()
if(CONFIG_GET(flag/sql_enabled))
if(SSdbcore.Connect())
var/datum/DBQuery/query_round_start = SSdbcore.NewQuery("UPDATE [format_table_name("round")] SET start_datetime = Now() WHERE id = [GLOB.round_id]")
query_round_start.Execute()
if(!Connect())
return
var/datum/DBQuery/query_round_start = SSdbcore.NewQuery("UPDATE [format_table_name("round")] SET start_datetime = Now() WHERE id = [GLOB.round_id]")
query_round_start.Execute()
qdel(query_round_start)
/datum/controller/subsystem/dbcore/proc/SetRoundEnd()
if(CONFIG_GET(flag/sql_enabled))
if(SSdbcore.Connect())
var/sql_station_name = sanitizeSQL(station_name())
var/datum/DBQuery/query_round_end = SSdbcore.NewQuery("UPDATE [format_table_name("round")] SET end_datetime = Now(), game_mode_result = '[sanitizeSQL(SSticker.mode_result)]', station_name = '[sql_station_name]' WHERE id = [GLOB.round_id]")
query_round_end.Execute()
if(!Connect())
return
var/sql_station_name = sanitizeSQL(station_name())
var/datum/DBQuery/query_round_end = SSdbcore.NewQuery("UPDATE [format_table_name("round")] SET end_datetime = Now(), game_mode_result = '[sanitizeSQL(SSticker.mode_result)]', station_name = '[sql_station_name]' WHERE id = [GLOB.round_id]")
query_round_end.Execute()
qdel(query_round_end)
/datum/controller/subsystem/dbcore/proc/Disconnect()
failed_connections = 0
@@ -212,9 +230,10 @@ Delayed insert mode was removed in mysql 7 and only works with MyISAM type table
sqlrowlist = " [sqlrowlist.Join(",\n ")]"
var/datum/DBQuery/Query = NewQuery("INSERT[delayed][ignore_errors] INTO [table]\n([columns.Join(", ")])\nVALUES\n[sqlrowlist]\n[duplicate_key]")
if (warn)
return Query.warn_execute()
. = Query.warn_execute()
else
return Query.Execute()
. = Query.Execute()
qdel(Query)
/datum/DBQuery
@@ -223,11 +242,14 @@ Delayed insert mode was removed in mysql 7 and only works with MyISAM type table
var/list/columns //list of DB Columns populated by Columns()
var/list/conversions
var/list/item //list of data values populated by NextRow()
var/last_activity
var/last_activity_time
var/datum/controller/subsystem/dbcore/db_connection
var/_db_query
/datum/DBQuery/New(sql_query, datum/controller/subsystem/dbcore/connection_handler, cursor_handler)
SSdbcore.active_queries[src] = TRUE
Activity("Created")
if(sql_query)
sql = sql_query
if(connection_handler)
@@ -237,12 +259,31 @@ Delayed insert mode was removed in mysql 7 and only works with MyISAM type table
item = list()
_db_query = _dm_db_new_query()
/datum/DBQuery/Destroy()
Close()
SSdbcore.active_queries -= src
return ..()
/datum/DBQuery/CanProcCall(proc_name)
//fuck off kevinz
return FALSE
/datum/DBQuery/proc/Activity(activity)
last_activity = activity
last_activity_time = world.time
/datum/DBQuery/proc/warn_execute()
. = Execute()
if(!.)
to_chat(usr, "<span class='danger'>A SQL error occurred during this operation, check the server logs.</span>")
/datum/DBQuery/proc/SetQuery(new_sql)
Activity("SetQuery")
Close()
sql = new_sql
/datum/DBQuery/proc/Execute(sql_query = sql, cursor_handler = default_cursor, log_error = TRUE)
Activity("Execute")
var/start_time
var/timeout = CONFIG_GET(number/query_debug_log_timeout)
if(timeout)
@@ -263,6 +304,7 @@ Delayed insert mode was removed in mysql 7 and only works with MyISAM type table
message_admins("HEY! A database query may have timed out. Did the server just hang? <a href='?_src_=holder;[HrefToken()];slowquery=yes'>\[YES\]</a>|<a href='?_src_=holder;[HrefToken()];slowquery=no'>\[NO\]</a>")
/datum/DBQuery/proc/NextRow()
Activity("NextRow")
return _dm_db_next_row(_db_query,item,conversions)
/datum/DBQuery/proc/RowsAffected()
+6
View File
@@ -0,0 +1,6 @@
SUBSYSTEM_DEF(dcs)
name = "Datum Component System"
flags = SS_NO_INIT | SS_NO_FIRE
/datum/controller/subsystem/dcs/Recover()
comp_lookup = SSdcs.comp_lookup
-19
View File
@@ -93,25 +93,6 @@ SUBSYSTEM_DEF(events)
else if(. == EVENT_READY)
E.runEvent(TRUE)
/datum/round_event/proc/findEventArea() //Here's a nice proc to use to find an area for your event to land in!
var/list/safe_areas = list(
/area/ai_monitored/turret_protected/ai,
/area/ai_monitored/turret_protected/ai_upload,
/area/engine,
/area/solar,
/area/holodeck,
/area/shuttle
)
//These are needed because /area/engine has to be removed from the list, but we still want these areas to get fucked up.
var/list/danger_areas = list(
/area/engine/break_room,
/area/crew_quarters/heads/chief)
//Need to locate() as it's just a list of paths.
return locate(pick((GLOB.the_station_areas - safe_areas) + danger_areas)) in GLOB.sortedAreas
//allows a client to trigger an event
//aka Badmin Central
// > Not in modules/admin
+2 -2
View File
@@ -293,13 +293,13 @@ SUBSYSTEM_DEF(garbage)
if(isnull(D.gc_destroyed))
if (D.SendSignal(COMSIG_PARENT_PREQDELETED, force)) // Give the components a chance to prevent their parent from being deleted
if (SEND_SIGNAL(D, COMSIG_PARENT_PREQDELETED, force)) // Give the components a chance to prevent their parent from being deleted
return
D.gc_destroyed = GC_CURRENTLY_BEING_QDELETED
var/start_time = world.time
var/start_tick = world.tick_usage
var/hint = D.Destroy(arglist(args.Copy(2))) // Let our friend know they're about to get fucked up.
D.SendSignal(COMSIG_PARENT_QDELETED, force, hint) // Let the (remaining) components know about the result of Destroy
SEND_SIGNAL(D, COMSIG_PARENT_QDELETED, force, hint) // Let the (remaining) components know about the result of Destroy
if(world.time != start_time)
I.slept_destroy++
else
+16 -6
View File
@@ -6,16 +6,26 @@ SUBSYSTEM_DEF(icon_smooth)
flags = SS_TICKER
var/list/smooth_queue = list()
var/list/deferred = list()
/datum/controller/subsystem/icon_smooth/fire()
while(smooth_queue.len)
var/atom/A = smooth_queue[smooth_queue.len]
smooth_queue.len--
smooth_icon(A)
var/list/cached = smooth_queue
while(cached.len)
var/atom/A = cached[cached.len]
cached.len--
if (A.flags_1 & INITIALIZED_1)
smooth_icon(A)
else
deferred += A
if (MC_TICK_CHECK)
return
if (!smooth_queue.len)
can_fire = 0
if (!cached.len)
if (deferred.len)
smooth_queue = deferred
deferred = cached
else
can_fire = 0
/datum/controller/subsystem/icon_smooth/Initialize()
smooth_zlevel(1,TRUE)
+80 -75
View File
@@ -7,7 +7,6 @@ SUBSYSTEM_DEF(job)
var/list/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/list/job_debug = list() //Debug info
var/initial_players_to_assign = 0 //used for checking against population caps
var/list/prioritized_jobs = list()
@@ -36,6 +35,7 @@ SUBSYSTEM_DEF(job)
old_overflow.spawn_positions = initial(old_overflow.spawn_positions)
old_overflow.total_positions = initial(old_overflow.total_positions)
overflow_role = new_overflow_role
JobDebug("Overflow role set to : [new_overflow_role]")
/datum/controller/subsystem/job/proc/SetupOccupations(faction = "Station")
occupations = list()
@@ -62,13 +62,6 @@ SUBSYSTEM_DEF(job)
return 1
/datum/controller/subsystem/job/proc/Debug(text)
if(!GLOB.Debug2)
return 0
job_debug.Add(text)
return 1
/datum/controller/subsystem/job/proc/GetJob(rank)
if(!occupations.len)
SetupOccupations()
@@ -80,12 +73,12 @@ SUBSYSTEM_DEF(job)
return type_occupations[jobtype]
/datum/controller/subsystem/job/proc/AssignRole(mob/dead/new_player/player, rank, latejoin = FALSE)
Debug("Running AR, Player: [player], Rank: [rank], LJ: [latejoin]")
JobDebug("Running AR, Player: [player], Rank: [rank], LJ: [latejoin]")
if(player && player.mind && rank)
var/datum/job/job = GetJob(rank)
if(!job)
return FALSE
if(jobban_isbanned(player, rank))
if(jobban_isbanned(player, rank) || QDELETED(player))
return FALSE
if(!job.player_old_enough(player.client))
return FALSE
@@ -94,41 +87,41 @@ SUBSYSTEM_DEF(job)
var/position_limit = job.total_positions
if(!latejoin)
position_limit = job.spawn_positions
Debug("Player: [player] is now Rank: [rank], JCP:[job.current_positions], JPL:[position_limit]")
JobDebug("Player: [player] is now Rank: [rank], JCP:[job.current_positions], JPL:[position_limit]")
player.mind.assigned_role = rank
unassigned -= player
job.current_positions++
return TRUE
Debug("AR has failed, Player: [player], Rank: [rank]")
JobDebug("AR has failed, Player: [player], Rank: [rank]")
return FALSE
/datum/controller/subsystem/job/proc/FindOccupationCandidates(datum/job/job, level, flag)
Debug("Running FOC, Job: [job], Level: [level], Flag: [flag]")
JobDebug("Running FOC, Job: [job], Level: [level], Flag: [flag]")
var/list/candidates = list()
for(var/mob/dead/new_player/player in unassigned)
if(jobban_isbanned(player, job.title))
Debug("FOC isbanned failed, Player: [player]")
if(jobban_isbanned(player, job.title) || QDELETED(player))
JobDebug("FOC isbanned failed, Player: [player]")
continue
if(!job.player_old_enough(player.client))
Debug("FOC player not old enough, Player: [player]")
JobDebug("FOC player not old enough, Player: [player]")
continue
if(job.required_playtime_remaining(player.client))
Debug("FOC player not enough xp, Player: [player]")
JobDebug("FOC player not enough xp, Player: [player]")
continue
if(flag && (!(flag in player.client.prefs.be_special)))
Debug("FOC flag failed, Player: [player], Flag: [flag], ")
JobDebug("FOC flag failed, Player: [player], Flag: [flag], ")
continue
if(player.mind && job.title in player.mind.restricted_roles)
Debug("FOC incompatible with antagonist role, Player: [player]")
JobDebug("FOC incompatible with antagonist role, Player: [player]")
continue
if(player.client.prefs.GetJobDepartment(job, level) & job.flag)
Debug("FOC pass, Player: [player], Level:[level]")
JobDebug("FOC pass, Player: [player], Level:[level]")
candidates += player
return candidates
/datum/controller/subsystem/job/proc/GiveRandomJob(mob/dead/new_player/player)
Debug("GRJ Giving random job, Player: [player]")
JobDebug("GRJ Giving random job, Player: [player]")
. = FALSE
for(var/datum/job/job in shuffle(occupations))
if(!job)
@@ -140,32 +133,37 @@ SUBSYSTEM_DEF(job)
if(job.title in GLOB.command_positions) //If you want a command position, select it!
continue
if(jobban_isbanned(player, job.title))
Debug("GRJ isbanned failed, Player: [player], Job: [job.title]")
if(jobban_isbanned(player, job.title) || QDELETED(player))
if(QDELETED(player))
JobDebug("GRJ isbanned failed, Player deleted")
break
JobDebug("GRJ isbanned failed, Player: [player], Job: [job.title]")
continue
if(!job.player_old_enough(player.client))
Debug("GRJ player not old enough, Player: [player]")
JobDebug("GRJ player not old enough, Player: [player]")
continue
if(job.required_playtime_remaining(player.client))
Debug("GRJ player not enough xp, Player: [player]")
JobDebug("GRJ player not enough xp, Player: [player]")
continue
if(player.mind && job.title in player.mind.restricted_roles)
Debug("GRJ incompatible with antagonist role, Player: [player], Job: [job.title]")
JobDebug("GRJ incompatible with antagonist role, Player: [player], Job: [job.title]")
continue
if((job.current_positions < job.spawn_positions) || job.spawn_positions == -1)
Debug("GRJ Random job given, Player: [player], Job: [job]")
JobDebug("GRJ Random job given, Player: [player], Job: [job]")
if(AssignRole(player, job.title))
return TRUE
/datum/controller/subsystem/job/proc/ResetOccupations()
JobDebug("Occupations reset.")
for(var/mob/dead/new_player/player in GLOB.player_list)
if((player) && (player.mind))
player.mind.assigned_role = null
player.mind.special_role = null
SSpersistence.antag_rep_change[player.ckey] = 0
SetupOccupations()
unassigned = list()
return
@@ -231,7 +229,7 @@ SUBSYSTEM_DEF(job)
**/
/datum/controller/subsystem/job/proc/DivideOccupations()
//Setup new player list and get the jobs list
Debug("Running DO")
JobDebug("Running DO")
//Holder for Triumvirate is stored in the SSticker, this just processes it
if(SSticker.triai)
@@ -247,7 +245,7 @@ SUBSYSTEM_DEF(job)
initial_players_to_assign = unassigned.len
Debug("DO, Len: [unassigned.len]")
JobDebug("DO, Len: [unassigned.len]")
if(unassigned.len == 0)
return 0
@@ -268,28 +266,28 @@ SUBSYSTEM_DEF(job)
HandleFeedbackGathering()
//People who wants to be the overflow role, sure, go on.
Debug("DO, Running Overflow Check 1")
JobDebug("DO, Running Overflow Check 1")
var/datum/job/overflow = GetJob(SSjob.overflow_role)
var/list/overflow_candidates = FindOccupationCandidates(overflow, 3)
Debug("AC1, Candidates: [overflow_candidates.len]")
JobDebug("AC1, Candidates: [overflow_candidates.len]")
for(var/mob/dead/new_player/player in overflow_candidates)
Debug("AC1 pass, Player: [player]")
JobDebug("AC1 pass, Player: [player]")
AssignRole(player, SSjob.overflow_role)
overflow_candidates -= player
Debug("DO, AC1 end")
JobDebug("DO, AC1 end")
//Select one head
Debug("DO, Running Head Check")
JobDebug("DO, Running Head Check")
FillHeadPosition()
Debug("DO, Head Check end")
JobDebug("DO, Head Check end")
//Check for an AI
Debug("DO, Running AI Check")
JobDebug("DO, Running AI Check")
FillAIPosition()
Debug("DO, AI Check end")
JobDebug("DO, AI Check end")
//Other jobs are now checked
Debug("DO, Running Standard Check")
JobDebug("DO, Running Standard Check")
// New job giving system by Donkie
@@ -313,66 +311,71 @@ SUBSYSTEM_DEF(job)
continue
if(jobban_isbanned(player, job.title))
Debug("DO isbanned failed, Player: [player], Job:[job.title]")
JobDebug("DO isbanned failed, Player: [player], Job:[job.title]")
continue
if(QDELETED(player))
JobDebug("DO player deleted during job ban check")
break
if(!job.player_old_enough(player.client))
Debug("DO player not old enough, Player: [player], Job:[job.title]")
JobDebug("DO player not old enough, Player: [player], Job:[job.title]")
continue
if(job.required_playtime_remaining(player.client))
Debug("DO player not enough xp, Player: [player], Job:[job.title]")
JobDebug("DO player not enough xp, Player: [player], Job:[job.title]")
continue
if(player.mind && job.title in player.mind.restricted_roles)
Debug("DO incompatible with antagonist role, Player: [player], Job:[job.title]")
JobDebug("DO incompatible with antagonist role, Player: [player], Job:[job.title]")
continue
// If the player wants that job on this level, then try give it to him.
if(player.client.prefs.GetJobDepartment(job, level) & job.flag)
// If the job isn't filled
if((job.current_positions < job.spawn_positions) || job.spawn_positions == -1)
Debug("DO pass, Player: [player], Level:[level], Job:[job.title]")
JobDebug("DO pass, Player: [player], Level:[level], Job:[job.title]")
AssignRole(player, job.title)
unassigned -= player
break
JobDebug("DO, Handling unassigned.")
// Hand out random jobs to the people who didn't get any in the last check
// Also makes sure that they got their preference correct
for(var/mob/dead/new_player/player in unassigned)
if(PopcapReached())
RejectPlayer(player)
else if(jobban_isbanned(player, SSjob.overflow_role))
GiveRandomJob(player) //you get to roll for random before everyone else just to be sure you don't get overflow. you're so speshul
for(var/mob/dead/new_player/player in unassigned)
if(PopcapReached())
RejectPlayer(player)
else if(player.client.prefs.joblessrole == BERANDOMJOB)
GiveRandomJob(player)
Debug("DO, Standard Check end")
Debug("DO, Running AC2")
// For those who wanted to be assistant if their preferences were filled, here you go.
for(var/mob/dead/new_player/player in unassigned)
if(PopcapReached())
RejectPlayer(player)
if(player.client.prefs.joblessrole == BEOVERFLOW)
Debug("AC2 Assistant located, Player: [player]")
AssignRole(player, SSjob.overflow_role)
else // For those who don't want to play if their preference were filled, back you go.
RejectPlayer(player)
HandleUnassigned(player)
JobDebug("DO, Handling unrejectable unassigned")
//Mop up people who can't leave.
for(var/mob/dead/new_player/player in unassigned) //Players that wanted to back out but couldn't because they're antags (can you feel the edge case?)
if(!GiveRandomJob(player))
AssignRole(player, SSjob.overflow_role) //If everything is already filled, make them an assistant
return 1
//We couldn't find a job from prefs for this guy.
/datum/controller/subsystem/job/proc/HandleUnassigned(mob/dead/new_player/player)
if(PopcapReached())
RejectPlayer(player)
else if(player.client.prefs.joblessrole == BEOVERFLOW)
var/allowed_to_be_a_loser = !jobban_isbanned(player, SSjob.overflow_role)
if(QDELETED(player) || !allowed_to_be_a_loser)
RejectPlayer(player)
else
if(!AssignRole(player, SSjob.overflow_role))
RejectPlayer(player)
else if(player.client.prefs.joblessrole == BERANDOMJOB)
if(!GiveRandomJob(player))
RejectPlayer(player)
else if(player.client.prefs.joblessrole == RETURNTOLOBBY)
RejectPlayer(player)
else //Something gone wrong if we got here.
var/message = "DO: [player] fell through handling unassigned"
JobDebug(message)
log_game(message)
message_admins(message)
RejectPlayer(player)
//Gives the player the stuff he should have with his rank
/datum/controller/subsystem/job/proc/EquipRank(mob/M, rank, joined_late = FALSE)
var/mob/dead/new_player/N
@@ -422,7 +425,7 @@ SUBSYSTEM_DEF(job)
else
M = H
SSpersistence.antag_rep_change[M.client.ckey] += job.antag_rep
SSpersistence.antag_rep_change[M.client.ckey] += job.GetAntagRep()
to_chat(M, "<b>You are the [rank].</b>")
if(job)
@@ -436,11 +439,9 @@ SUBSYSTEM_DEF(job)
if(job && H)
if(job.dresscodecompliant)// CIT CHANGE - dress code compliance
equip_loadout(N, H) // CIT CHANGE - allows players to spawn with loadout items
job.after_spawn(H, M, joined_late)
job.after_spawn(H, M, joined_late) // note: this happens before the mob has a key! M will always have a client, H might not.
equip_loadout(N, H, TRUE)//CIT CHANGE - makes players spawn with in-backpack loadout items properly. A little hacky but it works
//handle_roundstart_items(H, M.ckey, H.mind.assigned_role, H.mind.special_role) //CIT CHANGE - makes donators spawn with their items. This can safely be commented out when all of the donator items are migrated to the loadout system
return H
@@ -453,7 +454,7 @@ SUBSYSTEM_DEF(job)
if(ssc > 0)
if(J.spawn_positions > 0)
var/officer_positions = min(12, max(J.spawn_positions, round(unassigned.len / ssc))) //Scale between configured minimum and 12 officers
Debug("Setting open security officer positions to [officer_positions]")
JobDebug("Setting open security officer positions to [officer_positions]")
J.total_positions = officer_positions
J.spawn_positions = officer_positions
@@ -489,7 +490,7 @@ SUBSYSTEM_DEF(job)
for(var/mob/dead/new_player/player in GLOB.player_list)
if(!(player.ready == PLAYER_READY_TO_PLAY && player.mind && !player.mind.assigned_role))
continue //This player is not ready
if(jobban_isbanned(player, job.title))
if(jobban_isbanned(player, job.title) || QDELETED(player))
banned++
continue
if(!job.player_old_enough(player.client))
@@ -525,7 +526,8 @@ SUBSYSTEM_DEF(job)
if(player.mind && player.mind.special_role)
return
if(PopcapReached())
Debug("Popcap overflow Check observer located, Player: [player]")
JobDebug("Popcap overflow Check observer located, Player: [player]")
JobDebug("Player rejected :[player]")
to_chat(player, "<b>You have failed to qualify for any job you desired.</b>")
unassigned -= player
player.ready = PLAYER_NOT_READY
@@ -630,3 +632,6 @@ SUBSYSTEM_DEF(job)
for(var/mob/living/carbon/human/player in GLOB.carbon_list)
if(player.mind && (player.mind.assigned_role in GLOB.security_positions))
. |= player.mind
/datum/controller/subsystem/job/proc/JobDebug(message)
log_job_debug(message)
+1 -9
View File
@@ -85,12 +85,4 @@ SUBSYSTEM_DEF(lighting)
/datum/controller/subsystem/lighting/Recover()
initialized = SSlighting.initialized
..()
/datum/controller/subsystem/lighting/proc/initialize_lighting_objects(list/turfs)
for(var/turf/T in turfs)
if(!IS_DYNAMIC_LIGHTING(T))
continue
new/atom/movable/lighting_object(T)
CHECK_TICK
..()
+1 -1
View File
@@ -45,7 +45,7 @@ SUBSYSTEM_DEF(machines)
else
processing -= thing
if (!QDELETED(thing))
thing.isprocessing = FALSE
thing.datum_flags &= ~DF_ISPROCESSING
if (MC_TICK_CHECK)
return
+112 -13
View File
@@ -21,6 +21,11 @@ SUBSYSTEM_DEF(mapping)
var/list/areas_in_z = list()
var/loading_ruins = FALSE
var/list/turf/unused_turfs = list() //Not actually unused turfs they're unused but reserved for use for whatever requests them. "[zlevel_of_turf]" = list(turfs)
var/list/datum/turf_reservations //list of turf reservations
var/list/used_turfs = list() //list of turf = datum/turf_reservation
var/clearing_reserved_turfs = FALSE
// Z-manager stuff
var/station_start // should only be used for maploading-related tasks
@@ -41,8 +46,14 @@ SUBSYSTEM_DEF(mapping)
/datum/controller/subsystem/mapping/Initialize(timeofday)
if(initialized)
return
if(config.defaulted)
to_chat(world, "<span class='boldannounce'>Unable to load next map config, defaulting to Box Station</span>")
var/old_config = config
config = global.config.defaultmap
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
loader = new
loadWorld()
repopulate_sorted_areas()
@@ -58,12 +69,13 @@ SUBSYSTEM_DEF(mapping)
++space_levels_so_far
empty_space = add_new_zlevel("Empty Area [space_levels_so_far]", list(ZTRAIT_LINKAGE = CROSSLINKED))
// and the transit level
transit = add_new_zlevel("Transit", list(ZTRAIT_TRANSIT = TRUE))
transit = add_new_zlevel("Transit/Reserved", list(ZTRAIT_RESERVED = TRUE))
// Pick a random away mission.
if(CONFIG_GET(flag/roundstart_away))
createRandomZlevel()
// Generate mining ruins
loading_ruins = TRUE
var/list/lava_ruins = levels_by_trait(ZTRAIT_LAVA_RUINS)
@@ -83,12 +95,42 @@ SUBSYSTEM_DEF(mapping)
setup_map_transitions()
generate_station_area_list()
QDEL_NULL(loader)
initialize_reserved_level()
..()
/* Nuke threats, for making the blue tiles on the station go RED
Used by the AI doomsday and the self destruct nuke.
*/
/datum/controller/subsystem/mapping/proc/wipe_reservations(wipe_safety_delay = 100)
if(clearing_reserved_turfs || !initialized) //in either case this is just not needed.
return
clearing_reserved_turfs = TRUE
SSshuttle.transit_requesters.Cut()
message_admins("Clearing dynamic reservation space.")
var/list/obj/docking_port/mobile/in_transit = list()
for(var/i in SSshuttle.transit)
var/obj/docking_port/stationary/transit/T = i
if(!istype(T))
continue
in_transit[T] = T.get_docked()
var/go_ahead = world.time + wipe_safety_delay
if(in_transit.len)
message_admins("Shuttles in transit detected. Attempting to fast travel. Timeout is [wipe_safety_delay/10] seconds.")
var/list/cleared = list()
for(var/i in in_transit)
INVOKE_ASYNC(src, .proc/safety_clear_transit_dock, i, in_transit[i], cleared)
UNTIL((go_ahead < world.time) || (cleared.len == in_transit.len))
do_wipe_turf_reservations()
clearing_reserved_turfs = FALSE
/datum/controller/subsystem/mapping/proc/safety_clear_transit_dock(obj/docking_port/stationary/transit/T, obj/docking_port/mobile/M, list/returning)
M.setTimer(0)
var/error = M.initiate_docking(M.destination, M.preferred_direction)
if(!error)
returning += M
qdel(T, TRUE)
/datum/controller/subsystem/mapping/proc/add_nuke_threat(datum/nuke)
nuke_threats[nuke] = TRUE
check_nuke_threats()
@@ -108,20 +150,26 @@ SUBSYSTEM_DEF(mapping)
/datum/controller/subsystem/mapping/Recover()
flags |= SS_NO_INIT
initialized = SSmapping.initialized
map_templates = SSmapping.map_templates
ruins_templates = SSmapping.ruins_templates
space_ruins_templates = SSmapping.space_ruins_templates
lava_ruins_templates = SSmapping.lava_ruins_templates
shuttle_templates = SSmapping.shuttle_templates
shelter_templates = SSmapping.shelter_templates
unused_turfs = SSmapping.unused_turfs
turf_reservations = SSmapping.turf_reservations
used_turfs = SSmapping.used_turfs
config = SSmapping.config
next_map_config = SSmapping.next_map_config
clearing_reserved_turfs = SSmapping.clearing_reserved_turfs
z_list = SSmapping.z_list
#define INIT_ANNOUNCE(X) to_chat(world, "<span class='boldannounce'>[X]</span>"); log_world(X)
/datum/controller/subsystem/mapping/proc/LoadGroup(list/errorList, name, path, files, list/traits, list/default_traits)
/datum/controller/subsystem/mapping/proc/LoadGroup(list/errorList, name, path, files, list/traits, list/default_traits, silent = FALSE)
var/start_time = REALTIMEOFDAY
if (!islist(files)) // handle single-level maps
@@ -157,8 +205,8 @@ SUBSYSTEM_DEF(mapping)
var/full_path = "_maps/[path]/[file]"
if(!loader.load_map(file(full_path), 0, 0, start_z + files[file], no_changeturf = TRUE))
errorList |= full_path
INIT_ANNOUNCE("Loaded [name] in [(REALTIMEOFDAY - start_time)/10]s!")
if(!silent)
INIT_ANNOUNCE("Loaded [name] in [(REALTIMEOFDAY - start_time)/10]s!")
/datum/controller/subsystem/mapping/proc/loadWorld()
//if any of these fail, something has gone horribly, HORRIBLY, wrong
@@ -175,6 +223,7 @@ SUBSYSTEM_DEF(mapping)
if(SSdbcore.Connect())
var/datum/DBQuery/query_round_map_name = SSdbcore.NewQuery("UPDATE [format_table_name("round")] SET map_name = '[config.map_name]' WHERE id = [GLOB.round_id]")
query_round_map_name.Execute()
qdel(query_round_map_name)
#ifndef LOWMEMORYMODE
// TODO: remove this when the DB is prepared for the z-levels getting reordered
@@ -187,9 +236,6 @@ SUBSYSTEM_DEF(mapping)
LoadGroup(FailedZs, "Lavaland", "map_files/Mining", "Lavaland.dmm", default_traits = ZTRAITS_LAVALAND)
else if (!isnull(config.minetype))
INIT_ANNOUNCE("WARNING: An unknown minetype '[config.minetype]' was set! This is being ignored! Update the maploader code!")
// load Reebe
LoadGroup(FailedZs, "Reebe", "map_files/generic", "City_of_Cogs.dmm", default_traits = ZTRAITS_REEBE)
#endif
if(LAZYLEN(FailedZs)) //but seriously, unless the server's filesystem is messed up this will never happen
@@ -331,7 +377,6 @@ GLOBAL_LIST_EMPTY(the_station_areas)
shelter_templates[S.shelter_id] = S
map_templates[S.shelter_id] = S
//Manual loading of away missions.
/client/proc/admin_away()
set name = "Load Away Mission"
@@ -367,14 +412,14 @@ GLOBAL_LIST_EMPTY(the_station_areas)
away_level = template.load_new_z()
else
return
message_admins("Admin [key_name_admin(usr)] has loaded [away_name] away mission.")
log_admin("Admin [key_name(usr)] has loaded [away_name] away mission.")
if(!away_level)
message_admins("Loading [away_name] failed!")
return
if(GLOB.the_gateway)
//Link any found away gate with station gate
var/obj/machinery/gateway/centeraway/new_gate
@@ -384,4 +429,58 @@ GLOBAL_LIST_EMPTY(the_station_areas)
break
//Link station gate with away gate and remove wait time.
GLOB.the_gateway.awaygate = new_gate
GLOB.the_gateway.wait = world.time
GLOB.the_gateway.wait = world.time
/datum/controller/subsystem/mapping/proc/RequestBlockReservation(width, height, z, type = /datum/turf_reservation, turf_type_override)
UNTIL(initialized && !clearing_reserved_turfs)
var/datum/turf_reservation/reserve = new type
if(turf_type_override)
reserve.turf_type = turf_type_override
if(!z)
for(var/i in levels_by_trait(ZTRAIT_RESERVED))
if(reserve.Reserve(width, height, i))
return reserve
else
if(!level_trait(z, ZTRAIT_RESERVED))
qdel(reserve)
return
else
if(reserve.Reserve(width, height, z))
return reserve
QDEL_NULL(reserve)
//This is not for wiping reserved levels, use wipe_reservations() for that.
/datum/controller/subsystem/mapping/proc/initialize_reserved_level()
UNTIL(!clearing_reserved_turfs) //regardless, lets add a check just in case.
clearing_reserved_turfs = TRUE //This operation will likely clear any existing reservations, so lets make sure nothing tries to make one while we're doing it.
for(var/i in levels_by_trait(ZTRAIT_RESERVED))
var/turf/A = get_turf(locate(SHUTTLE_TRANSIT_BORDER,SHUTTLE_TRANSIT_BORDER,i))
var/turf/B = get_turf(locate(world.maxx - SHUTTLE_TRANSIT_BORDER,world.maxy - SHUTTLE_TRANSIT_BORDER,i))
reserve_turfs(block(A, B))
clearing_reserved_turfs = FALSE
/datum/controller/subsystem/mapping/proc/reserve_turfs(list/turfs)
for(var/i in turfs)
var/turf/T = i
T.empty(RESERVED_TURF_TYPE, RESERVED_TURF_TYPE, null, TRUE)
LAZYINITLIST(unused_turfs["[T.z]"])
unused_turfs["[T.z]"] |= T
T.flags_1 |= UNUSED_RESERVATION_TURF_1
CHECK_TICK
//DO NOT CALL THIS PROC DIRECTLY, CALL wipe_reservations().
/datum/controller/subsystem/mapping/proc/do_wipe_turf_reservations()
UNTIL(initialized) //This proc is for AFTER init, before init turf reservations won't even exist and using this will likely break things.
for(var/i in turf_reservations)
var/datum/turf_reservation/TR = i
if(!QDELETED(TR))
qdel(TR, TRUE)
UNSETEMPTY(turf_reservations)
var/list/clearing = list()
for(var/l in unused_turfs) //unused_turfs is a assoc list by z = list(turfs)
if(islist(unused_turfs[l]))
clearing |= unused_turfs[l]
clearing |= used_turfs //used turfs is an associative list, BUT, reserve_turfs() can still handle it. If the code above works properly, this won't even be needed as the turfs would be freed already.
unused_turfs.Cut()
used_turfs.Cut()
reserve_turfs(clearing)
-1
View File
@@ -7,7 +7,6 @@ SUBSYSTEM_DEF(mobs)
var/list/currentrun = list()
var/static/list/clients_by_zlevel[][]
var/static/list/cubemonkeys = list()
var/cubemonkeycap = 64
/datum/controller/subsystem/mobs/stat_entry()
..("P:[GLOB.mob_living_list.len]")
+42 -41
View File
@@ -115,38 +115,43 @@ SUBSYSTEM_DEF(overlays)
#define NOT_QUEUED_ALREADY (!(flags_1 & OVERLAY_QUEUED_1))
#define QUEUE_FOR_COMPILE flags_1 |= OVERLAY_QUEUED_1; SSoverlays.queue += src;
/atom/proc/cut_overlays(priority = FALSE)
var/list/cached_overlays = our_overlays
var/list/cached_priority = priority_overlays
LAZYINITLIST(priority_overlays)
LAZYINITLIST(remove_overlays)
LAZYINITLIST(add_overlays)
remove_overlays = overlays.Copy()
add_overlays.Cut()
var/need_compile = FALSE
if(priority)
priority_overlays.Cut()
if(LAZYLEN(cached_overlays)) //don't queue empty lists, don't cut priority overlays
cached_overlays.Cut() //clear regular overlays
need_compile = TRUE
if(priority && LAZYLEN(cached_priority))
cached_priority.Cut()
need_compile = TRUE
if(NOT_QUEUED_ALREADY && need_compile)
//If not already queued for work and there are overlays to remove
if(NOT_QUEUED_ALREADY && remove_overlays.len)
QUEUE_FOR_COMPILE
/atom/proc/cut_overlay(list/overlays, priority)
if(!overlays)
return
overlays = build_appearance_list(overlays)
LAZYINITLIST(add_overlays) //always initialized after this point
LAZYINITLIST(priority_overlays)
LAZYINITLIST(remove_overlays)
var/a_len = add_overlays.len
var/r_len = remove_overlays.len
var/p_len = priority_overlays.len
remove_overlays += overlays
add_overlays -= overlays
var/list/cached_overlays = our_overlays //sanic
var/list/cached_priority = priority_overlays
var/init_o_len = LAZYLEN(cached_overlays)
var/init_p_len = LAZYLEN(cached_priority) //starter pokemon
LAZYREMOVE(cached_overlays, overlays)
if(priority)
var/list/cached_priority = priority_overlays
LAZYREMOVE(cached_priority, overlays)
if(NOT_QUEUED_ALREADY && ((init_o_len != LAZYLEN(cached_overlays)) || (init_p_len != LAZYLEN(cached_priority))))
var/fa_len = add_overlays.len
var/fr_len = remove_overlays.len
var/fp_len = priority_overlays.len
//If not already queued and there is work to be done
if(NOT_QUEUED_ALREADY && (fa_len != a_len || fr_len != r_len || fp_len != p_len))
QUEUE_FOR_COMPILE
/atom/proc/add_overlay(list/overlays, priority = FALSE)
@@ -155,24 +160,21 @@ SUBSYSTEM_DEF(overlays)
overlays = build_appearance_list(overlays)
LAZYINITLIST(our_overlays) //always initialized after this point
LAZYINITLIST(add_overlays) //always initialized after this point
LAZYINITLIST(priority_overlays)
var/list/cached_overlays = our_overlays //sanic
var/list/cached_priority = priority_overlays
var/init_o_len = cached_overlays.len
var/init_p_len = cached_priority.len //starter pokemon
var/need_compile
var/a_len = add_overlays.len
var/p_len = priority_overlays.len
if(priority)
cached_priority += overlays //or in the image. Can we use [image] = image?
need_compile = init_p_len != cached_priority.len
priority_overlays += overlays //or in the image. Can we use [image] = image?
var/fp_len = priority_overlays.len
if(NOT_QUEUED_ALREADY && fp_len != p_len)
QUEUE_FOR_COMPILE
else
cached_overlays += overlays
need_compile = init_o_len != cached_overlays.len
if(NOT_QUEUED_ALREADY && need_compile) //have we caught more pokemon?
QUEUE_FOR_COMPILE
add_overlays += overlays
var/fa_len = add_overlays.len
if(NOT_QUEUED_ALREADY && fa_len != a_len)
QUEUE_FOR_COMPILE
/atom/proc/copy_overlays(atom/other, cut_old) //copys our_overlays from another atom
if(!other)
@@ -180,12 +182,11 @@ SUBSYSTEM_DEF(overlays)
cut_overlays()
return
var/list/cached_other = other.our_overlays
var/list/cached_other = other.overlays.Copy()
if(cached_other)
if(cut_old || !LAZYLEN(our_overlays))
our_overlays = cached_other.Copy()
else
our_overlays |= cached_other
if(cut_old || !LAZYLEN(overlays))
remove_overlays = overlays
add_overlays = cached_other
if(NOT_QUEUED_ALREADY)
QUEUE_FOR_COMPILE
else if(cut_old)
@@ -196,7 +197,7 @@ SUBSYSTEM_DEF(overlays)
//TODO: Better solution for these?
/image/proc/add_overlay(x)
overlays += x
overlays |= x
/image/proc/cut_overlay(x)
overlays -= x
@@ -210,10 +211,10 @@ SUBSYSTEM_DEF(overlays)
cut_overlays()
return
var/list/cached_other = other.our_overlays
var/list/cached_other = other.overlays.Copy()
if(cached_other)
if(cut_old || !overlays.len)
overlays = cached_other.Copy()
overlays = cached_other
else
overlays |= cached_other
else if(cut_old)
+1 -1
View File
@@ -212,7 +212,7 @@ SUBSYSTEM_DEF(persistence)
continue
var/list/savable_obj = list()
for(var/obj/O in F)
if(is_type_in_typecache(O, satchel_blacklist) || O.admin_spawned)
if(is_type_in_typecache(O, satchel_blacklist) || (O.flags_1 & ADMIN_SPAWNED_1))
continue
if(O.persistence_replacement)
savable_obj += O.persistence_replacement
@@ -78,5 +78,8 @@ PROCESSING_SUBSYSTEM_DEF(circuit)
/obj/item/integrated_electronics/wirer,
/obj/item/integrated_electronics/debugger,
/obj/item/integrated_electronics/analyzer,
/obj/item/integrated_electronics/detailer
/obj/item/integrated_electronics/detailer,
/obj/item/card/data,
/obj/item/card/data/full_color,
/obj/item/card/data/disk
)
@@ -27,7 +27,6 @@ SUBSYSTEM_DEF(processing)
if (MC_TICK_CHECK)
return
/datum/var/isprocessing = FALSE
/datum/proc/process()
set waitfor = 0
STOP_PROCESSING(SSobj, src)
+1
View File
@@ -8,3 +8,4 @@ SUBSYSTEM_DEF(religion)
var/bible_icon_state
var/bible_item_state
var/holy_weapon_type
var/holy_armor_type
+2 -8
View File
@@ -22,14 +22,9 @@ SUBSYSTEM_DEF(research)
var/list/errored_datums = list()
var/list/point_types = list() //typecache style type = TRUE list
//----------------------------------------------
var/list/single_server_income = list(TECHWEB_POINT_TYPE_GENERIC = 54.3)
var/list/single_server_income = list(TECHWEB_POINT_TYPE_GENERIC = 20) //citadel edit - techwebs nerf
var/multiserver_calculation = FALSE
var/last_income = 0
//^^^^^^^^ ALL OF THESE ARE PER SECOND! ^^^^^^^^
//Aiming for 1.5 hours to max R&D
//[88nodes * 5000points/node] / [1.5hr * 90min/hr * 60s/min]
//Around 450000 points max???
/datum/controller/subsystem/research/Initialize()
point_types = TECHWEB_POINT_TYPE_LIST_ASSOCIATIVE_NAMES
@@ -44,9 +39,8 @@ SUBSYSTEM_DEF(research)
handle_research_income()
/datum/controller/subsystem/research/proc/handle_research_income()
var/list/bitcoins
var/list/bitcoins = list()
if(multiserver_calculation)
bitcoins = list()
var/eff = calculate_server_coefficient()
for(var/obj/machinery/rnd/server/miner in servers)
var/list/result = (miner.mine()) //SLAVE AWAY, SLAVE.
+36 -124
View File
@@ -1,4 +1,3 @@
#define HIGHLIGHT_DYNAMIC_TRANSIT 0
#define MAX_TRANSIT_REQUEST_RETRIES 10
SUBSYSTEM_DEF(shuttle)
@@ -14,10 +13,8 @@ SUBSYSTEM_DEF(shuttle)
var/list/stationary = list()
var/list/transit = list()
var/list/turf/transit_turfs = list()
var/list/transit_requesters = list()
var/list/transit_request_failures = list()
var/clear_transit = FALSE
//emergency shuttle stuff
var/obj/docking_port/mobile/emergency/emergency
@@ -67,15 +64,8 @@ SUBSYSTEM_DEF(shuttle)
continue
supply_packs[P.type] = P
if(!transit_turfs.len)
setup_transit_zone()
initial_load()
#ifdef HIGHLIGHT_DYNAMIC_TRANSIT
color_space()
#endif
if(!arrivals)
WARNING("No /obj/docking_port/mobile/arrivals placed on the map!")
if(!emergency)
@@ -95,33 +85,6 @@ SUBSYSTEM_DEF(shuttle)
S.load_roundstart()
CHECK_TICK
/datum/controller/subsystem/shuttle/proc/setup_transit_zone()
// transit zone
var/z = SSmapping.transit.z_value
var/turf/A = get_turf(locate(SHUTTLE_TRANSIT_BORDER,SHUTTLE_TRANSIT_BORDER,z))
var/turf/B = get_turf(locate(world.maxx - SHUTTLE_TRANSIT_BORDER,world.maxy - SHUTTLE_TRANSIT_BORDER,z))
for(var/i in block(A, B))
var/turf/T = i
T.ChangeTurf(/turf/open/space)
transit_turfs += T
T.flags_1 |= UNUSED_TRANSIT_TURF_1
#ifdef HIGHLIGHT_DYNAMIC_TRANSIT
/datum/controller/subsystem/shuttle/proc/color_space()
var/z = SSmapping.transit.z_value
var/turf/A = get_turf(locate(SHUTTLE_TRANSIT_BORDER,SHUTTLE_TRANSIT_BORDER,z))
var/turf/B = get_turf(locate(world.maxx - SHUTTLE_TRANSIT_BORDER,world.maxy - SHUTTLE_TRANSIT_BORDER,z))
for(var/i in block(A, B))
var/turf/T = i
// Only dying the "pure" space, not the transit tiles
if(istype(T, /turf/open/space/transit) || !isspaceturf(T))
continue
if((T.x == A.x) || (T.x == B.x) || (T.y == A.y) || (T.y == B.y))
T.color = "#ffff00"
else
T.color = "#00ffff"
#endif
/datum/controller/subsystem/shuttle/fire()
for(var/thing in mobile)
if(!thing)
@@ -129,12 +92,10 @@ SUBSYSTEM_DEF(shuttle)
continue
var/obj/docking_port/mobile/P = thing
P.check()
var/changed_transit = FALSE
for(var/thing in transit)
var/obj/docking_port/stationary/transit/T = thing
if(!T.owner)
qdel(T, force=TRUE)
changed_transit = TRUE
// This next one removes transit docks/zones that aren't
// immediately being used. This will mean that the zone creation
// code will be running a lot.
@@ -145,32 +106,21 @@ SUBSYSTEM_DEF(shuttle)
var/not_in_use = (!T.get_docked())
if(idle && not_centcom_evac && not_in_use)
qdel(T, force=TRUE)
changed_transit = TRUE
if(clear_transit)
transit_requesters.Cut()
for(var/i in transit)
qdel(i, force=TRUE)
setup_transit_zone()
clear_transit = FALSE
changed_transit = TRUE
#ifdef HIGHLIGHT_DYNAMIC_TRANSIT
if(changed_transit)
color_space()
#endif
CheckAutoEvac()
while(transit_requesters.len)
var/requester = popleft(transit_requesters)
var/success = generate_transit_dock(requester)
if(!success) // BACK OF THE QUEUE
transit_request_failures[requester]++
if(transit_request_failures[requester] < MAX_TRANSIT_REQUEST_RETRIES)
transit_requesters += requester
else
var/obj/docking_port/mobile/M = requester
M.transit_failure()
if(MC_TICK_CHECK)
break
if(!SSmapping.clearing_reserved_turfs)
while(transit_requesters.len)
var/requester = popleft(transit_requesters)
var/success = generate_transit_dock(requester)
if(!success) // BACK OF THE QUEUE
transit_request_failures[requester]++
if(transit_request_failures[requester] < MAX_TRANSIT_REQUEST_RETRIES)
transit_requesters += requester
else
var/obj/docking_port/mobile/M = requester
M.transit_failure()
if(MC_TICK_CHECK)
break
/datum/controller/subsystem/shuttle/proc/CheckAutoEvac()
if(emergencyNoEscape || emergencyNoRecall || !emergency || !SSticker.HasRoundStarted())
@@ -277,7 +227,7 @@ SUBSYSTEM_DEF(shuttle)
if(call_reason)
SSblackbox.record_feedback("text", "shuttle_reason", 1, "[call_reason]")
log_game("Shuttle call reason: [call_reason]")
message_admins("[key_name_admin(user)] has called the shuttle. (<A HREF='?_src_=holder;[HrefToken()];trigger_centcom_recall=1'>TRIGGER CENTCOM RECALL</A>)")
message_admins("[ADMIN_LOOKUPFLW(user)] has called the shuttle. (<A HREF='?_src_=holder;[HrefToken()];trigger_centcom_recall=1'>TRIGGER CENTCOM RECALL</A>)")
/datum/controller/subsystem/shuttle/proc/centcom_recall(old_timer, admiral_message)
if(emergency.mode != SHUTTLE_CALL || emergency.timer != old_timer)
@@ -310,9 +260,8 @@ SUBSYSTEM_DEF(shuttle)
if(canRecall())
emergency.cancel(get_area(user))
log_game("[key_name(user)] has recalled the shuttle.")
message_admins("[key_name_admin(user)] has recalled the shuttle.")
var/area/A = get_area(user)
deadchat_broadcast("<span class='deadsay'><span class='name'>[user.real_name]</span> has recalled the shuttle at <span class='name'>[A.name]</span>.</span>", user)
message_admins("[ADMIN_LOOKUPFLW(user)] has recalled the shuttle.")
deadchat_broadcast("<span class='deadsay'><span class='name'>[user.real_name]</span> has recalled the shuttle from <span class='name'>[get_area_name(user, TRUE)]</span>.</span>", user)
return 1
/datum/controller/subsystem/shuttle/proc/canRecall()
@@ -476,43 +425,29 @@ SUBSYSTEM_DEF(shuttle)
if(EAST, WEST)
transit_width += M.height
transit_height += M.width
/*
to_chat(world, "The attempted transit dock will be [transit_width] width, and \)
[transit_height] in height. The travel dir is [travel_dir]."
*/
// Then find a place to put the zone
var/transit_path = /turf/open/space/transit
switch(travel_dir)
if(NORTH)
transit_path = /turf/open/space/transit/north
if(SOUTH)
transit_path = /turf/open/space/transit/south
if(EAST)
transit_path = /turf/open/space/transit/east
if(WEST)
transit_path = /turf/open/space/transit/west
var/list/proposed_zone
var/datum/turf_reservation/proposal = SSmapping.RequestBlockReservation(transit_width, transit_height, null, /datum/turf_reservation/transit, transit_path)
base:
for(var/i in transit_turfs)
CHECK_TICK
var/turf/topleft = i
if(!(topleft.flags_1 & UNUSED_TRANSIT_TURF_1))
continue
var/turf/bottomright = locate(topleft.x + transit_width,
topleft.y + transit_height, topleft.z)
if(!bottomright)
continue
if(!(bottomright.flags_1 & UNUSED_TRANSIT_TURF_1))
continue
proposed_zone = block(topleft, bottomright)
if(!proposed_zone)
continue
for(var/j in proposed_zone)
var/turf/T = j
if(!T)
continue base
if(!(T.flags_1 & UNUSED_TRANSIT_TURF_1))
continue base
break base
if((!proposed_zone) || (!proposed_zone.len))
if(!istype(proposal))
return FALSE
var/turf/topleft = proposed_zone[1]
var/turf/bottomleft = locate(proposal.bottom_left_coords[1], proposal.bottom_left_coords[2], proposal.bottom_left_coords[3])
// Then create a transit docking port in the middle
var/coords = M.return_coords(0, 0, dock_dir)
/* 0------2
@@ -531,41 +466,24 @@ SUBSYSTEM_DEF(shuttle)
var/y2 = min(y0, y1)
// Then invert the numbers
var/transit_x = topleft.x + SHUTTLE_TRANSIT_BORDER + abs(x2)
var/transit_y = topleft.y + SHUTTLE_TRANSIT_BORDER + abs(y2)
var/transit_x = bottomleft.x + SHUTTLE_TRANSIT_BORDER + abs(x2)
var/transit_y = bottomleft.y + SHUTTLE_TRANSIT_BORDER + abs(y2)
var/transit_path = /turf/open/space/transit
switch(travel_dir)
if(NORTH)
transit_path = /turf/open/space/transit/north
if(SOUTH)
transit_path = /turf/open/space/transit/south
if(EAST)
transit_path = /turf/open/space/transit/east
if(WEST)
transit_path = /turf/open/space/transit/west
var/turf/midpoint = locate(transit_x, transit_y, topleft.z)
var/turf/midpoint = locate(transit_x, transit_y, bottomleft.z)
if(!midpoint)
return FALSE
var/area/shuttle/transit/A = new()
A.parallax_movedir = travel_dir
A.contents = proposed_zone
A.contents = proposal.reserved_turfs
var/obj/docking_port/stationary/transit/new_transit_dock = new(midpoint)
new_transit_dock.assigned_turfs = proposed_zone
new_transit_dock.reserved_area = proposal
new_transit_dock.name = "Transit for [M.id]/[M.name]"
new_transit_dock.owner = M
new_transit_dock.assigned_area = A
// Add 180, because ports point inwards, rather than outwards
new_transit_dock.setDir(angle2dir(dock_angle))
for(var/i in new_transit_dock.assigned_turfs)
var/turf/T = i
T.ChangeTurf(transit_path)
T.flags_1 &= ~(UNUSED_TRANSIT_TURF_1)
M.assigned_transit = new_transit_dock
return new_transit_dock
@@ -576,9 +494,6 @@ SUBSYSTEM_DEF(shuttle)
stationary = SSshuttle.stationary
if (istype(SSshuttle.transit))
transit = SSshuttle.transit
if (istype(SSshuttle.transit_turfs))
transit_turfs = SSshuttle.transit_turfs
if (istype(SSshuttle.transit_requesters))
transit_requesters = SSshuttle.transit_requesters
if (istype(SSshuttle.transit_request_failures))
@@ -616,9 +531,6 @@ SUBSYSTEM_DEF(shuttle)
if (istype(SSshuttle.shuttle_purchase_requirements_met))
shuttle_purchase_requirements_met = SSshuttle.shuttle_purchase_requirements_met
if (clear_transit)
WARNING("The shuttle subsystem crashed and was recovered while clearing transit.")
centcom_message = SSshuttle.centcom_message
ordernum = SSshuttle.ordernum
points = SSshuttle.points
@@ -699,4 +611,4 @@ SUBSYSTEM_DEF(shuttle)
var/obj/machinery/computer/camera_advanced/shuttle_docker/C = V
C.update_hidden_docking_ports(remove_images, add_images)
QDEL_LIST(remove_images)
QDEL_LIST(remove_images)
+16 -5
View File
@@ -26,7 +26,7 @@ SUBSYSTEM_DEF(throwing)
var/atom/movable/AM = currentrun[currentrun.len]
var/datum/thrownthing/TT = currentrun[AM]
currentrun.len--
if (!AM || !TT)
if (QDELETED(AM) || QDELETED(TT))
processing -= AM
if (MC_TICK_CHECK)
return
@@ -61,6 +61,15 @@ SUBSYSTEM_DEF(throwing)
var/delayed_time = 0
var/last_move = 0
/datum/thrownthing/Destroy()
SSthrowing.processing -= thrownthing
thrownthing.throwing = null
thrownthing = null
target = null
thrower = null
callback = null
return ..()
/datum/thrownthing/proc/tick()
var/atom/movable/AM = thrownthing
if (!isturf(AM.loc) || !AM.throwing)
@@ -113,15 +122,15 @@ SUBSYSTEM_DEF(throwing)
return
/datum/thrownthing/proc/finalize(hit = FALSE, target=null)
set waitfor = 0
SSthrowing.processing -= thrownthing
set waitfor = FALSE
//done throwing, either because it hit something or it finished moving
thrownthing.throwing = null
if(!thrownthing)
return
if (!hit)
for (var/thing in get_turf(thrownthing)) //looking for our target on the turf we land on.
var/atom/A = thing
if (A == target)
hit = 1
hit = TRUE
thrownthing.throw_impact(A, src)
break
if (!hit)
@@ -136,6 +145,8 @@ SUBSYSTEM_DEF(throwing)
if (callback)
callback.Invoke()
qdel(src)
/datum/thrownthing/proc/hit_atom(atom/A)
finalize(hit=TRUE, target=A)
+13 -5
View File
@@ -42,6 +42,7 @@ SUBSYSTEM_DEF(ticker)
var/timeLeft //pregame timer
var/start_at
var/gametime_offset = 432000 //Deciseconds to add to world.time for station time.
var/station_time_rate_multiplier = 12 //factor of station time progressal vs real time.
@@ -263,8 +264,8 @@ SUBSYSTEM_DEF(ticker)
if(!GLOB.Debug2)
if(!can_continue)
qdel(mode)
mode = null
log_game("[mode.name] failed pre_setup, cause: [mode.setup_error]")
QDEL_NULL(mode)
to_chat(world, "<B>Error setting up [GLOB.master_mode].</B> Reverting to pre-game lobby.")
SSjob.ResetOccupations()
return 0
@@ -391,8 +392,8 @@ SUBSYSTEM_DEF(ticker)
captainless=0
if(player.mind.assigned_role != player.mind.special_role)
SSjob.EquipRank(N, player.mind.assigned_role, 0)
if(CONFIG_GET(flag/roundstart_traits))
SSquirks.AssignQuirks(player, N.client, TRUE)
if(CONFIG_GET(flag/roundstart_traits) && ishuman(N.new_character))
SSquirks.AssignQuirks(N.new_character, N.client, TRUE)
CHECK_TICK
if(captainless)
for(var/mob/dead/new_player/N in GLOB.player_list)
@@ -453,7 +454,7 @@ SUBSYSTEM_DEF(ticker)
queued_players -= next_in_line //Client disconnected, remove he
queue_delay = 0 //No vacancy: restart timer
if(25 to INFINITY) //No response from the next in line when a vacancy exists, remove he
to_chat(next_in_line, "<span class='danger'>No response recieved. You have been removed from the line.</span>")
to_chat(next_in_line, "<span class='danger'>No response received. You have been removed from the line.</span>")
queued_players -= next_in_line
queue_delay = 0
@@ -647,6 +648,13 @@ SUBSYSTEM_DEF(ticker)
if(end_string)
end_state = end_string
var/statspage = CONFIG_GET(string/roundstatsurl)
var/gamelogloc = CONFIG_GET(string/gamelogurl)
if(statspage)
to_chat(world, "<span class='info'>Round statistics and logs can be viewed <a href=\"[statspage][GLOB.round_id]\">at this website!</a></span>")
else if(gamelogloc)
to_chat(world, "<span class='info'>Round logs can be located <a href=\"[gamelogloc]\">at this website!</a></span>")
log_game("<span class='boldannounce'>Rebooting World. [reason]</span>")
world.Reboot()
+2
View File
@@ -485,6 +485,8 @@ SUBSYSTEM_DEF(timer)
if (hash_timer.flags & TIMER_STOPPABLE)
. = hash_timer.id
return
else if(flags & TIMER_OVERRIDE)
stack_trace("TIMER_OVERRIDE used without TIMER_UNIQUE")
var/timeToRun = world.time + wait
+4 -2
View File
@@ -337,9 +337,11 @@ SUBSYSTEM_DEF(vote)
return 1
/datum/action/vote/proc/remove_from_client()
if(owner && owner.client)
if(!owner)
return
if(owner.client)
owner.client.player_details.player_actions -= src
else if(owner.ckey)
var/datum/player_details/P = GLOB.player_details[owner.ckey]
if(P)
P.player_actions -= src
P.player_actions -= src