From b012dc7e5027597a41a70fef67f99356a3201194 Mon Sep 17 00:00:00 2001 From: Sam Maselli <sammypet3@gmail.com> Date: Mon, 30 Dec 2024 16:38:39 -0500 Subject: [PATCH 1/3] yer backend --- client/src/resources/lang/en_us.json | 2 +- server/src/game/role/doomsayer.rs | 2 +- server/src/game/role/kira.rs | 2 +- server/src/game/role/mod.rs | 3 +- server/src/game/role/serial_killer.rs | 8 +- server/src/game/role/yer.rs | 131 ++++++++++++++++++++++++++ 6 files changed, 143 insertions(+), 5 deletions(-) create mode 100644 server/src/game/role/yer.rs diff --git a/client/src/resources/lang/en_us.json b/client/src/resources/lang/en_us.json index d9eccc3b5..693210ac4 100644 --- a/client/src/resources/lang/en_us.json +++ b/client/src/resources/lang/en_us.json @@ -1595,7 +1595,7 @@ "wiki.article.role.serialKiller.reminder": "Each night, select a player to attack.", "wiki.article.role.serialKiller.guide": "- At night select a player to attack them\n- You can't use your ability night 1.", "wiki.article.role.serialKiller.abilities":"* Visit a player to attack", - "wiki.article.role.serialKiller.attributes":"", + "wiki.article.role.serialKiller.attributes":"- You have an armor-piercing attack", "wiki.article.role.serialKiller.extra":"", "wiki.article.role.mafiaKillingWildcard.reminder": "Choose a syndicate killing role to become that role when night starts.", diff --git a/server/src/game/role/doomsayer.rs b/server/src/game/role/doomsayer.rs index b90b8c46d..9c0d489e4 100644 --- a/server/src/game/role/doomsayer.rs +++ b/server/src/game/role/doomsayer.rs @@ -86,7 +86,7 @@ impl DoomsayerGuess{ //Fiends Role::Arsonist | Role::Werewolf | Role::Ojo | Role::Puppeteer | Role::Pyrolisk | Role::Kira | - Role:: SerialKiller | Role::Warden | + Role::SerialKiller | Role::Warden | Role::Yer | Role::FiendsWildcard => Some(DoomsayerGuess::NonTown), //Cult diff --git a/server/src/game/role/kira.rs b/server/src/game/role/kira.rs index 3665472d9..a82b290a6 100644 --- a/server/src/game/role/kira.rs +++ b/server/src/game/role/kira.rs @@ -86,7 +86,7 @@ impl KiraGuess{ //Fiends Role::Arsonist | Role::Werewolf | Role::Ojo | Role::Puppeteer | Role::Pyrolisk | Role::Kira | - Role::SerialKiller | Role::Warden | + Role::SerialKiller | Role::Warden | Role::Yer | Role::FiendsWildcard => Some(Self::NonTown), //Cult diff --git a/server/src/game/role/mod.rs b/server/src/game/role/mod.rs index 7e0b9e361..9a1b8a94c 100644 --- a/server/src/game/role/mod.rs +++ b/server/src/game/role/mod.rs @@ -160,6 +160,7 @@ macros::roles! { Spiral : spiral, Kira : kira, Warden : warden, + Yer : yer, FiendsWildcard : fiends_wildcard, SerialKiller : serial_killer, @@ -184,7 +185,7 @@ macros::priorities! { Heal, Kill, - Convert, + Convert, //role swap & win condition change Poison, Investigative, diff --git a/server/src/game/role/serial_killer.rs b/server/src/game/role/serial_killer.rs index 269ab6995..c62ad86f5 100644 --- a/server/src/game/role/serial_killer.rs +++ b/server/src/game/role/serial_killer.rs @@ -28,7 +28,13 @@ impl RoleStateImpl for SerialKiller { let target_ref = visit.target; - target_ref.try_night_kill_single_attacker(actor_ref, game, GraveKiller::Role(Role::SerialKiller), AttackPower::Basic, true); + target_ref.try_night_kill_single_attacker( + actor_ref, + game, + GraveKiller::Role(Role::SerialKiller), + AttackPower::ArmorPiercing, + true + ); } } fn controller_parameters_map(self, game: &Game, actor_ref: PlayerReference) -> ControllerParametersMap { diff --git a/server/src/game/role/yer.rs b/server/src/game/role/yer.rs new file mode 100644 index 000000000..f23744db3 --- /dev/null +++ b/server/src/game/role/yer.rs @@ -0,0 +1,131 @@ +use serde::Serialize; + +use crate::game::attack_power::AttackPower; +use crate::game::chat::ChatMessageVariant; +use crate::game::components::insider_group::InsiderGroupID; +use crate::game::win_condition::WinCondition; +use crate::game::{attack_power::DefensePower, grave::GraveKiller}; +use crate::game::player::PlayerReference; + +use crate::game::visit::Visit; + +use crate::game::Game; +use crate::vec_set; +use super::{Priority, Role, RoleState, RoleStateImpl}; +use crate::game::ability_input::*; + +#[derive(Debug, Clone, Serialize, Default)] +pub struct Yer{ + star_passes_remaining: u8, +} + +pub(super) const MAXIMUM_COUNT: Option<u8> = None; +pub(super) const DEFENSE: DefensePower = DefensePower::Armor; + +impl RoleStateImpl for Yer { + type ClientRoleState = Yer; + fn new_state(game: &Game) -> Self { + Self{ + star_passes_remaining: game.num_players().div_ceil(5), + ..Self::default() + } + } + fn do_night_action(mut self, game: &mut Game, actor_ref: PlayerReference, priority: Priority) { + if game.day_number() == 1 {return} + + let chose_to_convert = if let Some(BooleanSelection(bool)) = game.saved_controllers.get_controller_current_selection_boolean( + ControllerID::role(actor_ref, Role::Yer, 0) + ){ + bool + }else{false}; + + let actor_visits = actor_ref.untagged_night_visits_cloned(game); + if let Some(visit) = actor_visits.first(){ + let target_ref = visit.target; + + if !chose_to_convert{ + if priority != Priority::Kill {return} + + target_ref.try_night_kill_single_attacker( + actor_ref, + game, + GraveKiller::Role(Role::Yer), + AttackPower::ArmorPiercing, + true + ); + }else{ + if priority != Priority::Convert {return} + if self.star_passes_remaining <= 0 {return} + + if target_ref.night_defense(game).can_block(AttackPower::Basic) { + actor_ref.push_night_message(game, ChatMessageVariant::YourConvertFailed); + return + } + + self.star_passes_remaining = self.star_passes_remaining.saturating_sub(1); + + InsiderGroupID::Puppeteer.add_player_to_revealed_group(game, target_ref); + target_ref.set_win_condition( + game, + WinCondition::new_loyalist(crate::game::game_conclusion::GameConclusion::Fiends) + ); + target_ref.set_night_convert_role_to(game, Some(RoleState::Yer(self.clone()))); + + actor_ref.set_role_state(game, self); + actor_ref.try_night_kill_single_attacker( + actor_ref, + game, + GraveKiller::Role(Role::Yer), + AttackPower::ProtectionPiercing, + true + ); + } + } + } + fn controller_parameters_map(self, game: &Game, actor_ref: PlayerReference) -> ControllerParametersMap { + crate::game::role::common_role::controller_parameters_map_boolean( + game, + actor_ref, + self.star_passes_remaining <= 0 || game.day_number() <= 1, + ControllerID::role(actor_ref, Role::Yer, 0) + ).combine_overwrite_owned( + crate::game::role::common_role::controller_parameters_map_player_list_night_typical( + game, + actor_ref, + false, + game.day_number() <= 1, + ControllerID::role(actor_ref, Role::Yer, 1) + ) + ).combine_overwrite_owned( + ControllerParametersMap::new_controller_fast( + game, + ControllerID::role(actor_ref, Role::Yer, 2), + AvailableAbilitySelection::new_role_option( + Role::values().into_iter() + .map(|role| Some(role)) + .collect() + ), + AbilitySelection::new_role_option(Some(Role::Yer)), + !actor_ref.alive(game), + None, + false, + vec_set!(actor_ref) + ) + ) + } + fn convert_selection_to_visits(self, game: &Game, actor_ref: PlayerReference) -> Vec<Visit> { + crate::game::role::common_role::convert_controller_selection_to_visits( + game, + actor_ref, + ControllerID::role(actor_ref, Role::Yer, 1), + true + ) + } + fn default_revealed_groups(self) -> vec_set::VecSet<InsiderGroupID> { + vec_set![InsiderGroupID::Puppeteer] + } +} + + +impl Yer{ +} \ No newline at end of file From 0ccd32fd5e46de7c23a2d25b46fd5b3d5785bcdc Mon Sep 17 00:00:00 2001 From: Sam Maselli <sammypet3@gmail.com> Date: Tue, 31 Dec 2024 15:09:32 -0500 Subject: [PATCH 2/3] yer front end --- client/src/game/roleState.d.tsx | 5 ++++ .../AbilityMenu/RoleSpecific.tsx | 25 ++++++++++++------- client/src/resources/abilityId.json | 9 +++++++ client/src/resources/lang/en_us.json | 22 ++++++++++++---- client/src/resources/roles.json | 13 ++++++++++ server/src/game/role/yer.rs | 25 ++++++++++++------- server/src/game/role_list.rs | 2 +- 7 files changed, 77 insertions(+), 24 deletions(-) diff --git a/client/src/game/roleState.d.tsx b/client/src/game/roleState.d.tsx index 175e4759d..df514d8f2 100644 --- a/client/src/game/roleState.d.tsx +++ b/client/src/game/roleState.d.tsx @@ -182,6 +182,11 @@ Doomsayer } | { type: "puppeteer" marionettesRemaining: number +} | { + type: "warden" +} | { + type: "yer", + starPassesRemaining: number } | { type: "kira" } | { diff --git a/client/src/menu/game/gameScreenContent/AbilityMenu/RoleSpecific.tsx b/client/src/menu/game/gameScreenContent/AbilityMenu/RoleSpecific.tsx index 09981d0c4..86f04d411 100644 --- a/client/src/menu/game/gameScreenContent/AbilityMenu/RoleSpecific.tsx +++ b/client/src/menu/game/gameScreenContent/AbilityMenu/RoleSpecific.tsx @@ -56,7 +56,7 @@ function roleSpecificSectionInner( roleState: RoleState, numPlayers: number ): ReactElement | null{ - let chargesCounter = abilityChargesCounter(numPlayers); + let maxChargesCounter = abilityChargesCounter(numPlayers); switch(roleState.type){ case "auditor": @@ -67,7 +67,7 @@ function roleSpecificSectionInner( return <LargeDoomsayerMenu/>; case "jailor": return <Counter - max={chargesCounter} + max={maxChargesCounter} current={roleState.executionsRemaining} > <StyledText>{translate("role.jailor.roleDataText.executionsRemaining", roleState.executionsRemaining)}</StyledText> @@ -112,7 +112,7 @@ function roleSpecificSectionInner( </div> case "loaded": return <Counter - max={chargesCounter} + max={maxChargesCounter} current={roleState.state.bullets} > <StyledText>{translate("role.vigilante.roleDataText", roleState.state.bullets)}</StyledText> @@ -122,14 +122,14 @@ function roleSpecificSectionInner( } case "veteran": return <Counter - max={chargesCounter} + max={maxChargesCounter} current={roleState.alertsRemaining} > <StyledText>{translate("role.veteran.roleDataText", roleState.alertsRemaining)}</StyledText> </Counter> case "armorsmith": return <Counter - max={chargesCounter} + max={maxChargesCounter} current={roleState.openShopsRemaining} > <StyledText>{translate("role.armorsmith.roleDataText", roleState.openShopsRemaining)}</StyledText> @@ -139,14 +139,14 @@ function roleSpecificSectionInner( case "counterfeiter": case "forger": return <Counter - max={chargesCounter} + max={maxChargesCounter} current={roleState.forgesRemaining} > <StyledText>{translate("role.forger.roleDataText", roleState.forgesRemaining)}</StyledText> </Counter> case "mortician": return <Counter - max={chargesCounter} + max={maxChargesCounter} current={roleState.cremationsRemaining} > <StyledText>{translate("role.mortician.roleDataText", roleState.cremationsRemaining)}</StyledText> @@ -159,10 +159,17 @@ function roleSpecificSectionInner( return <SpiralMenu />; case "puppeteer": return <SmallPuppeteerMenu - maxCharges={chargesCounter} + maxCharges={maxChargesCounter} marionettesRemaining={roleState.marionettesRemaining} phase={phaseState.type} />; + case "yer": + return <Counter + max={maxChargesCounter} + current={roleState.starPassesRemaining} + > + <StyledText>{translate("role.yer.shapeshiftsRemaining", roleState.starPassesRemaining)}</StyledText> + </Counter>; case "recruiter": return <RecruiterMenu remaining={roleState.recruitsRemaining} @@ -176,7 +183,7 @@ function roleSpecificSectionInner( <StyledText>{translate("role.martyr.roleDataText.eccentric")}</StyledText> </div> <Counter - max={chargesCounter} + max={maxChargesCounter} current={roleState.state.bullets} > <StyledText>{translate("role.martyr.roleDataText", roleState.state.bullets)}</StyledText> diff --git a/client/src/resources/abilityId.json b/client/src/resources/abilityId.json index 902bbfe14..d9fe5e405 100644 --- a/client/src/resources/abilityId.json +++ b/client/src/resources/abilityId.json @@ -200,6 +200,15 @@ "wardenLiveOrDie": { "midnight": true }, + "role/yer/0": { + "midnight": true + }, + "role/yer/1": { + "midnight": true + }, + "role/yer/2": { + "midnight": true + }, "role/kira/0": { "midnight": true }, diff --git a/client/src/resources/lang/en_us.json b/client/src/resources/lang/en_us.json index fed986480..bd29ee6e5 100644 --- a/client/src/resources/lang/en_us.json +++ b/client/src/resources/lang/en_us.json @@ -511,9 +511,15 @@ "controllerId.role.warden.0.name": "Imprison", "controllerId.role.warden.1.name": "Self Ward", + "role.yer.name": "Yer", + "role.yer.name:var.0": "Yers", + "role.yer.shapeshiftsRemaining": "Shapeshifts remaining", + "controllerId.role.yer.0.name": "Shapeshift", + "controllerId.role.yer.1.name": "Choose Target", + "controllerId.role.yer.2.name": "Disguise as Role", + "role.serialKiller.name": "Serial Killer", "role.serialKiller.name:var.0": "Serial Killers", - "role.serialKiller.target": "Attack", "controllerId.role.serialKiller.0.name": "Attack", "role.fiendsWildcard.name": "Fiends Wildcard", @@ -1791,13 +1797,13 @@ "wiki.article.role.puppeteer.abilities":"- You may choose to do one of the following\n - Visit a player to poison them\n - They are told they are poisoned\n - They are indirectly hit with an armor-piercing attack on the following night\n\n - Visit a player to string up into a marionette\n - They are told they are strung up, and they now win with fiends, regardless of their role\n - They will be indirectly hit with a protection-piercing attack every night by all puppeteers until they die, if there are no puppeteers they are still attacked\n - You can only use this X times (X = Total players ÷ 5 (round up))", "wiki.article.role.puppeteer.attributes":"- You and the marionettes are all puppeteer insiders\n- Stringing someone up is armor-piercing, if a player has higher defense than armor when you attempt to string them up, they are instead poisoned\n - At night all puppeteers and marionettes can chat in the puppeteer chat, even if dead\n - The players in the puppeteer chat that are dead can chat during the day or night", "wiki.article.role.puppeteer.extra":"- You can't select anybody who is a puppeteer, marionette, or is being strung into a marionette\n- A puppeteer can't be stringed into a marionette\n- A marionette can't be stringed into a marionette twice, if 2 puppeteers choose a player to be turned into a marionette on the same night, they get the message only once", - + "wiki.article.role.kira.reminder": "Each night, guess players roles, if all your guesses are correct, you attack all of the players you guessed.", "wiki.article.role.kira.guide":"- Each night, guess players roles, if all your guesses are correct, you attack all of the players you guessed.\n- You can choose not to guess a players role by selecting none, this doesn't count as a wrong guess\n- Each night you get a result, for each guess, you are told if your guess was correct, incorrect but someone has that role, or incorrect and nobody has that role\n- You can't attack night 1, but you can still make guesses\n\n_For Example_\n- You guess @1 is a lookout, @2 is a tracker, and don't guess anyone else by selecting none. If @1 is a lookout, @2 is a tracker, you attack @1 and @2, but nobody else.", "wiki.article.role.kira.abilities":"- Each night, make a guess for every living player\n - Your options for guesses are, any specific town role, none, and non town. So if they aren't town, you don't need to know their exact role\n - If all of your guesses are one of either correct or none, you attack all of the players you guessed correctly with an indirect armor-piercing attack\n- Every night, you get a result\n - For each player you guessed as something non none, you learn one of three things\n - Your guess is correct, that player has that role\n - Your guess is incorrect, that player doesn't have that role, but someone else in the game does have that role\n - Your guess is incorrect, that player doesn't have that role, and nobody else in the game has that role\n- If it is night 1, you don't attack anyone, but you still get your result", "wiki.article.role.kira.attributes":"- You don't visit anyone\n- Your attack is armor-piercing\n- You don't attack anyone night 1", "wiki.article.role.kira.extra":"- You can't guess dead players or yourself, nor can you attack them\n* If you are blocked, your ability does nothing", - + "wiki.article.role.pyrolisk.reminder": "Each night*, select a player to attack them. You passively attack everyone who visits you. Everyone you kill is obscured.", "wiki.article.role.pyrolisk.guide":"- Each night except the first, select a player to attack them, and obscure them\n- You passively attack and obscure everyone who visits you\n- On night 1, you can't attack anyone, and you have innocent aura\n- You are told the players you obscures role and alibi", "wiki.article.role.pyrolisk.abilities":"* On night 1\n * You can't attack\n * You have innocent aura\n* On other nights\n * Visit a player to attack them\n * All players who visit you are attacked\n* All players you attacked and killed have their grave obscured and you are told their role and alibi", @@ -1809,13 +1815,19 @@ "wiki.article.role.spiral.abilities":"- Each night except the first, select a player to attack and spiral all visitors to them\n - Players die the night after they begin to spiral\n - The night a player dies to spiraling, all visitors to them begin to spiral, causing a potential chain reaction\n- You can't spiral a player if any player is still spiraling", "wiki.article.role.spiral.attributes":"- Players are not told when they start to spiral\n* If you are blocked, spiraling players still die\n* Your attack is armor piercing", "wiki.article.role.spiral.extra":"- You can't cause yourself to spiral\n- If a dead player is spiraling, they stay spiraling, and you attack them again, even while they are dead. Although they cannot die after already dead.", - + "wiki.article.role.warden.reminder": "Each night*, put up to 3 players in your prison who each must choose to either live or die, but if they all choose to live, they all die instead.", "wiki.article.role.warden.guide":"- Each night except the first, choose up to 3 players to put in prison\n - The prisoners must choose to live or die\n - If a player chooses die, you attack them (armor-piercing)\n - If all of the players in your prison choose live, you attack all of them (armor-piercing)\n - The players in your prison can talk in a private chat group at night\n - You can always read from the private prisoner chat group\n - The players in your prison are roleblocked\n - You can put yourself in your prison, but you can't ever die or be roleblocked by your own ability\n - Each night, you may choose to ward yourself", "wiki.article.role.warden.abilities":"- Each night except the first, choose up to 3 players to put in prison\n - The prisoners must choose to live or die\n - If a player chooses die, you attack them (armor-piercing)\n - If all of the players in your prison choose live, you attack all of them (armor-piercing)\n - The players in your prison can talk in a private chat group at night\n - You can always read from the private prisoner chat group\n - The players in your prison are roleblocked\n - You can put yourself in your prison, but you can't ever die or be roleblocked by your own ability\n - Each night, you may choose to ward yourself", "wiki.article.role.warden.attributes":" - You can't die to your own ability, but the logic of your ability doesn't change. _For example_:\n You imprison yourself and another player. You both choose live. You survive and the other player dies. All players in prison chose to live so both players should die, but you can't die to your own ability.", "wiki.article.role.warden.extra":" - You don't visit anybody due to your own ability", - + + "wiki.article.role.yer.reminder":"Each night*, either attack a player, or convert a player to be a yer, and attack yourself.", + "wiki.article.role.yer.guide":"- At night choose to either shapeshift or not\n - If you don't shapeshift\n - Choose a player to attack with an armor piercing attack\n - If you shapeshift\n - Choose a player to convert with an armor-piercing attack\n - That player becomes a yer, and their win condition switches to be fiends loyalist\n - You attack yourself with a protection piercing attack\n- You can only shapeshift X times (X = Total players ÷ 5 (round up))", + "wiki.article.role.yer.abilities":"", + "wiki.article.role.yer.attributes":"", + "wiki.article.role.yer.extra":"", + "wiki.article.role.fiendsWildcard.reminder": "Choose a fiends role to become at start of night.", "wiki.article.role.fiendsWildcard.guide": "* Choose a fiends role to become that role\n * You become that role when night starts\n* You can't become a role that has exceeded its role limit", "wiki.article.role.fiendsWildcard.abilities":"* Become a role you choose at the start of night", diff --git a/client/src/resources/roles.json b/client/src/resources/roles.json index 04b990a4b..ea38ecada 100644 --- a/client/src/resources/roles.json +++ b/client/src/resources/roles.json @@ -1191,6 +1191,19 @@ {"type": "wardblocked"} ] }, + "yer": { + "mainRoleSet": "fiends", + "roleSets": ["fiends"], + "armor": true, + "aura": null, + "maxCount": null, + "canWriteDeathNote": true, + "canBeConvertedTo": [], + "chatMessages":[ + {"type": "youAttackedSomeone"}, + {"type": "someoneSurvivedYourAttack"} + ] + }, "fiendsWildcard": { "mainRoleSet": "fiends", "roleSets": ["fiends"], diff --git a/server/src/game/role/yer.rs b/server/src/game/role/yer.rs index f23744db3..b646df516 100644 --- a/server/src/game/role/yer.rs +++ b/server/src/game/role/yer.rs @@ -2,7 +2,6 @@ use serde::Serialize; use crate::game::attack_power::AttackPower; use crate::game::chat::ChatMessageVariant; -use crate::game::components::insider_group::InsiderGroupID; use crate::game::win_condition::WinCondition; use crate::game::{attack_power::DefensePower, grave::GraveKiller}; use crate::game::player::PlayerReference; @@ -15,6 +14,7 @@ use super::{Priority, Role, RoleState, RoleStateImpl}; use crate::game::ability_input::*; #[derive(Debug, Clone, Serialize, Default)] +#[serde(rename_all = "camelCase")] pub struct Yer{ star_passes_remaining: u8, } @@ -57,21 +57,29 @@ impl RoleStateImpl for Yer { if priority != Priority::Convert {return} if self.star_passes_remaining <= 0 {return} - if target_ref.night_defense(game).can_block(AttackPower::Basic) { + if target_ref.night_defense(game).can_block(AttackPower::ArmorPiercing) { actor_ref.push_night_message(game, ChatMessageVariant::YourConvertFailed); return } - + self.star_passes_remaining = self.star_passes_remaining.saturating_sub(1); + + //role switching stuff + let fake_role = if let Some(RoleOptionSelection(Some(role))) = game.saved_controllers.get_controller_current_selection_role_option( + ControllerID::role(actor_ref, Role::Yer, 2) + ){ + role + }else{Role::Yer}; + + actor_ref.set_night_grave_role(game, Some(fake_role)); - InsiderGroupID::Puppeteer.add_player_to_revealed_group(game, target_ref); + //convert & kill stuff target_ref.set_win_condition( game, WinCondition::new_loyalist(crate::game::game_conclusion::GameConclusion::Fiends) ); target_ref.set_night_convert_role_to(game, Some(RoleState::Yer(self.clone()))); - actor_ref.set_role_state(game, self); actor_ref.try_night_kill_single_attacker( actor_ref, game, @@ -79,6 +87,8 @@ impl RoleStateImpl for Yer { AttackPower::ProtectionPiercing, true ); + + actor_ref.set_role_state(game, self); } } } @@ -106,7 +116,7 @@ impl RoleStateImpl for Yer { .collect() ), AbilitySelection::new_role_option(Some(Role::Yer)), - !actor_ref.alive(game), + self.star_passes_remaining <= 0 || !actor_ref.alive(game) || game.day_number() <= 1, None, false, vec_set!(actor_ref) @@ -121,9 +131,6 @@ impl RoleStateImpl for Yer { true ) } - fn default_revealed_groups(self) -> vec_set::VecSet<InsiderGroupID> { - vec_set![InsiderGroupID::Puppeteer] - } } diff --git a/server/src/game/role_list.rs b/server/src/game/role_list.rs index b7c851eba..3a9126189 100644 --- a/server/src/game/role_list.rs +++ b/server/src/game/role_list.rs @@ -215,7 +215,7 @@ impl RoleSet{ Role::Arsonist, Role::Werewolf, Role::Ojo, Role::Puppeteer, Role::Pyrolisk, Role::Kira, Role::SerialKiller, Role::FiendsWildcard, - Role::Spiral, Role::Warden + Role::Spiral, Role::Warden, Role::Yer ], RoleSet::Cult => vec![ From 83c318b7a64364318a5dda803ad72bc95229274d Mon Sep 17 00:00:00 2001 From: Sam Maselli <sammypet3@gmail.com> Date: Sat, 4 Jan 2025 17:15:43 -0500 Subject: [PATCH 3/3] fix up yer encyclopedia --- client/src/resources/lang/en_us.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/client/src/resources/lang/en_us.json b/client/src/resources/lang/en_us.json index bd29ee6e5..7e0810fa2 100644 --- a/client/src/resources/lang/en_us.json +++ b/client/src/resources/lang/en_us.json @@ -1823,10 +1823,10 @@ "wiki.article.role.warden.extra":" - You don't visit anybody due to your own ability", "wiki.article.role.yer.reminder":"Each night*, either attack a player, or convert a player to be a yer, and attack yourself.", - "wiki.article.role.yer.guide":"- At night choose to either shapeshift or not\n - If you don't shapeshift\n - Choose a player to attack with an armor piercing attack\n - If you shapeshift\n - Choose a player to convert with an armor-piercing attack\n - That player becomes a yer, and their win condition switches to be fiends loyalist\n - You attack yourself with a protection piercing attack\n- You can only shapeshift X times (X = Total players ÷ 5 (round up))", + "wiki.article.role.yer.guide":"- At night choose to either shapeshift or not\n - If you don't shapeshift\n - Choose a player to attack with an armor piercing attack\n - If you shapeshift\n - Choose a player to convert with an armor-piercing attack\n - If the attack succeedes\n - That players role becomes yer - That player converts to fiends loyalist\n - You attack yourself with a protection piercing attack\n - If you die, your grave shows the role you disguised as on it\n- You can only shapeshift X times (X = Total players ÷ 5 (round up))", "wiki.article.role.yer.abilities":"", "wiki.article.role.yer.attributes":"", - "wiki.article.role.yer.extra":"", + "wiki.article.role.yer.extra":"- You visit the player you choose\n- You can't attack or convert night 1", "wiki.article.role.fiendsWildcard.reminder": "Choose a fiends role to become at start of night.", "wiki.article.role.fiendsWildcard.guide": "* Choose a fiends role to become that role\n * You become that role when night starts\n* You can't become a role that has exceeded its role limit",