diff --git a/.gitignore b/.gitignore index 3b85a6ec3040..b1cb02811cb0 100644 --- a/.gitignore +++ b/.gitignore @@ -13,7 +13,6 @@ *.lk *.int *.backup -*.int ### https://raw.github.com/github/gitignore/cc542de017c606138a87ee4880e5f06b3a306def/Global/Linux.gitignore *~ @@ -127,6 +126,9 @@ celerybeat-schedule venv/ ENV/ +# IntelliJ IDEA / PyCharm (with plugin) +.idea + # Spyder project settings .spyderproject diff --git a/code/controllers/configuration/entries/game_options.dm b/code/controllers/configuration/entries/game_options.dm index 1b6e30c12cfa..6f8e630ffb95 100644 --- a/code/controllers/configuration/entries/game_options.dm +++ b/code/controllers/configuration/entries/game_options.dm @@ -92,6 +92,20 @@ /datum/config_entry/flag/allow_latejoin_antagonists // If late-joining players can be traitor/changeling +/datum/config_entry/flag/use_antag_rep // see game_options.txt for details + +/datum/config_entry/number/antag_rep_maximum + config_entry_value = 200 + min_val = 0 + +/datum/config_entry/number/default_antag_tickets + config_entry_value = 100 + min_val = 0 + +/datum/config_entry/number/max_tickets_per_roll + config_entry_value = 100 + min_val = 0 + /datum/config_entry/number/midround_antag_time_check // How late (in minutes you want the midround antag system to stay on, setting this to 0 will disable the system) config_entry_value = 60 min_val = 0 diff --git a/code/controllers/subsystem/job.dm b/code/controllers/subsystem/job.dm index 4e185300c242..65544c377b41 100644 --- a/code/controllers/subsystem/job.dm +++ b/code/controllers/subsystem/job.dm @@ -402,6 +402,8 @@ SUBSYSTEM_DEF(job) else M = H + SSpersistence.antag_rep_change[M.client.ckey] += job.antag_rep + to_chat(M, "You are the [rank].") to_chat(M, "As the [rank] you answer directly to [job.supervisors]. Special circumstances may change this.") to_chat(M, "To speak on your departments radio, use the :h button. To see others, look closely at your headset.") diff --git a/code/controllers/subsystem/persistence.dm b/code/controllers/subsystem/persistence.dm index b46a55c4d164..0500de33b6f5 100644 --- a/code/controllers/subsystem/persistence.dm +++ b/code/controllers/subsystem/persistence.dm @@ -1,3 +1,5 @@ +#define FILE_ANTAG_REP "data/AntagReputation.json" + SUBSYSTEM_DEF(persistence) name = "Persistence" init_order = INIT_ORDER_PERSISTENCE @@ -11,6 +13,8 @@ SUBSYSTEM_DEF(persistence) var/list/saved_modes = list(1,2,3) var/list/saved_trophies = list() var/list/spawned_objects = list() + var/list/antag_rep = list() + var/list/antag_rep_change = list() /datum/controller/subsystem/persistence/Initialize() LoadSatchels() @@ -18,6 +22,8 @@ SUBSYSTEM_DEF(persistence) LoadChiselMessages() LoadTrophies() LoadRecentModes() + if(CONFIG_GET(flag/use_antag_rep)) + LoadAntagReputation() ..() /datum/controller/subsystem/persistence/proc/LoadSatchels() @@ -152,6 +158,15 @@ SUBSYSTEM_DEF(persistence) return saved_modes = json["data"] +/datum/controller/subsystem/persistence/proc/LoadAntagReputation() + var/json = file2text(FILE_ANTAG_REP) + if(!json) + var/json_file = file(FILE_ANTAG_REP) + if(!fexists(json_file)) + WARNING("Failed to load antag reputation. File likely corrupt.") + return + return + antag_rep = json_decode(json) /datum/controller/subsystem/persistence/proc/SetUpTrophies(list/trophy_items) for(var/A in GLOB.trophy_cases) @@ -183,6 +198,8 @@ SUBSYSTEM_DEF(persistence) CollectSecretSatchels() CollectTrophies() CollectRoundtype() + if(CONFIG_GET(flag/use_antag_rep)) + CollectAntagReputation() /datum/controller/subsystem/persistence/proc/CollectSecretSatchels() satchel_blacklist = typecacheof(list(/obj/item/stack/tile/plasteel, /obj/item/crowbar)) @@ -253,3 +270,18 @@ SUBSYSTEM_DEF(persistence) file_data["data"] = saved_modes fdel(json_file) WRITE_FILE(json_file, json_encode(file_data)) + +/datum/controller/subsystem/persistence/proc/CollectAntagReputation() + var/ANTAG_REP_MAXIMUM = CONFIG_GET(number/antag_rep_maximum) + + for(var/p_ckey in antag_rep_change) +// var/start = antag_rep[p_ckey] + antag_rep[p_ckey] = max(0, min(antag_rep[p_ckey]+antag_rep_change[p_ckey], ANTAG_REP_MAXIMUM)) + +// WARNING("AR_DEBUG: [p_ckey]: Committed [antag_rep_change[p_ckey]] reputation, going from [start] to [antag_rep[p_ckey]]") + + antag_rep_change = list() + + fdel(FILE_ANTAG_REP) + text2file(json_encode(antag_rep), FILE_ANTAG_REP) + diff --git a/code/game/gamemodes/brother/traitor_bro.dm b/code/game/gamemodes/brother/traitor_bro.dm index 2143bba3383b..41b583852d2b 100644 --- a/code/game/gamemodes/brother/traitor_bro.dm +++ b/code/game/gamemodes/brother/traitor_bro.dm @@ -37,7 +37,7 @@ var/datum/team/brother_team/team = new var/team_size = prob(10) ? min(3, possible_brothers.len) : 2 for(var/k = 1 to team_size) - var/datum/mind/bro = pick(possible_brothers) + var/datum/mind/bro = antag_pick(possible_brothers) possible_brothers -= bro antag_candidates -= bro team.add_member(bro) diff --git a/code/game/gamemodes/changeling/changeling.dm b/code/game/gamemodes/changeling/changeling.dm index 1f95688fa364..a77bf196c292 100644 --- a/code/game/gamemodes/changeling/changeling.dm +++ b/code/game/gamemodes/changeling/changeling.dm @@ -45,7 +45,7 @@ GLOBAL_VAR(changeling_team_objective_type) //If this is not null, we hand our th for(var/i = 0, i < num_changelings, i++) if(!antag_candidates.len) break - var/datum/mind/changeling = pick(antag_candidates) + var/datum/mind/changeling = antag_pick(antag_candidates) antag_candidates -= changeling changelings += changeling changeling.special_role = ROLE_CHANGELING diff --git a/code/game/gamemodes/changeling/traitor_chan.dm b/code/game/gamemodes/changeling/traitor_chan.dm index e59cf40ca440..d2f5accea41b 100644 --- a/code/game/gamemodes/changeling/traitor_chan.dm +++ b/code/game/gamemodes/changeling/traitor_chan.dm @@ -46,7 +46,7 @@ for(var/j = 0, j < num_changelings, j++) if(!possible_changelings.len) break - var/datum/mind/changeling = pick(possible_changelings) + var/datum/mind/changeling = antag_pick(possible_changelings) antag_candidates -= changeling possible_changelings -= changeling changeling.special_role = ROLE_CHANGELING diff --git a/code/game/gamemodes/clock_cult/clock_cult.dm b/code/game/gamemodes/clock_cult/clock_cult.dm index 730c8bff7742..bd6a8bf77d73 100644 --- a/code/game/gamemodes/clock_cult/clock_cult.dm +++ b/code/game/gamemodes/clock_cult/clock_cult.dm @@ -155,7 +155,7 @@ Credit where due: starter_servants += round(number_players / 10) starter_servants = min(starter_servants, 8) //max 8 servants (that sould only happen with a ton of players) while(starter_servants) - var/datum/mind/servant = pick(antag_candidates) + var/datum/mind/servant = antag_pick(antag_candidates) servants_to_serve += servant antag_candidates -= servant servant.assigned_role = ROLE_SERVANT_OF_RATVAR diff --git a/code/game/gamemodes/cult/cult.dm b/code/game/gamemodes/cult/cult.dm index fde8a16b13c3..d343bb35ab70 100644 --- a/code/game/gamemodes/cult/cult.dm +++ b/code/game/gamemodes/cult/cult.dm @@ -74,7 +74,7 @@ for(var/cultists_number = 1 to recommended_enemies) if(!antag_candidates.len) break - var/datum/mind/cultist = pick(antag_candidates) + var/datum/mind/cultist = antag_pick(antag_candidates) antag_candidates -= cultist cultists_to_cult += cultist cultist.special_role = ROLE_CULTIST diff --git a/code/game/gamemodes/devil/devil_game_mode.dm b/code/game/gamemodes/devil/devil_game_mode.dm index f25ba6c6b6cc..3007164465d6 100644 --- a/code/game/gamemodes/devil/devil_game_mode.dm +++ b/code/game/gamemodes/devil/devil_game_mode.dm @@ -36,7 +36,7 @@ for(var/j = 0, j < num_devils, j++) if (!antag_candidates.len) break - var/datum/mind/devil = pick(antag_candidates) + var/datum/mind/devil = antag_pick(antag_candidates) devils += devil devil.special_role = traitor_name devil.restricted_roles = restricted_jobs diff --git a/code/game/gamemodes/game_mode.dm b/code/game/gamemodes/game_mode.dm index 68f2b383ae49..50ad92d44b63 100644 --- a/code/game/gamemodes/game_mode.dm +++ b/code/game/gamemodes/game_mode.dm @@ -283,6 +283,61 @@ set_security_level(SEC_LEVEL_BLUE) +// This is a frequency selection system. You may imagine it like a raffle where each player can have some number of tickets. The more tickets you have the more likely you are to +// "win". The default is 100 tickets. If no players use any extra tickets (earned with the antagonist rep system) calling this function should be equivalent to calling the normal +// pick() function. By default you may use up to 100 extra tickets per roll, meaning at maximum a player may double their chances compared to a player who has no extra tickets. +// +// The odds of being picked are simply (your_tickets / total_tickets). Suppose you have one player using fifty (50) extra tickets, and one who uses no extra: +// Player A: 150 tickets +// Player B: 100 tickets +// Total: 250 tickets +// +// The odds become: +// Player A: 150 / 250 = 0.6 = 60% +// Player B: 100 / 250 = 0.4 = 40% +/datum/game_mode/proc/antag_pick(list/datum/candidates) + if(!CONFIG_GET(flag/use_antag_rep)) // || candidates.len <= 1) + return pick(candidates) + + // Tickets start at 100 + var/DEFAULT_ANTAG_TICKETS = CONFIG_GET(number/default_antag_tickets) + + // You may use up to 100 extra tickets (double your odds) + var/MAX_TICKETS_PER_ROLL = CONFIG_GET(number/max_tickets_per_roll) + + + var/total_tickets = 0 + + MAX_TICKETS_PER_ROLL += DEFAULT_ANTAG_TICKETS + + var/p_ckey + var/p_rep + + for(var/datum/mind/mind in candidates) + p_ckey = ckey(mind.key) + total_tickets += min(SSpersistence.antag_rep[p_ckey] + DEFAULT_ANTAG_TICKETS, MAX_TICKETS_PER_ROLL) + + var/antag_select = rand(1,total_tickets) + var/current = 1 + + for(var/datum/mind/mind in candidates) + p_ckey = ckey(mind.key) + p_rep = SSpersistence.antag_rep[p_ckey] + p_rep = p_rep == null ? 0 : p_rep + + if(current <= antag_select) + var/subtract = min(p_rep + DEFAULT_ANTAG_TICKETS, MAX_TICKETS_PER_ROLL) - DEFAULT_ANTAG_TICKETS + SSpersistence.antag_rep_change[p_ckey] = -subtract + +// WARNING("AR_DEBUG: Player [mind.key] won spending [subtract] tickets from starting value [SSpersistence.antag_rep[p_ckey]]") + + return mind + + current += min(p_rep + DEFAULT_ANTAG_TICKETS, MAX_TICKETS_PER_ROLL) + + WARNING("Something has gone terribly wrong. /datum/game_mode/proc/antag_pick failed to select a candidate. Falling back to pick()") + return pick(candidates) + /datum/game_mode/proc/get_players_for_role(role) var/list/players = list() var/list/candidates = list() @@ -382,19 +437,29 @@ if(L.ckey && L.client) + var/failed = FALSE if(L.client.inactivity >= (ROUNDSTART_LOGOUT_REPORT_TIME / 2)) //Connected, but inactive (alt+tabbed or something) msg += "[L.name] ([L.ckey]), the [L.job] (Connected, Inactive)\n" - continue //AFK client - if(L.stat) + failed = TRUE //AFK client + if(!failed && L.stat) if(L.suiciding) //Suicider msg += "[L.name] ([L.ckey]), the [L.job] (Suicide)\n" - continue //Disconnected client - if(L.stat == UNCONSCIOUS) + failed = TRUE //Disconnected client + if(!failed && L.stat == UNCONSCIOUS) msg += "[L.name] ([L.ckey]), the [L.job] (Dying)\n" - continue //Unconscious - if(L.stat == DEAD) + failed = TRUE //Unconscious + if(!failed && L.stat == DEAD) msg += "[L.name] ([L.ckey]), the [L.job] (Dead)\n" - continue //Dead + failed = TRUE //Dead + + var/p_ckey = L.client.ckey +// WARNING("AR_DEBUG: [p_ckey]: failed - [failed], antag_rep_change: [SSpersistence.antag_rep_change[p_ckey]]") + + // people who died or left should not gain any reputation + // people who rolled antagonist still lose it + if(failed && SSpersistence.antag_rep_change[p_ckey] > 0) +// WARNING("AR_DEBUG: Zeroed [p_ckey]'s antag_rep_change") + SSpersistence.antag_rep_change[p_ckey] = 0 continue //Happy connected client for(var/mob/dead/observer/D in GLOB.dead_mob_list) @@ -477,4 +542,4 @@ if(EMERGENCY_ESCAPED_OR_ENDGAMED) SSticker.news_report = STATION_EVACUATED if(SSshuttle.emergency.is_hijacked()) - SSticker.news_report = SHUTTLE_HIJACK \ No newline at end of file + SSticker.news_report = SHUTTLE_HIJACK diff --git a/code/game/gamemodes/revolution/revolution.dm b/code/game/gamemodes/revolution/revolution.dm index 45f85719d348..1553ee811f48 100644 --- a/code/game/gamemodes/revolution/revolution.dm +++ b/code/game/gamemodes/revolution/revolution.dm @@ -52,7 +52,7 @@ for (var/i=1 to max_headrevs) if (antag_candidates.len==0) break - var/datum/mind/lenin = pick(antag_candidates) + var/datum/mind/lenin = antag_pick(antag_candidates) antag_candidates -= lenin headrev_candidates += lenin lenin.restricted_roles = restricted_jobs diff --git a/code/game/gamemodes/traitor/traitor.dm b/code/game/gamemodes/traitor/traitor.dm index 7409faa706e2..80ce90722b0a 100644 --- a/code/game/gamemodes/traitor/traitor.dm +++ b/code/game/gamemodes/traitor/traitor.dm @@ -49,7 +49,7 @@ for(var/j = 0, j < num_traitors, j++) if (!antag_candidates.len) break - var/datum/mind/traitor = pick(antag_candidates) + var/datum/mind/traitor = antag_pick(antag_candidates) pre_traitors += traitor traitor.special_role = traitor_name traitor.restricted_roles = restricted_jobs @@ -100,4 +100,4 @@ /datum/game_mode/proc/update_traitor_icons_removed(datum/mind/traitor_mind) var/datum/atom_hud/antag/traitorhud = GLOB.huds[ANTAG_HUD_TRAITOR] traitorhud.leave_hud(traitor_mind.current) - set_antag_hud(traitor_mind.current, null) \ No newline at end of file + set_antag_hud(traitor_mind.current, null) diff --git a/code/game/gamemodes/wizard/wizard.dm b/code/game/gamemodes/wizard/wizard.dm index dd8dad331f44..8a6a7b7903d9 100644 --- a/code/game/gamemodes/wizard/wizard.dm +++ b/code/game/gamemodes/wizard/wizard.dm @@ -19,7 +19,7 @@ var/finished = 0 /datum/game_mode/wizard/pre_setup() - var/datum/mind/wizard = pick(antag_candidates) + var/datum/mind/wizard = antag_pick(antag_candidates) wizards += wizard wizard.assigned_role = ROLE_WIZARD wizard.special_role = ROLE_WIZARD diff --git a/code/modules/admin/admin.dm b/code/modules/admin/admin.dm index 61ec6316d57b..364f1a763361 100644 --- a/code/modules/admin/admin.dm +++ b/code/modules/admin/admin.dm @@ -44,6 +44,13 @@ body += "

Show related accounts by: " body += "\[ CID | " body += "IP \]" + var/rep = 0 + rep += SSpersistence.antag_rep[M.ckey] + body += "

Antagonist reputation: [rep]" + body += "
\[increase\] " + body += "\[decrease\] " + body += "\[set\] " + body += "\[zero\]" body += "

\[ " diff --git a/code/modules/admin/topic.dm b/code/modules/admin/topic.dm index f4b614e7bba3..3ef790a359b1 100644 --- a/code/modules/admin/topic.dm +++ b/code/modules/admin/topic.dm @@ -2405,6 +2405,15 @@ usr << browse(dat.Join("
"), "window=related_[C];size=420x300") + else if(href_list["modantagrep"]) + if(!check_rights(R_ADMIN)) + return + + var/mob/M = locate(href_list["mob"]) in GLOB.mob_list + var/client/C = M.client + usr.client.cmd_admin_mod_antag_rep(C, href_list["modantagrep"]) + show_player_panel(M) + /datum/admins/proc/HandleCMode() if(!check_rights(R_ADMIN)) return diff --git a/code/modules/admin/verbs/randomverbs.dm b/code/modules/admin/verbs/randomverbs.dm index bbe7c97bbf6c..eea838b4e8b1 100644 --- a/code/modules/admin/verbs/randomverbs.dm +++ b/code/modules/admin/verbs/randomverbs.dm @@ -47,6 +47,52 @@ admin_ticket_log(M, msg) SSblackbox.record_feedback("tally", "admin_verb", 1, "Subtle Message") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc! +/client/proc/cmd_admin_mod_antag_rep(client/C in GLOB.clients, var/operation) + set category = "Special Verbs" + set name = "Modify Antagonist Reputation" + + if(!check_rights(R_ADMIN)) + return + + var/msg = "" + var/log_text = "" + + if(operation == "zero") + log_text = "Set to 0" + SSpersistence.antag_rep -= C.ckey + else + var/prompt = "Please enter the amount of reputation to [operation]:" + + if(operation == "set") + prompt = "Please enter the new reputation value:" + + msg = input("Message:", prompt) as num + + if (!msg) + return + + var/ANTAG_REP_MAXIMUM = CONFIG_GET(number/antag_rep_maximum) + + if(operation == "set") + log_text = "Set to [num2text(msg)]" + SSpersistence.antag_rep[C.ckey] = max(0, min(msg, ANTAG_REP_MAXIMUM)) + else if(operation == "add") + log_text = "Added [num2text(msg)]" + SSpersistence.antag_rep[C.ckey] = min(SSpersistence.antag_rep[C.ckey]+msg, ANTAG_REP_MAXIMUM) + else if(operation == "subtract") + log_text = "Subtracted [num2text(msg)]" + SSpersistence.antag_rep[C.ckey] = max(SSpersistence.antag_rep[C.ckey]-msg, 0) + else + to_chat(src, "Invalid operation for antag rep modification: [operation] by user [key_name(usr)]") + return + + if(SSpersistence.antag_rep[C.ckey] <= 0) + SSpersistence.antag_rep -= C.ckey + + log_admin("[key_name(usr)]: Modified [key_name(C)]'s antagonist reputation [log_text]") + message_admins("[key_name_admin(usr)]: Modified [key_name(C)]'s antagonist reputation ([log_text])") + SSblackbox.record_feedback("tally", "admin_verb", 1, "Modify Antagonist Reputation") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc! + /client/proc/cmd_admin_world_narrate() set category = "Special Verbs" set name = "Global Narrate" diff --git a/code/modules/jobs/job_types/captain.dm b/code/modules/jobs/job_types/captain.dm index 38418e9916dd..aede0bef8740 100755 --- a/code/modules/jobs/job_types/captain.dm +++ b/code/modules/jobs/job_types/captain.dm @@ -15,6 +15,7 @@ Captain minimal_player_age = 14 exp_requirements = 180 exp_type = EXP_TYPE_CREW + antag_rep = 20 outfit = /datum/outfit/job/captain @@ -69,6 +70,7 @@ Head of Personnel exp_requirements = 180 exp_type = EXP_TYPE_CREW exp_type_department = EXP_TYPE_SUPPLY + antag_rep = 16 outfit = /datum/outfit/job/hop diff --git a/code/modules/jobs/job_types/cargo_service.dm b/code/modules/jobs/job_types/cargo_service.dm index c74fbd3b1bf5..9c6c6f566dd9 100644 --- a/code/modules/jobs/job_types/cargo_service.dm +++ b/code/modules/jobs/job_types/cargo_service.dm @@ -11,6 +11,7 @@ Quartermaster spawn_positions = 1 supervisors = "the head of personnel" selection_color = "#d7b088" + antag_rep = 12 outfit = /datum/outfit/job/quartermaster @@ -41,6 +42,7 @@ Cargo Technician spawn_positions = 2 supervisors = "the quartermaster and the head of personnel" selection_color = "#dcba97" + antag_rep = 4 outfit = /datum/outfit/job/cargo_tech @@ -69,6 +71,7 @@ Shaft Miner spawn_positions = 3 supervisors = "the quartermaster and the head of personnel" selection_color = "#dcba97" + antag_rep = 8 outfit = /datum/outfit/job/miner @@ -147,6 +150,7 @@ Bartender spawn_positions = 1 supervisors = "the head of personnel" selection_color = "#bbe291" + antag_rep = 4 outfit = /datum/outfit/job/bartender @@ -180,6 +184,7 @@ Cook supervisors = "the head of personnel" selection_color = "#bbe291" var/cooks = 0 //Counts cooks amount + antag_rep = 8 outfit = /datum/outfit/job/cook @@ -232,6 +237,7 @@ Botanist spawn_positions = 2 supervisors = "the head of personnel" selection_color = "#bbe291" + antag_rep = 8 outfit = /datum/outfit/job/botanist @@ -271,6 +277,7 @@ Janitor supervisors = "the head of personnel" selection_color = "#bbe291" var/global/janitors = 0 + antag_rep = 8 outfit = /datum/outfit/job/janitor diff --git a/code/modules/jobs/job_types/civilian.dm b/code/modules/jobs/job_types/civilian.dm index 9a2030d7ed20..a10c15e53f6e 100644 --- a/code/modules/jobs/job_types/civilian.dm +++ b/code/modules/jobs/job_types/civilian.dm @@ -11,6 +11,7 @@ Clown spawn_positions = 1 supervisors = "the head of personnel" selection_color = "#dddddd" + antag_rep = 4 outfit = /datum/outfit/job/clown @@ -72,6 +73,7 @@ Mime spawn_positions = 1 supervisors = "the head of personnel" selection_color = "#dddddd" + antag_rep = 4 outfit = /datum/outfit/job/mime @@ -122,6 +124,7 @@ Curator spawn_positions = 1 supervisors = "the head of personnel" selection_color = "#dddddd" + antag_rep = 4 outfit = /datum/outfit/job/curator @@ -167,6 +170,7 @@ Lawyer supervisors = "the head of personnel" selection_color = "#dddddd" var/lawyers = 0 //Counts lawyer amount + antag_rep = 8 outfit = /datum/outfit/job/lawyer diff --git a/code/modules/jobs/job_types/civilian_chaplain.dm b/code/modules/jobs/job_types/civilian_chaplain.dm index 6b119c19d7b2..00685454b03c 100644 --- a/code/modules/jobs/job_types/civilian_chaplain.dm +++ b/code/modules/jobs/job_types/civilian_chaplain.dm @@ -12,6 +12,7 @@ Chaplain spawn_positions = 1 supervisors = "the head of personnel" selection_color = "#dddddd" + antag_rep = 4 outfit = /datum/outfit/job/chaplain diff --git a/code/modules/jobs/job_types/engineering.dm b/code/modules/jobs/job_types/engineering.dm index 1b1619cc24b7..064422bfbaee 100644 --- a/code/modules/jobs/job_types/engineering.dm +++ b/code/modules/jobs/job_types/engineering.dm @@ -17,6 +17,7 @@ Chief Engineer exp_requirements = 180 exp_type = EXP_TYPE_CREW exp_type_department = EXP_TYPE_ENGINEERING + antag_rep = 16 outfit = /datum/outfit/job/ce @@ -76,6 +77,7 @@ Station Engineer selection_color = "#fff5cc" exp_requirements = 60 exp_type = EXP_TYPE_CREW + antag_rep = 8 outfit = /datum/outfit/job/engineer @@ -132,6 +134,7 @@ Atmospheric Technician selection_color = "#fff5cc" exp_requirements = 60 exp_type = EXP_TYPE_CREW + antag_rep = 8 outfit = /datum/outfit/job/atmos diff --git a/code/modules/jobs/job_types/job.dm b/code/modules/jobs/job_types/job.dm index 70854d020b97..077759e8b10d 100644 --- a/code/modules/jobs/job_types/job.dm +++ b/code/modules/jobs/job_types/job.dm @@ -48,6 +48,9 @@ var/exp_type = "" var/exp_type_department = "" + //The amount of good boy points playing this role will earn you towards a higher chance to roll antagonist next round + var/antag_rep = 0 + //Only override this proc //H is usually a human unless an /equip override transformed it /datum/job/proc/after_spawn(mob/living/H, mob/M) diff --git a/code/modules/jobs/job_types/medical.dm b/code/modules/jobs/job_types/medical.dm index 1f2df19f644e..4da656868336 100644 --- a/code/modules/jobs/job_types/medical.dm +++ b/code/modules/jobs/job_types/medical.dm @@ -17,6 +17,7 @@ Chief Medical Officer exp_requirements = 180 exp_type = EXP_TYPE_CREW exp_type_department = EXP_TYPE_MEDICAL + antag_rep = 16 outfit = /datum/outfit/job/cmo @@ -59,6 +60,7 @@ Medical Doctor spawn_positions = 3 supervisors = "the chief medical officer" selection_color = "#ffeef0" + antag_rep = 8 outfit = /datum/outfit/job/doctor @@ -96,6 +98,7 @@ Chemist selection_color = "#ffeef0" exp_type = EXP_TYPE_CREW exp_requirements = 60 + antag_rep = 8 outfit = /datum/outfit/job/chemist @@ -131,6 +134,7 @@ Geneticist selection_color = "#ffeef0" exp_type = EXP_TYPE_CREW exp_requirements = 60 + antag_rep = 8 outfit = /datum/outfit/job/geneticist @@ -167,6 +171,7 @@ Virologist selection_color = "#ffeef0" exp_type = EXP_TYPE_CREW exp_requirements = 60 + antag_rep = 8 outfit = /datum/outfit/job/virologist diff --git a/code/modules/jobs/job_types/science.dm b/code/modules/jobs/job_types/science.dm index d8579a37b091..4fb13472087b 100644 --- a/code/modules/jobs/job_types/science.dm +++ b/code/modules/jobs/job_types/science.dm @@ -17,6 +17,7 @@ Research Director exp_type_department = EXP_TYPE_SCIENCE exp_requirements = 180 exp_type = EXP_TYPE_CREW + antag_rep = 16 outfit = /datum/outfit/job/rd @@ -72,6 +73,7 @@ Scientist selection_color = "#ffeeff" exp_requirements = 60 exp_type = EXP_TYPE_CREW + antag_rep = 8 outfit = /datum/outfit/job/scientist @@ -106,6 +108,7 @@ Roboticist selection_color = "#ffeeff" exp_requirements = 60 exp_type = EXP_TYPE_CREW + antag_rep = 8 outfit = /datum/outfit/job/roboticist diff --git a/code/modules/jobs/job_types/security.dm b/code/modules/jobs/job_types/security.dm index 442b75c972f6..322922a779ef 100644 --- a/code/modules/jobs/job_types/security.dm +++ b/code/modules/jobs/job_types/security.dm @@ -23,6 +23,7 @@ Head of Security exp_requirements = 300 exp_type = EXP_TYPE_CREW exp_type_department = EXP_TYPE_SECURITY + antag_rep = 20 outfit = /datum/outfit/job/hos @@ -76,6 +77,7 @@ Warden minimal_player_age = 7 exp_requirements = 300 exp_type = EXP_TYPE_CREW + antag_rep = 16 outfit = /datum/outfit/job/warden @@ -128,6 +130,7 @@ Detective minimal_player_age = 7 exp_requirements = 300 exp_type = EXP_TYPE_CREW + antag_rep = 12 outfit = /datum/outfit/job/detective @@ -178,6 +181,7 @@ Security Officer minimal_player_age = 7 exp_requirements = 300 exp_type = EXP_TYPE_CREW + antag_rep = 12 outfit = /datum/outfit/job/security diff --git a/code/modules/jobs/job_types/silicon.dm b/code/modules/jobs/job_types/silicon.dm index 4a4893e93d5a..0860c0811361 100644 --- a/code/modules/jobs/job_types/silicon.dm +++ b/code/modules/jobs/job_types/silicon.dm @@ -14,6 +14,7 @@ AI minimal_player_age = 30 exp_requirements = 180 exp_type = EXP_TYPE_CREW + antag_rep = 12 /datum/job/ai/equip(mob/living/carbon/human/H) return H.AIize(FALSE) @@ -52,4 +53,4 @@ Cyborg /datum/job/cyborg/after_spawn(mob/living/silicon/robot/R, mob/M) if(CONFIG_GET(flag/rename_cyborg)) //name can't be set in robot/New without the client - R.rename_self("cyborg", M.client) \ No newline at end of file + R.rename_self("cyborg", M.client) diff --git a/config/config.txt b/config/config.txt index 9f793a0286b0..f9dc54a0d7f9 100644 --- a/config/config.txt +++ b/config/config.txt @@ -71,7 +71,6 @@ ENABLE_LOCALHOST_RANK ## Allows admins to bypass job playtime requirements. #USE_EXP_RESTRICTIONS_ADMIN_BYPASS - ## log OOC channel LOG_OOC diff --git a/config/game_options.txt b/config/game_options.txt index 758f1df89839..7b53f1459fa1 100644 --- a/config/game_options.txt +++ b/config/game_options.txt @@ -223,6 +223,21 @@ BROTHER_OBJECTIVES_AMOUNT 2 ## If late-joining players have a chance to become a traitor/changeling ALLOW_LATEJOIN_ANTAGONISTS +## Comment this out to disable the antagonist reputation system. This system rewards players who participate in the game instead of greytiding by giving them slightly higher odds to +## roll antagonist in subsequent rounds until they get it. +## +## For details See the comments for /datum/game_mode/proc/antag_pick in code/game/gamemodes/game_mode.dm +# USE_ANTAG_REP + +## The maximum amount of antagonist reputation tickets a player can bank (not use at once) +ANTAG_REP_MAXIMUM 200 + +## The default amount of tickets all users use while rolling +DEFAULT_ANTAG_TICKETS 100 + +## The maximum amount of extra tickets a user may use from their ticket bank in addition to the default tickets +MAX_TICKETS_PER_ROLL 100 + ## Uncomment to allow players to see the set odds of different rounds in secret/random in the get server revision screen. This will NOT tell the current roundtype. #SHOW_GAME_TYPE_ODDS