From 9418a1c8a67d08f8e61ee08164fcfdf2332926c2 Mon Sep 17 00:00:00 2001 From: SkyMarshal Date: Thu, 21 Jun 2012 17:51:06 -0700 Subject: [PATCH] Traitor objective system update. --- code/WorkInProgress/SkyMarshal/Ultralight.dm | 56 +--- code/defines/area/Space Station 13 areas.dm | 2 +- code/game/events/EventProcs/space_ninja.dm | 2 +- code/game/gamemodes/changeling/changeling.dm | 4 +- code/game/gamemodes/newobjective.dm | 254 +++++++++++-------- code/game/gamemodes/traitor/traitor.dm | 43 ++++ 6 files changed, 209 insertions(+), 152 deletions(-) diff --git a/code/WorkInProgress/SkyMarshal/Ultralight.dm b/code/WorkInProgress/SkyMarshal/Ultralight.dm index 5e86b2a4df..dadc5c2ec2 100644 --- a/code/WorkInProgress/SkyMarshal/Ultralight.dm +++ b/code/WorkInProgress/SkyMarshal/Ultralight.dm @@ -21,7 +21,7 @@ #define ul_Clamp(Value) min(max(Value, 0), ul_Steps) -#define ul_IsLuminous(A) (A.LuminosityRed > 0 || A.LuminosityGreen > 0 || A.LuminosityBlue > 0) +#define ul_IsLuminous(A) (A.LuminosityRed || A.LuminosityGreen || A.LuminosityBlue) #define ul_Luminosity(A) max(A.LuminosityRed, A.LuminosityGreen, A.LuminosityBlue) @@ -94,35 +94,17 @@ atom/proc/ul_Illuminate() if(DeltaRed > 0) if(!Affected.MaxRed) Affected.MaxRed = list() - Affected.MaxRedSources = list() - if(!(DeltaRed in Affected.MaxRed)) - Affected.MaxRed.Add(DeltaRed) - Affected.MaxRedSources.Add(1) - else - var/list_location = Affected.MaxRed.Find(DeltaRed) - Affected.MaxRedSources[list_location]++ + Affected.MaxRed += DeltaRed if(DeltaGreen > 0) if(!Affected.MaxGreen) Affected.MaxGreen = list() - Affected.MaxGreenSources = list() - if(!(DeltaGreen in Affected.MaxGreen)) - Affected.MaxGreen.Add(DeltaGreen) - Affected.MaxGreenSources.Add(1) - else - var/list_location = Affected.MaxGreen.Find(DeltaGreen) - Affected.MaxGreenSources[list_location]++ + Affected.MaxGreen += DeltaGreen if(DeltaBlue > 0) if(!Affected.MaxBlue) Affected.MaxBlue = list() - Affected.MaxBlueSources = list() - if(!(DeltaBlue in Affected.MaxBlue)) - Affected.MaxBlue.Add(DeltaBlue) - Affected.MaxBlueSources.Add(1) - else - var/list_location = Affected.MaxBlue.Find(DeltaBlue) - Affected.MaxBlueSources[list_location]++ + Affected.MaxBlue += DeltaBlue Affected.ul_UpdateLight() @@ -154,42 +136,21 @@ atom/proc/ul_Extinguish() if(DeltaRed > 0) if(Affected.MaxRed) - var/list_location = Affected.MaxRed.Find(DeltaRed) - if(list_location) - if(Affected.MaxRedSources[list_location] > 1) - Affected.MaxRedSources[list_location]-- - else - Affected.MaxRed.Remove(DeltaRed) - Affected.MaxRedSources.Cut(list_location, list_location + 1) + Affected.MaxRed -= DeltaRed if(!Affected.MaxRed.len) del Affected.MaxRed - del Affected.MaxRedSources if(DeltaGreen > 0) if(Affected.MaxGreen) - var/list_location = Affected.MaxGreen.Find(DeltaGreen) - if(list_location) - if(Affected.MaxGreenSources[list_location] > 1) - Affected.MaxGreenSources[list_location]-- - else - Affected.MaxGreen.Remove(DeltaGreen) - Affected.MaxGreenSources.Cut(list_location, list_location + 1) + Affected.MaxGreen -= DeltaGreen if(!Affected.MaxGreen.len) del Affected.MaxGreen - del Affected.MaxGreenSources if(DeltaBlue > 0) if(Affected.MaxBlue) - var/list_location = Affected.MaxBlue.Find(DeltaBlue) - if(list_location) - if(Affected.MaxBlueSources[list_location] > 1) - Affected.MaxBlueSources[list_location]-- - else - Affected.MaxBlue.Remove(DeltaBlue) - Affected.MaxBlueSources.Cut(list_location, list_location + 1) + Affected.MaxBlue -= DeltaBlue if(!Affected.MaxBlue.len) del Affected.MaxBlue - del Affected.MaxBlueSources Affected.ul_UpdateLight() @@ -286,9 +247,6 @@ atom/movable/Move() turf/var/list/MaxRed turf/var/list/MaxGreen turf/var/list/MaxBlue -turf/var/list/MaxRedSources -turf/var/list/MaxGreenSources -turf/var/list/MaxBlueSources turf/proc/ul_GetRed() if(MaxRed) diff --git a/code/defines/area/Space Station 13 areas.dm b/code/defines/area/Space Station 13 areas.dm index 631f09b415..aa979fb998 100755 --- a/code/defines/area/Space Station 13 areas.dm +++ b/code/defines/area/Space Station 13 areas.dm @@ -328,7 +328,7 @@ proc/process_ghost_teleport_locs() name = "\improper Centcom" icon_state = "centcom" requires_power = 0 - ul_Lighting = 1 + ul_Lighting = 0 /area/centcom/control name = "\improper Centcom Control" diff --git a/code/game/events/EventProcs/space_ninja.dm b/code/game/events/EventProcs/space_ninja.dm index ca89012651..b075430e98 100644 --- a/code/game/events/EventProcs/space_ninja.dm +++ b/code/game/events/EventProcs/space_ninja.dm @@ -244,7 +244,7 @@ In either case, it's a good idea to spawn the ninja with a semi-random set of ob hostile_targets -= current_mind//Remove them from the list. if(2)//Steal var/list/datum/objective/theft = GenerateTheft(ninja_mind.assigned_role,ninja_mind) - var/datum/objective/steal/steal_objective = PickObjectiveFromList(theft) + var/datum/objective/steal/steal_objective = pickweight(theft) ninja_mind.objectives += steal_objective objective_list -= 2 diff --git a/code/game/gamemodes/changeling/changeling.dm b/code/game/gamemodes/changeling/changeling.dm index 3d9465a02d..c2910af968 100644 --- a/code/game/gamemodes/changeling/changeling.dm +++ b/code/game/gamemodes/changeling/changeling.dm @@ -103,7 +103,7 @@ if(46 to 90) - var/list/datum/objective/theft = PickObjectiveFromList(GenerateTheft(changeling.assigned_role,changeling)) + var/list/datum/objective/theft = pickweight(GenerateTheft(changeling.assigned_role,changeling)) var/datum/objective/steal/steal_objective = pick(theft) steal_objective.owner = changeling changeling.objectives += steal_objective @@ -120,7 +120,7 @@ kill_objective.find_target() changeling.objectives += kill_objective - var/list/datum/objective/theft = PickObjectiveFromList(GenerateTheft(changeling.assigned_role,changeling)) + var/list/datum/objective/theft = pickweight(GenerateTheft(changeling.assigned_role,changeling)) var/datum/objective/steal/steal_objective = pick(theft) steal_objective.owner = changeling changeling.objectives += steal_objective diff --git a/code/game/gamemodes/newobjective.dm b/code/game/gamemodes/newobjective.dm index 66e71c124a..d3bd4ae403 100644 --- a/code/game/gamemodes/newobjective.dm +++ b/code/game/gamemodes/newobjective.dm @@ -1,79 +1,57 @@ +#define FRAME_PROBABILITY 3 +#define THEFT_PROBABILITY 55 +#define KILL_PROBABILITY 37 +#define PROTECT_PROBABILITY 5 + +#define LENIENT 0 +#define NORMAL 1 +#define HARD 2 +#define IMPOSSIBLE 3 + + /proc/GenerateTheft(var/job,var/datum/mind/traitor) var/list/datum/objective/objectives = list() - var/list/weight = list() - var/index = 1 for(var/o in typesof(/datum/objective/steal)) if(o != /datum/objective/steal) //Make sure not to get a blank steal objective. var/datum/objective/target = new o(null,job) - weight += list("[index]" = target.weight) objectives += target - index++ - return list(objectives, weight) + objectives[target] = target.weight + return objectives /proc/GenerateAssassinate(var/job,var/datum/mind/traitor) var/list/datum/objective/assassinate/missions = list() - var/list/weight = list() - var/index = 1 for(var/datum/mind/target in ticker.minds) if((target != traitor) && istype(target.current, /mob/living/carbon/human)) if(target && target.current) var/datum/objective/target_obj = new /datum/objective/assassinate(null,job,target) - weight += list("[index]" = target_obj.weight) missions += target_obj - index++ - return list(missions, weight) + missions[target_obj] = target_obj.weight + return missions /proc/GenerateFrame(var/job,var/datum/mind/traitor) var/list/datum/objective/frame/missions = list() - var/list/weight = list() - var/index = 1 for(var/datum/mind/target in ticker.minds) if((target != traitor) && istype(target.current, /mob/living/carbon/human)) if(target && target.current) var/datum/objective/target_obj = new /datum/objective/frame(null,job,target) - weight += list("[index]" = target_obj.weight) missions += target_obj - index++ - return list(missions, weight) + missions[target_obj] = target_obj.weight + return missions /proc/GenerateProtection(var/job,var/datum/mind/traitor) var/list/datum/objective/frame/missions = list() - var/list/weight = list() - var/index = 1 for(var/datum/mind/target in ticker.minds) if((target != traitor) && istype(target.current, /mob/living/carbon/human)) if(target && target.current) var/datum/objective/target_obj = new /datum/objective/protection(null,job,target) - weight += list("[index]" = target_obj.weight) missions += target_obj - index++ - return list(missions, weight) + missions[target_obj] = target_obj.weight + return missions -/proc/PickObjectiveFromList(var/list/objectivesArray) - var/list/datum/objectives = objectivesArray[1] - var/pick_index = text2num(pickweight(objectivesArray[2])) - if (pick_index > objectives.len || pick_index < 1) - log_admin("Objective picking failed. Error logged. One or more traitors will need to be manually-assigned objectives. Pick_index was [pick_index]. Tell Sky.") - message_admins("Objective picking failed. Error logged. One or more traitors will need to be manually-assigned objectives. Pick_index was [pick_index]. Tell Sky.") - CRASH("Objective picking failed. Pick_index was [pick_index].") - - return objectives[pick_index] - -/proc/RemoveObjectiveFromList(var/list/objectiveArray, var/datum/objective/objective) - var/list/datum/objective/temp = objectiveArray[1] - var/list/weight = objectiveArray[2] - var/index = temp.Find(objective) - if(index == temp.len) - temp.Cut(index) - weight.Cut(index) - else - temp.Cut(index, index+1) - weight.Cut(index, index+1) - return list(temp,weight) /proc/SelectObjectives(var/job,var/datum/mind/traitor,var/hijack = 0) var/list/chosenobjectives = list() @@ -81,36 +59,131 @@ var/list/killobjectives = GenerateAssassinate(job,traitor) var/list/frameobjectives = GenerateFrame(job,traitor) var/list/protectobjectives = GenerateProtection(job,traitor) - //var/points - var/totalweight - var/selectobj + var/total_weight var/conflict - while(totalweight < 100) - selectobj = rand(1,100) //Randomly determine the type of objective to be given. - if(!length(killobjectives[1]) || !length(protectobjectives[1])|| !length(frameobjectives[1])) //If any of these lists are empty, just give them theft objectives. - var/datum/objective/objective = PickObjectiveFromList(theftobjectives) + var/steal_weight = THEFT_PROBABILITY + var/frame_weight = FRAME_PROBABILITY + var/kill_weight = KILL_PROBABILITY + var/protect_weight = PROTECT_PROBABILITY + var/target_weight = 50 + +///////////////////////////////////////////////////////////// +//HANDLE ASSIGNING OBJECTIVES BASED OFF OF PREVIOUS SUCCESS// +///////////////////////////////////////////////////////////// + + var/savefile/info = new("data/player_saves/[copytext(traitor.key, 1, 2)]/[traitor.key]/traitor.sav") + var/list/infos + info >> infos + if(istype(infos)) + var/total_attempts = infos["Total"] + var/total_overall_success = infos["Success"] + var/success_ratio = total_overall_success/total_attempts + var/steal_success = infos["Steal"] + var/kill_success = infos["Kill"] + var/frame_success = infos["Frame"] + var/protect_success = infos["Protect"] + + var/list/ordered_success = list(steal_success, kill_success, frame_success, protect_success) + + var/difficulty = pick(LENIENT, LENIENT, NORMAL, NORMAL, NORMAL, HARD, HARD, IMPOSSIBLE) + //Highest to lowest in terms of success rate, and resulting weight for later computation + var/success_weights = list(1, 1, 1, 1) + switch(difficulty) + if(LENIENT) + success_weights = list(1.5, 1, 0.75, 0.5) + target_weight = success_ratio*100 + if(NORMAL) + target_weight = success_ratio*150 + if(HARD) + success_weights = list(0.66, 0.8, 1, 1.25) + target_weight = success_ratio*200 + if(IMPOSSIBLE) //YOU SHALL NOT PASS + success_weights = list(0.5, 0.75, 1.2, 2) + target_weight = success_ratio*300 + + for(var/i = 1, i <= 4, i++) + //Iterate through the success rates, and determine the weights to chose based on the highest to + // the lowest to multiply it by the proper success ratio. + var/weight = max(ordered_success) + ordered_success -= weight + if(weight == steal_success) + steal_weight *= steal_success*success_weights[i] + else if(weight == frame_success) + frame_weight *= frame_success*success_weights[i] + else if(weight == protect_success) + protect_weight *= protect_success*success_weights[i] + else if(weight == kill_success) + kill_weight *= kill_success*success_weights[i] + + var/total_weights = kill_weight + protect_weight + frame_weight + steal_weight + frame_weight = round(frame_weight/total_weights) + kill_weight = round(kill_weight/total_weights) + steal_weight = round(steal_weight/total_weights) + //Protect is whatever is left over. + + var/steal_range = steal_weight + var/frame_range = frame_weight + steal_range + var/kill_range = kill_weight + frame_range + //Protect is whatever is left over. + + while(total_weight < target_weight) + var/selectobj = rand(1,100) //Randomly determine the type of objective to be given. + if(!length(killobjectives) || !length(protectobjectives)|| !length(frameobjectives)) //If any of these lists are empty, just give them theft objectives. + var/datum/objective/objective = pickweight(theftobjectives) chosenobjectives += objective - totalweight += objective.points - theftobjectives = RemoveObjectiveFromList(theftobjectives, objective) + total_weight += objective.points + theftobjectives -= objective else switch(selectobj) - if(1 to 55) //Theft Objectives (55% chance) - var/datum/objective/objective = PickObjectiveFromList(theftobjectives) + if(1 to steal_range) + if(!theftobjectives.len) + continue + var/datum/objective/objective = pickweight(theftobjectives) for(1 to 10) - if(objective.points + totalweight <= 100) + if(objective.points + total_weight <= 100 || !theftobjectives.len) break - objective = PickObjectiveFromList(theftobjectives) + theftobjectives -= objective + objective = pickweight(theftobjectives) + if(!objective && !theftobjectives.len) + continue chosenobjectives += objective - totalweight += objective.points - theftobjectives = RemoveObjectiveFromList(theftobjectives, objective) - if(56 to 92) //Assassination Objectives (37% chance) - var/datum/objective/assassinate/objective = PickObjectiveFromList(killobjectives) + total_weight += objective.points + theftobjectives -= objective + if(steal_range + 1 to frame_range) //Framing Objectives (3% chance) + if(!frameobjectives.len) + continue + var/datum/objective/objective = pickweight(frameobjectives) + for(1 to 10) + if(objective.points + total_weight <= 100 || !frameobjectives.len) + break + frameobjectives -= objective + objective = pickweight(frameobjectives) + if(!objective && !frameobjectives.len) + continue + for(var/datum/objective/protection/conflicttest in chosenobjectives) //Check to make sure we aren't telling them to Assassinate somebody they need to Protect. + if(conflicttest.target == objective.target) + conflict = 1 + break + for(var/datum/objective/assassinate/conflicttest in chosenobjectives) //Check to make sure we aren't telling them to Protect somebody they need to Assassinate. + if(conflicttest.target == objective.target) + conflict = 1 + break + if(!conflict) + chosenobjectives += objective + total_weight += objective.points + frameobjectives -= objective + conflict = 0 + if(frame_range + 1 to kill_range) + if(!killobjectives.len) + continue + var/datum/objective/assassinate/objective = pickweight(killobjectives) world << objective for(1 to 10) - if(objective.points + totalweight <= 100) + if(objective.points + total_weight <= 100 || !killobjectives.len) break - objective = PickObjectiveFromList(killobjectives) - if(!objective) + killobjectives -= objective + objective = pickweight(killobjectives) + if(!objective && !killobjectives.len) continue for(var/datum/objective/protection/conflicttest in chosenobjectives) //Check to make sure we aren't telling them to Assassinate somebody they need to Protect. if(conflicttest.target == objective.target) @@ -122,37 +195,19 @@ break if(!conflict) chosenobjectives += objective - totalweight += objective.points - killobjectives = RemoveObjectiveFromList(killobjectives, objective) + total_weight += objective.points + killobjectives -= objective conflict = 0 - if(93 to 95) //Framing Objectives (3% chance) - var/datum/objective/objective = PickObjectiveFromList(frameobjectives) - for(1 to 10) - if(objective.points + totalweight <= 100) - break - objective = PickObjectiveFromList(frameobjectives) - if(!objective) + if(kill_range + 1 to 100) //Protection Objectives (5% chance) + if(!protectobjectives.len) continue - for(var/datum/objective/protection/conflicttest in chosenobjectives) //Check to make sure we aren't telling them to Assassinate somebody they need to Protect. - if(conflicttest.target == objective.target) - conflict = 1 - break - for(var/datum/objective/assassinate/conflicttest in chosenobjectives) //Check to make sure we aren't telling them to Protect somebody they need to Assassinate. - if(conflicttest.target == objective.target) - conflict = 1 - break - if(!conflict) - chosenobjectives += objective - totalweight += objective.points - frameobjectives = RemoveObjectiveFromList(frameobjectives, objective) - conflict = 0 - if(96 to 100) //Protection Objectives (5% chance) - var/datum/objective/protection/objective = PickObjectiveFromList(protectobjectives) + var/datum/objective/protection/objective = pickweight(protectobjectives) for(1 to 10) - if(objective.points + totalweight <= 100) + if(objective.points + total_weight <= 100 || !protectobjectives.len) break - objective = PickObjectiveFromList(protectobjectives) - if(!objective) + protectobjectives -= objective + objective = pickweight(protectobjectives) + if(!objective || !protectobjectives.len) continue for(var/datum/objective/assassinate/conflicttest in chosenobjectives) //Check to make sure we aren't telling them to Protect somebody they need to Assassinate. if(conflicttest.target == objective.target) @@ -164,19 +219,11 @@ break if(!conflict) chosenobjectives += objective - totalweight += objective.points - protectobjectives = RemoveObjectiveFromList(protectobjectives, objective) + total_weight += objective.points + protectobjectives -= objective conflict = 0 - var/hasendgame = 0 - for(var/datum/objective/o in chosenobjectives) - if(o.type == /datum/objective/hijack || o.type == /datum/objective/escape) - hasendgame = 1 - break - for(var/datum/objective/o in chosenobjectives) - if(o.explanation_text == "Free Objective") - del(o) //Cleaning up any sillies. - if(hasendgame == 0) + if(!locate(/datum/objective/hijack) in chosenobjectives && !locate(/datum/objective/escape) in chosenobjectives) if(hijack) chosenobjectives += new /datum/objective/hijack(null,job) else @@ -1401,3 +1448,12 @@ datum/objective/silence if (get_turf(player) in pod4) return 0 return 1 + +#undef FRAME_PROBABILITY +#undef THEFT_PROBABILITY +#undef KILL_PROBABILITY +#undef PROTECT_PROBABILITY +#undef LENIENT +#undef NORMAL +#undef HARD +#undef IMPOSSIBLE \ No newline at end of file diff --git a/code/game/gamemodes/traitor/traitor.dm b/code/game/gamemodes/traitor/traitor.dm index 2747c30b92..2cd4ad9d62 100644 --- a/code/game/gamemodes/traitor/traitor.dm +++ b/code/game/gamemodes/traitor/traitor.dm @@ -177,11 +177,29 @@ if(traitor.objectives.len)//If the traitor had no objectives, don't need to process this. var/traitorwin = 1 var/count = 1 + var/list/success_log = list("Steal-Win" = 0, "Steal-Fail" = 0, "Protect-Win" = 0, "Protect-Fail" = 0,\ + "Frame-Win" = 0, "Frame-Fail" = 0, "Kill-Win" = 0, "Kill-Fail" = 0) for(var/datum/objective/objective in traitor.objectives) if(objective.check_completion()) + if(istype(objective, /datum/objective/frame)) + success_log["Frame-Win"]++ + if(istype(objective, /datum/objective/protection)) + success_log["Protect-Win"]++ + if(istype(objective, /datum/objective/assassinate)) + success_log["Kill-Win"]++ + if(istype(objective, /datum/objective/steal)) + success_log["Steal-Win"]++ world << "Objective #[count]: [objective.explanation_text] \green Success" //feedback_add_details("traitor_objective","[objective.type]|SUCCESS") else + if(istype(objective, /datum/objective/frame)) + success_log["Frame-Fail"]++ + if(istype(objective, /datum/objective/protection)) + success_log["Protect-Fail"]++ + if(istype(objective, /datum/objective/assassinate)) + success_log["Kill-Fail"]++ + if(istype(objective, /datum/objective/steal)) + success_log["Steal-Fail"]++ world << "Objective #[count]: [objective.explanation_text] \red Failed" //feedback_add_details("traitor_objective","[objective.type]|FAIL") traitorwin = 0 @@ -193,6 +211,31 @@ else world << "The [special_role_text] has failed!" //feedback_add_details("traitor_success","FAIL") + var/savefile/traitor_logs = new("data/player_saves/[copytext(traitor.key, 1, 2)]/[traitor.key]/traitor.sav") + var/list/infos + traitor_logs >> infos + if(istype(infos)) + infos["Total"]++ + infos["Success"] += traitorwin + infos["Steal"] = (success_log["Steal-Win"]+success_log["Steal-Fail"]+infos["Steal_Total"]) ? ((infos["Steal"]*infos["Steal_Total"]) + success_log["Steal-Win"])/(success_log["Steal-Win"]+success_log["Steal-Fail"]+infos["Steal_Total"]) : 1 + infos["Kill"] = (success_log["Kill-Win"]+success_log["Kill-Fail"]+infos["Kill_Total"]) ? ((infos["Kill"]*infos["Kill_Total"]) + success_log["Kill-Win"])/(success_log["Kill-Win"]+success_log["Kill-Fail"]+infos["Kill_Total"]) : 1 + infos["Frame"] = (success_log["Frame-Win"]+success_log["Frame-Fail"]+infos["Frame_Total"]) ? ((infos["Frame"]*infos["Frame_Total"]) + success_log["Frame-Win"])/(success_log["Frame-Win"]+success_log["Frame-Fail"]+infos["Frame_Total"]) : 1 + infos["Protect"] = (success_log["Protect-Win"]+success_log["Protect-Fail"]+infos["Protect_Total"]) ? ((infos["Protect"]*infos["Protect_Total"]) + success_log["Protect-Win"])/(success_log["Protect-Win"]+success_log["Protect-Fail"]+infos["Protect_Total"]) : 1 + infos["Steal_Total"] = infos["Steal_Total"]+success_log["Steal-Win"]+success_log["Steal-Fail"] + infos["Kill_Total"] = infos["Kill_Total"]+success_log["Kill-Win"]+success_log["Kill-Fail"] + infos["Frame_Total"] = infos["Frame_Total"]+success_log["Frame-Win"]+success_log["Frame-Fail"] + infos["Protect_Total"] = infos["Protect_Total"]+success_log["Protect-Win"]+success_log["Protect-Fail"] + else + infos = list("Total" = 1, "Success" = traitorwin, + "Steal" = (success_log["Steal-Win"]+success_log["Steal-Fail"]) ? success_log["Steal-Win"]/(success_log["Steal-Win"]+success_log["Steal-Fail"]) : 1, + "Kill" = (success_log["Kill-Win"]+success_log["Kill-Fail"]) ? success_log["Kill-Win"]/(success_log["Kill-Win"]+success_log["Kill-Fail"]) : 1, + "Frame" = (success_log["Frame-Win"]+success_log["Frame-Fail"]) ? success_log["Frame-Win"]/(success_log["Frame-Win"]+success_log["Frame-Fail"]) : 1, + "Protect" = (success_log["Protect-Win"]+success_log["Protect-Fail"]) ? success_log["Protect-Win"]/(success_log["Protect-Win"]+success_log["Protect-Fail"]) : 1, + "Steal_Total" = success_log["Steal-Win"]+success_log["Steal-Fail"], + "Kill_Total" = success_log["Kill-Win"]+success_log["Kill-Fail"], + "Frame_Total" = success_log["Frame-Win"]+success_log["Frame-Fail"], + "Protect_Total" = success_log["Protect-Win"]+success_log["Protect-Fail"]) + traitor_logs << infos var/datum/traitorinfo/info = logtraitors[traitor] if (info)