From 4e8691b6be66368c31c1961a211b54f11f278bcd Mon Sep 17 00:00:00 2001 From: SkyratBot <59378654+SkyratBot@users.noreply.github.com> Date: Fri, 29 Jul 2022 19:55:08 +0200 Subject: [PATCH] [MIRROR] Nuke Ops Leader update [MDB IGNORE] (#15275) * Nuke Ops Leader update (#68830) makes the nuke op player with the most nuke ops playtime the leader makes the leader start with loud mode on on their radio idea for that second one from BeeStation/BeeStation-Hornet#6631 making the most playtime nuke op the leader prevents 1st time players from rolling it, they will generally be more competent, and able to be entrusted, just like you can trust a head of staff more. a player with more competency will also probably be better at actually leading and not just clicking a button to open the ship, if they try. the radio is a tiny change to make the leader matter more, and able to give better leadership, because im pretty sure most people dont even realize the leader has access to loud mode * Nuke Ops Leader update Co-authored-by: Fikou <23585223+Fikou@users.noreply.github.com> --- .../dynamic/dynamic_rulesets_midround.dm | 30 ++++++++++++------- .../dynamic/dynamic_rulesets_roundstart.dm | 15 ++++++---- .../antagonists/_common/antag_helpers.dm | 28 +++++++++++++++++ code/modules/antagonists/nukeop/nukeop.dm | 17 ++++------- code/modules/antagonists/nukeop/outfits.dm | 27 +++++++++-------- code/modules/mob/mob_helpers.dm | 12 ++++++++ 6 files changed, 89 insertions(+), 40 deletions(-) diff --git a/code/game/gamemodes/dynamic/dynamic_rulesets_midround.dm b/code/game/gamemodes/dynamic/dynamic_rulesets_midround.dm index 0eaf01665be..2a9aa501730 100644 --- a/code/game/gamemodes/dynamic/dynamic_rulesets_midround.dm +++ b/code/game/gamemodes/dynamic/dynamic_rulesets_midround.dm @@ -157,18 +157,22 @@ else // Not dead? Disregard them, pick a new applicant i-- continue - if(!applicant) i-- continue - - var/mob/new_character = applicant - - if (makeBody) - new_character = generate_ruleset_body(applicant) - - finish_setup(new_character, i) assigned += applicant + finish_applications() + +/// Here the accepted applications get generated bodies and their setup is finished. +/// Called by review_applications() +/datum/dynamic_ruleset/midround/from_ghosts/proc/finish_applications() + var/i = 0 + for(var/mob/applicant as anything in assigned) + i++ + var/mob/new_character = applicant + if(makeBody) + new_character = generate_ruleset_body(applicant) + finish_setup(new_character, i) notify_ghosts("[applicant.name] has been picked for the ruleset [name]!", source = new_character, action = NOTIFY_ORBIT, header="Something Interesting!") /datum/dynamic_ruleset/midround/from_ghosts/proc/generate_ruleset_body(mob/applicant) @@ -382,6 +386,7 @@ requirements = REQUIREMENTS_VERY_HIGH_THREAT_NEEDED var/list/operative_cap = list(2,2,3,3,4,5,5,5,5,5) var/datum/team/nuclear/nuke_team + var/mob/leader flags = HIGH_IMPACT_RULESET /datum/dynamic_ruleset/midround/from_ghosts/nuclear/acceptable(population=0, threat=0) @@ -396,11 +401,16 @@ return FALSE return ..() +/datum/dynamic_ruleset/midround/from_ghosts/nuclear/finish_applications() + leader = get_most_experienced(assigned, ROLE_NUCLEAR_OPERATIVE) + return ..() + /datum/dynamic_ruleset/midround/from_ghosts/nuclear/finish_setup(mob/new_character, index) new_character.mind.set_assigned_role(SSjob.GetJobType(/datum/job/nuclear_operative)) new_character.mind.special_role = ROLE_NUCLEAR_OPERATIVE - if (index == 1) // Our first guy is the leader - var/datum/antagonist/nukeop/leader/new_role = new + if(new_character.mind == leader) + leader = null + var/datum/antagonist/nukeop/leader/new_role = new() nuke_team = new_role.nuke_team new_character.mind.add_antag_datum(new_role) else diff --git a/code/game/gamemodes/dynamic/dynamic_rulesets_roundstart.dm b/code/game/gamemodes/dynamic/dynamic_rulesets_roundstart.dm index 3e47a2f2083..fcf61b0be2f 100644 --- a/code/game/gamemodes/dynamic/dynamic_rulesets_roundstart.dm +++ b/code/game/gamemodes/dynamic/dynamic_rulesets_roundstart.dm @@ -390,6 +390,7 @@ requirements = list(90,90,90,80,60,40,30,20,10,10) flags = HIGH_IMPACT_RULESET antag_cap = list("denominator" = 18, "offset" = 1) + var/required_role = ROLE_NUCLEAR_OPERATIVE var/datum/team/nuclear/nuke_team /datum/dynamic_ruleset/roundstart/nuclear/ready(population, forced = FALSE) @@ -410,15 +411,16 @@ return TRUE /datum/dynamic_ruleset/roundstart/nuclear/execute() - var/leader = TRUE - for(var/datum/mind/M in assigned) - if (leader) - leader = FALSE - var/datum/antagonist/nukeop/leader/new_op = M.add_antag_datum(antag_leader_datum) + var/most_experienced = get_most_experienced(assigned, required_role) + if(!most_experienced) + most_experienced = assigned[1] + for(var/datum/mind/assigned_player in assigned) + if(assigned_player == most_experienced) + var/datum/antagonist/nukeop/leader/new_op = assigned_player.add_antag_datum(antag_leader_datum) nuke_team = new_op.nuke_team else var/datum/antagonist/nukeop/new_op = new antag_datum() - M.add_antag_datum(new_op) + assigned_player.add_antag_datum(new_op) return TRUE /datum/dynamic_ruleset/roundstart/nuclear/round_result() @@ -595,6 +597,7 @@ antag_flag_override = ROLE_OPERATIVE antag_leader_datum = /datum/antagonist/nukeop/leader/clownop requirements = list(101,101,101,101,101,101,101,101,101,101) + required_role = ROLE_CLOWN_OPERATIVE /datum/dynamic_ruleset/roundstart/nuclear/clown_ops/pre_execute() . = ..() diff --git a/code/modules/antagonists/_common/antag_helpers.dm b/code/modules/antagonists/_common/antag_helpers.dm index e939e1f78cc..19dc4cbb7db 100644 --- a/code/modules/antagonists/_common/antag_helpers.dm +++ b/code/modules/antagonists/_common/antag_helpers.dm @@ -7,3 +7,31 @@ continue if(!antag_type || !specific && istype(A,antag_type) || specific && A.type == antag_type) . += A.owner + +/// From a list of players (minds, mobs or clients), finds the one with the highest playtime (either from a specific role or overall living) and returns it. +/proc/get_most_experienced(list/players, specific_role) + if(!CONFIG_GET(flag/use_exp_tracking)) //woops + return + var/most_experienced + for(var/client/player as anything in players) + if(!most_experienced) + most_experienced = player + continue + player = get_player_client(player) + if(!player?.prefs || !length(player.prefs.exp)) + continue + var/client/most_played = get_player_client(most_experienced) + if(!most_played?.prefs || !length(most_played.prefs.exp)) + most_experienced = player + continue + var/player_playtime + var/most_playtime + if(specific_role) + player_playtime = player.prefs.exp[specific_role] ? text2num(player.prefs.exp[specific_role]) : 0 + most_playtime = most_played.prefs.exp[specific_role] ? text2num(most_played.prefs.exp[specific_role]) : 0 + else + player_playtime = player.get_exp_living(TRUE) + most_playtime = most_played.get_exp_living(TRUE) + if(player_playtime > most_playtime) + most_experienced = player + return most_experienced diff --git a/code/modules/antagonists/nukeop/nukeop.dm b/code/modules/antagonists/nukeop/nukeop.dm index b7400ff2f2c..bd3eddc22e1 100644 --- a/code/modules/antagonists/nukeop/nukeop.dm +++ b/code/modules/antagonists/nukeop/nukeop.dm @@ -244,24 +244,19 @@ /datum/antagonist/nukeop/leader/greet() owner.current.playsound_local(get_turf(owner.current), 'sound/ambience/antag/ops.ogg',100,0, use_reverb = FALSE) - to_chat(owner, "You are the Syndicate [title] for this mission. You are responsible for the distribution of telecrystals and your ID is the only one who can open the launch bay doors.") - to_chat(owner, "If you feel you are not up to this task, give your ID to another operative.") + to_chat(owner, "You are the Syndicate [title] for this mission. You are responsible for guiding the team and your ID is the only one who can open the launch bay doors.") + to_chat(owner, "If you feel you are not up to this task, give your ID and radio to another operative.") if(!CONFIG_GET(flag/disable_warops)) to_chat(owner, "In your hand you will find a special item capable of triggering a greater challenge for your team. Examine it carefully and consult with your fellow operatives before activating it.") - owner.announce_objectives() /datum/antagonist/nukeop/leader/on_gain() . = ..() if(!CONFIG_GET(flag/disable_warops)) - var/obj/item/dukinuki = new challengeitem - var/mob/living/carbon/human/H = owner.current - if(!istype(H)) - dukinuki.forceMove(H.drop_location()) - else - H.put_in_hands(dukinuki, TRUE) - nuke_team.war_button_ref = WEAKREF(dukinuki) - + var/mob/living/carbon/human/leader = owner.current + var/obj/item/war_declaration = new challengeitem(leader.drop_location()) + leader.put_in_hands(war_declaration) + nuke_team.war_button_ref = WEAKREF(war_declaration) addtimer(CALLBACK(src, .proc/nuketeam_name_assign), 1) /datum/antagonist/nukeop/leader/proc/nuketeam_name_assign() diff --git a/code/modules/antagonists/nukeop/outfits.dm b/code/modules/antagonists/nukeop/outfits.dm index c4b9fd3dbb3..1fec618a12d 100644 --- a/code/modules/antagonists/nukeop/outfits.dm +++ b/code/modules/antagonists/nukeop/outfits.dm @@ -25,25 +25,26 @@ id_trim = /datum/id_trim/chameleon/operative/nuke_leader -/datum/outfit/syndicate/post_equip(mob/living/carbon/human/H, visualsOnly = FALSE) +/datum/outfit/syndicate/post_equip(mob/living/carbon/human/nukie, visualsOnly = FALSE) if(visualsOnly) return - var/obj/item/radio/R = H.ears - R.set_frequency(FREQ_SYNDICATE) - R.freqlock = TRUE + var/obj/item/radio/radio = nukie.ears + radio.set_frequency(FREQ_SYNDICATE) + radio.freqlock = TRUE if(command_radio) - R.command = TRUE + radio.command = TRUE + radio.use_command = TRUE if(ispath(uplink_type, /obj/item/uplink/nuclear) || tc) // /obj/item/uplink/nuclear understands 0 tc - var/obj/item/U = new uplink_type(H, H.key, tc) - H.equip_to_slot_or_del(U, ITEM_SLOT_BACKPACK) + var/obj/item/uplink = new uplink_type(nukie, nukie.key, tc) + nukie.equip_to_slot_or_del(uplink, ITEM_SLOT_BACKPACK) - var/obj/item/implant/weapons_auth/W = new/obj/item/implant/weapons_auth(H) - W.implant(H) - var/obj/item/implant/explosive/E = new/obj/item/implant/explosive(H) - E.implant(H) - H.faction |= ROLE_SYNDICATE - H.update_icons() + var/obj/item/implant/weapons_auth/weapons_implant = new/obj/item/implant/weapons_auth(nukie) + weapons_implant.implant(nukie) + var/obj/item/implant/explosive/explosive_implant = new/obj/item/implant/explosive(nukie) + explosive_implant.implant(nukie) + nukie.faction |= ROLE_SYNDICATE + nukie.update_icons() /datum/outfit/syndicate/full name = "Syndicate Operative - Full Kit" diff --git a/code/modules/mob/mob_helpers.dm b/code/modules/mob/mob_helpers.dm index faf7e5078eb..0281765d141 100644 --- a/code/modules/mob/mob_helpers.dm +++ b/code/modules/mob/mob_helpers.dm @@ -422,3 +422,15 @@ if(ITEM_SLOT_SUITSTORE) return /obj/item return null + +/// Returns a client from a mob, mind or client +/proc/get_player_client(player) + if(ismob(player)) + var/mob/player_mob = player + player = player_mob.client + else if(istype(player, /datum/mind)) + var/datum/mind/player_mind = player + player = player_mind.current.client + if(!istype(player, /client)) + return + return player