Merge branch 'master' of https://github.com/Citadel-Station-13/Citadel-Station-13 into upstream-merge-33574
This commit is contained in:
@@ -10,11 +10,13 @@ SUBSYSTEM_DEF(blackbox)
|
||||
var/sealed = FALSE //time to stop tracking stats?
|
||||
var/list/research_levels = list() //list of highest tech levels attained that isn't lost lost by destruction of RD computers
|
||||
var/list/versions = list("time_dilation_current" = 2,
|
||||
"science_techweb_unlock" = 2) //associative list of any feedback variables that have had their format changed since creation and their current version, remember to update this
|
||||
"science_techweb_unlock" = 2,
|
||||
"antagonists" = 3) //associative list of any feedback variables that have had their format changed since creation and their current version, remember to update this
|
||||
|
||||
|
||||
/datum/controller/subsystem/blackbox/Initialize()
|
||||
triggertime = world.time
|
||||
record_feedback("amount", "random_seed", Master.random_seed)
|
||||
. = ..()
|
||||
|
||||
//poll population
|
||||
@@ -225,7 +227,10 @@ Versioning
|
||||
var/pos = length(FV.json["data"]) + 1
|
||||
FV.json["data"]["[pos]"] = list() //in 512 "pos" can be replaced with "[FV.json["data"].len+1]"
|
||||
for(var/i in data)
|
||||
FV.json["data"]["[pos]"]["[i]"] = "[data[i]]" //and here with "[FV.json["data"].len]"
|
||||
if(islist(data[i]))
|
||||
FV.json["data"]["[pos]"]["[i]"] = data[i] //and here with "[FV.json["data"].len]"
|
||||
else
|
||||
FV.json["data"]["[pos]"]["[i]"] = "[data[i]]"
|
||||
else
|
||||
CRASH("Invalid feedback key_type: [key_type]")
|
||||
|
||||
|
||||
@@ -0,0 +1,12 @@
|
||||
SUBSYSTEM_DEF(input)
|
||||
name = "Input"
|
||||
wait = 1 //SS_TICKER means this runs every tick
|
||||
flags = SS_TICKER | SS_NO_INIT
|
||||
priority = 1000
|
||||
runlevels = RUNLEVELS_DEFAULT | RUNLEVEL_LOBBY
|
||||
|
||||
/datum/controller/subsystem/input/fire()
|
||||
var/list/clients = GLOB.clients // Let's sing the list cache song
|
||||
for(var/i in 1 to clients.len)
|
||||
var/client/C = clients[i]
|
||||
C.keyLoop()
|
||||
@@ -21,8 +21,8 @@ SUBSYSTEM_DEF(parallax)
|
||||
return
|
||||
continue
|
||||
var/atom/movable/A = C.eye
|
||||
if(!A)
|
||||
return
|
||||
if(!istype(A))
|
||||
continue
|
||||
for (A; isloc(A.loc) && !isturf(A.loc); A = A.loc);
|
||||
|
||||
if(A != C.movingmob)
|
||||
|
||||
@@ -20,7 +20,7 @@ SUBSYSTEM_DEF(research)
|
||||
var/list/techweb_point_items = list() //path = value
|
||||
var/list/errored_datums = list()
|
||||
//----------------------------------------------
|
||||
var/single_server_income = 40.7
|
||||
var/single_server_income = 54.3
|
||||
var/multiserver_calculation = FALSE
|
||||
var/last_income = 0
|
||||
//^^^^^^^^ ALL OF THESE ARE PER SECOND! ^^^^^^^^
|
||||
|
||||
@@ -307,6 +307,9 @@ SUBSYSTEM_DEF(shuttle)
|
||||
return 1
|
||||
|
||||
/datum/controller/subsystem/shuttle/proc/autoEvac()
|
||||
if (!SSticker.IsRoundInProgress())
|
||||
return
|
||||
|
||||
var/callShuttle = 1
|
||||
|
||||
for(var/thing in GLOB.shuttle_caller_list)
|
||||
@@ -397,7 +400,7 @@ SUBSYSTEM_DEF(shuttle)
|
||||
if(M.request(getDock(destination)))
|
||||
return 2
|
||||
else
|
||||
if(M.dock(getDock(destination)) != DOCKING_SUCCESS)
|
||||
if(M.initiate_docking(getDock(destination)) != DOCKING_SUCCESS)
|
||||
return 2
|
||||
return 0 //dock successful
|
||||
|
||||
@@ -412,7 +415,7 @@ SUBSYSTEM_DEF(shuttle)
|
||||
if(M.request(D))
|
||||
return 2
|
||||
else
|
||||
if(M.dock(D) != DOCKING_SUCCESS)
|
||||
if(M.initiate_docking(D) != DOCKING_SUCCESS)
|
||||
return 2
|
||||
return 0 //dock successful
|
||||
|
||||
|
||||
@@ -80,7 +80,7 @@ SUBSYSTEM_DEF(throwing)
|
||||
last_move = world.time
|
||||
|
||||
//calculate how many tiles to move, making up for any missed ticks.
|
||||
var/tilestomove = Ceiling(min(((((world.time+world.tick_lag) - start_time + delayed_time) * speed) - (dist_travelled ? dist_travelled : -1)), speed*MAX_TICKS_TO_MAKE_UP) * (world.tick_lag * SSthrowing.wait))
|
||||
var/tilestomove = CEILING(min(((((world.time+world.tick_lag) - start_time + delayed_time) * speed) - (dist_travelled ? dist_travelled : -1)), speed*MAX_TICKS_TO_MAKE_UP) * (world.tick_lag * SSthrowing.wait), 1)
|
||||
while (tilestomove-- > 0)
|
||||
if ((dist_travelled >= maxrange || AM.loc == target_turf) && AM.has_gravity(AM.loc))
|
||||
finalize()
|
||||
|
||||
@@ -398,204 +398,6 @@ SUBSYSTEM_DEF(ticker)
|
||||
var/mob/living/L = I
|
||||
L.notransform = FALSE
|
||||
|
||||
/datum/controller/subsystem/ticker/proc/declare_completion()
|
||||
set waitfor = FALSE
|
||||
var/station_evacuated = EMERGENCY_ESCAPED_OR_ENDGAMED
|
||||
var/num_survivors = 0
|
||||
var/num_escapees = 0
|
||||
var/num_shuttle_escapees = 0
|
||||
var/list/successfulCrew = list()
|
||||
var/list/miscreants = list()
|
||||
|
||||
to_chat(world, "<BR><BR><BR><FONT size=3><B>The round has ended.</B></FONT>")
|
||||
if(LAZYLEN(GLOB.round_end_notifiees))
|
||||
send2irc("Notice", "[GLOB.round_end_notifiees.Join(", ")] the round has ended.")
|
||||
|
||||
/* var/nocredits = config.no_credits_round_end
|
||||
for(var/client/C in GLOB.clients)
|
||||
if(!C.credits && !nocredits)
|
||||
C.RollCredits()
|
||||
C.playtitlemusic(40)*/
|
||||
|
||||
//Player status report
|
||||
for(var/i in GLOB.mob_list)
|
||||
var/mob/Player = i
|
||||
if(Player.mind && !isnewplayer(Player))
|
||||
if(Player.stat != DEAD && !isbrain(Player))
|
||||
num_survivors++
|
||||
if(station_evacuated) //If the shuttle has already left the station
|
||||
var/list/area/shuttle_areas
|
||||
if(SSshuttle && SSshuttle.emergency)
|
||||
shuttle_areas = SSshuttle.emergency.shuttle_areas
|
||||
if(!Player.onCentCom() && !Player.onSyndieBase())
|
||||
to_chat(Player, "<font color='blue'><b>You managed to survive, but were marooned on [station_name()]...</b></FONT>")
|
||||
else
|
||||
num_escapees++
|
||||
to_chat(Player, "<font color='green'><b>You managed to survive the events on [station_name()] as [Player.real_name].</b></FONT>")
|
||||
if(shuttle_areas[get_area(Player)])
|
||||
num_shuttle_escapees++
|
||||
else
|
||||
to_chat(Player, "<font color='green'><b>You managed to survive the events on [station_name()] as [Player.real_name].</b></FONT>")
|
||||
else
|
||||
to_chat(Player, "<font color='red'><b>You did not survive the events on [station_name()]...</b></FONT>")
|
||||
|
||||
CHECK_TICK
|
||||
|
||||
//Round statistics report
|
||||
var/datum/station_state/end_state = new /datum/station_state()
|
||||
end_state.count()
|
||||
var/station_integrity = min(PERCENT(GLOB.start_state.score(end_state)), 100)
|
||||
|
||||
to_chat(world, "<BR>[GLOB.TAB]Shift Duration: <B>[DisplayTimeText(world.time - SSticker.round_start_time)]</B>")
|
||||
to_chat(world, "<BR>[GLOB.TAB]Station Integrity: <B>[mode.station_was_nuked ? "<font color='red'>Destroyed</font>" : "[station_integrity]%"]</B>")
|
||||
if(mode.station_was_nuked)
|
||||
SSticker.news_report = STATION_DESTROYED_NUKE
|
||||
var/total_players = GLOB.joined_player_list.len
|
||||
if(total_players)
|
||||
to_chat(world, "<BR>[GLOB.TAB]Total Population: <B>[total_players]</B>")
|
||||
if(station_evacuated)
|
||||
to_chat(world, "<BR>[GLOB.TAB]Evacuation Rate: <B>[num_escapees] ([PERCENT(num_escapees/total_players)]%)</B>")
|
||||
to_chat(world, "<BR>[GLOB.TAB](on emergency shuttle): <B>[num_shuttle_escapees] ([PERCENT(num_shuttle_escapees/total_players)]%)</B>")
|
||||
news_report = STATION_EVACUATED
|
||||
if(SSshuttle.emergency.is_hijacked())
|
||||
news_report = SHUTTLE_HIJACK
|
||||
to_chat(world, "<BR>[GLOB.TAB]Survival Rate: <B>[num_survivors] ([PERCENT(num_survivors/total_players)]%)</B>")
|
||||
to_chat(world, "<BR>")
|
||||
|
||||
CHECK_TICK
|
||||
|
||||
//Silicon laws report
|
||||
for (var/i in GLOB.ai_list)
|
||||
var/mob/living/silicon/ai/aiPlayer = i
|
||||
if (aiPlayer.stat != DEAD && aiPlayer.mind)
|
||||
to_chat(world, "<b>[aiPlayer.name] (Played by: [aiPlayer.mind.key])'s laws at the end of the round were:</b>")
|
||||
aiPlayer.show_laws(1)
|
||||
else if (aiPlayer.mind) //if the dead ai has a mind, use its key instead
|
||||
to_chat(world, "<b>[aiPlayer.name] (Played by: [aiPlayer.mind.key])'s laws when it was deactivated were:</b>")
|
||||
aiPlayer.show_laws(1)
|
||||
|
||||
to_chat(world, "<b>Total law changes: [aiPlayer.law_change_counter]</b>")
|
||||
|
||||
if (aiPlayer.connected_robots.len)
|
||||
var/robolist = "<b>[aiPlayer.real_name]'s minions were:</b> "
|
||||
for(var/mob/living/silicon/robot/robo in aiPlayer.connected_robots)
|
||||
if(robo.mind)
|
||||
robolist += "[robo.name][robo.stat?" (Deactivated) (Played by: [robo.mind.key]), ":" (Played by: [robo.mind.key]), "]"
|
||||
to_chat(world, "[robolist]")
|
||||
|
||||
CHECK_TICK
|
||||
|
||||
for (var/mob/living/silicon/robot/robo in GLOB.silicon_mobs)
|
||||
if (!robo.connected_ai && robo.mind)
|
||||
if (robo.stat != DEAD)
|
||||
to_chat(world, "<b>[robo.name] (Played by: [robo.mind.key]) survived as an AI-less borg! Its laws were:</b>")
|
||||
else
|
||||
to_chat(world, "<b>[robo.name] (Played by: [robo.mind.key]) was unable to survive the rigors of being a cyborg without an AI. Its laws were:</b>")
|
||||
|
||||
if(robo) //How the hell do we lose robo between here and the world messages directly above this?
|
||||
robo.laws.show_laws(world)
|
||||
|
||||
CHECK_TICK
|
||||
|
||||
mode.declare_completion()//To declare normal completion.
|
||||
|
||||
CHECK_TICK
|
||||
|
||||
//calls auto_declare_completion_* for all modes
|
||||
for(var/handler in typesof(/datum/game_mode/proc))
|
||||
if (findtext("[handler]","auto_declare_completion_"))
|
||||
call(mode, handler)(force_ending)
|
||||
|
||||
CHECK_TICK
|
||||
|
||||
if(CONFIG_GET(string/cross_server_address))
|
||||
send_news_report()
|
||||
|
||||
CHECK_TICK
|
||||
|
||||
//Print a list of antagonists to the server log
|
||||
var/list/total_antagonists = list()
|
||||
//Look into all mobs in world, dead or alive
|
||||
for(var/datum/mind/Mind in minds)
|
||||
var/temprole = Mind.special_role
|
||||
if(temprole) //if they are an antagonist of some sort.
|
||||
if(temprole in total_antagonists) //If the role exists already, add the name to it
|
||||
total_antagonists[temprole] += ", [Mind.name]([Mind.key])"
|
||||
else
|
||||
total_antagonists.Add(temprole) //If the role doesnt exist in the list, create it and add the mob
|
||||
total_antagonists[temprole] += ": [Mind.name]([Mind.key])"
|
||||
|
||||
CHECK_TICK
|
||||
|
||||
//Now print them all into the log!
|
||||
log_game("Antagonists at round end were...")
|
||||
for(var/i in total_antagonists)
|
||||
log_game("[i]s[total_antagonists[i]].")
|
||||
|
||||
CHECK_TICK
|
||||
|
||||
for(var/datum/mind/crewMind in minds)
|
||||
if(!crewMind.current || !crewMind.objectives.len)
|
||||
continue
|
||||
for(var/datum/objective/miscreant/MO in crewMind.objectives)
|
||||
miscreants += "<B>[crewMind.current.real_name]</B> (Played by: <B>[crewMind.key]</B>)<BR><B>Objective</B>: [MO.explanation_text] <font color='grey'>(Optional)</font>"
|
||||
for(var/datum/objective/crew/CO in crewMind.objectives)
|
||||
if(CO.check_completion())
|
||||
to_chat(crewMind.current, "<br><B>Your optional objective</B>: [CO.explanation_text] <font color='green'><B>Success!</B></font>")
|
||||
successfulCrew += "<B>[crewMind.current.real_name]</B> (Played by: <B>[crewMind.key]</B>)<BR><B>Objective</B>: [CO.explanation_text] <font color='green'><B>Success!</B></font> <font color='grey'>(Optional)</font>"
|
||||
else
|
||||
to_chat(crewMind.current, "<br><B>Your optional objective</B>: [CO.explanation_text] <font color='red'><B>Failed.</B></font>")
|
||||
|
||||
if (successfulCrew.len)
|
||||
var/completedObjectives = "<B>The following crew members completed their Crew Objectives:</B><BR>"
|
||||
for(var/i in successfulCrew)
|
||||
completedObjectives += "[i]<BR>"
|
||||
to_chat(world, "[completedObjectives]<BR>")
|
||||
else
|
||||
if(CONFIG_GET(flag/allow_crew_objectives))
|
||||
to_chat(world, "<B>Nobody completed their Crew Objectives!</B><BR>")
|
||||
|
||||
CHECK_TICK
|
||||
|
||||
if (miscreants.len)
|
||||
var/miscreantObjectives = "<B>The following crew members were miscreants:</B><BR>"
|
||||
for(var/i in miscreants)
|
||||
miscreantObjectives += "[i]<BR>"
|
||||
to_chat(world, "[miscreantObjectives]<BR>")
|
||||
|
||||
CHECK_TICK
|
||||
|
||||
mode.declare_station_goal_completion()
|
||||
|
||||
CHECK_TICK
|
||||
//medals, placed far down so that people can actually see the commendations.
|
||||
if(GLOB.commendations.len)
|
||||
to_chat(world, "<b><font size=3>Medal Commendations:</font></b>")
|
||||
for (var/com in GLOB.commendations)
|
||||
to_chat(world, com)
|
||||
|
||||
CHECK_TICK
|
||||
|
||||
//Collects persistence features
|
||||
if(mode.allow_persistence_save)
|
||||
SSpersistence.CollectData()
|
||||
|
||||
//stop collecting feedback during grifftime
|
||||
SSblackbox.Seal()
|
||||
|
||||
sleep(50)
|
||||
ready_for_reboot = TRUE
|
||||
standard_reboot()
|
||||
|
||||
/datum/controller/subsystem/ticker/proc/standard_reboot()
|
||||
if(ready_for_reboot)
|
||||
if(mode.station_was_nuked)
|
||||
Reboot("Station destroyed by Nuclear Device.", "nuke")
|
||||
else
|
||||
Reboot("Round ended.", "proper completion")
|
||||
else
|
||||
CRASH("Attempted standard reboot without ticker roundend completion")
|
||||
|
||||
/datum/controller/subsystem/ticker/proc/send_tip_of_the_round()
|
||||
var/m
|
||||
if(selected_tip)
|
||||
|
||||
@@ -206,6 +206,7 @@ SUBSYSTEM_DEF(vote)
|
||||
var/datum/action/vote/V = new
|
||||
if(question)
|
||||
V.name = "Vote: [question]"
|
||||
C.player_details.player_actions += V
|
||||
V.Grant(C.mob)
|
||||
generated_actions += V
|
||||
return 1
|
||||
@@ -299,6 +300,7 @@ SUBSYSTEM_DEF(vote)
|
||||
for(var/v in generated_actions)
|
||||
var/datum/action/vote/V = v
|
||||
if(!QDELETED(V))
|
||||
V.remove_from_client()
|
||||
V.Remove(V.owner)
|
||||
generated_actions = list()
|
||||
|
||||
@@ -318,7 +320,16 @@ SUBSYSTEM_DEF(vote)
|
||||
/datum/action/vote/Trigger()
|
||||
if(owner)
|
||||
owner.vote()
|
||||
remove_from_client()
|
||||
Remove(owner)
|
||||
|
||||
/datum/action/vote/IsAvailable()
|
||||
return 1
|
||||
|
||||
/datum/action/vote/proc/remove_from_client()
|
||||
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
|
||||
Reference in New Issue
Block a user