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