From 1eed63b18147c21f984f4ace9e3115f865ab9a0f Mon Sep 17 00:00:00 2001 From: Ryan Schmidt Date: Fri, 29 Nov 2024 18:36:44 -0700 Subject: [PATCH] Pactbreaker balance adjustments - Visiting forest while knowing all wolves + cursed no longer gives evidence on other visitors - Vampires no longer grant clues to "witnesses" of bites, just the target - The target of a vampire bite now receives 3 clue tokens instead of 2 - Clue tokens now count as 40% of an evidence card instead of 50% --- messages/en.json | 9 +++--- src/defaultsettings.yml | 8 ++--- src/gamemodes/pactbreaker.py | 58 ++++-------------------------------- 3 files changed, 12 insertions(+), 63 deletions(-) diff --git a/messages/en.json b/messages/en.json index baf71977..17f5dd13 100644 --- a/messages/en.json +++ b/messages/en.json @@ -1442,7 +1442,7 @@ "pactbreaker_no_id": "You do not have enough clue tokens to investigate someone; you need {0} tokens and you only have {1}.", "pactbreaker_id_fail": "Your investigation of {0} did not turn up any useful information.", "pactbreaker_wolf_notify": "You are {=wolf!role:article} {=wolf!role:bold}. It is your job to eliminate the {=vampire!role:plural} and {=vigilante!role:plural} to re-establish your pact with the village.\n{=pactbreaker_notify!message}\nFinally, you can use \"{=kill!command} \" to kill someone in the stocks or a known {=vampire!role} or {=vigilante!role} instead of visting a location.", - "pactbreaker_vampire_notify": "You are {=vampire!role:article} {=vampire!role:bold}. It is your job to kill all the villagers.\n{=pactbreaker_notify!message}\nFinally, you can use \"{=bite!command} \" to feed on someone's blood instead of visting a location. Witnesses will gain clues should you do so, but biting most people twice will kill them.", + "pactbreaker_vampire_notify": "You are {=vampire!role:article} {=vampire!role:bold}. It is your job to kill all the villagers.\n{=pactbreaker_notify!message}\nFinally, you can use \"{=bite!command} \" to feed on someone's blood instead of visting a location. Your target will gain clues should you do so, but biting most people twice will kill them.", "pactbreaker_vigilante_notify": "You are {=vigilante!role:article} {=vigilante!role:bold}. It is your job to eliminate the {=wolf!role:plural} and {=vampire!role:plural} to end their threat over the village.\n{=pactbreaker_notify!message}.\nFinally, you can use \"{=kill!command} \" to kill someone in the stocks or a known {=wolf!role} or {=vampire!role} instead of visting a location. If the person you kill is not {=wolf!role:article} {=wolf!role} or {=wolf!role:article} {=vampire!role}, you will die alongside your victim.", "pactbreaker_villager_notify": "You are {=villager!role:article} {=villager!role:bold}. It is your job to either re-establish the pact with the {=wolf!role:plural} by killing the {=vigilante!role:plural} and {=vampire!role:plural} or to help the {=vigilante!role:plural} end the threat the {=wolf!role:plural} and {=vampire!role:plural} cause.\n{=pactbreaker_notify!message}", "pactbreaker_notify": "You may visit the {=forest!command:bold}, {=square!command:bold}, {=streets!command:bold}, or {=graveyard!command:bold} by using \"{=visit!command} \". Visiting allows you to collect evidence about other players.", @@ -1484,10 +1484,9 @@ "pactbreaker_drain": "While out last night, you spot {0:@} alone and unaware of your presence. You quickly close in for a quick meal and vanish back into the shadows before they can clearly see who you are.", "pactbreaker_drain_kill": "While out last night, you spot {0:@} alone and unaware of your presence. You quickly close in for a quick meal, draining them fully and killing them.", "pactbreaker_drain_turn": "While out last night, you spot {0:@} alone and unaware of your presence. You quickly close in for a quick meal, draining them fully. Before they die, you give them a bit of your own blood, turning them into {=vampire!role:article} {=vampire!role}.", - "pactbreaker_drained": "While out last night, you are suddenly overtaken by a vampire! They drain your blood and your vision blurs, however you manage to make the vague shape of your assailant before they retreat, giving you a potential clue to their identity.", - "pactbreaker_drained_dead": "While out last night, you are suddenly overtaken by a vampire! They drain the rest of your blood as your consciousness fades away...", - "pactbreaker_drained_vigilante": "While out last night, you are suddenly overtaken by a vampire again! They drain the rest of your blood as your consciousness fades away. Shortly after, you reawaken in your own home with an unnatural hunger. It seems you have become {0!role:article} {0!role:bold} yourself!", - "pactbreaker_drained_witness": "While out last night, you hear a scream and rush to its source, arriving just as a shadowy figure departs. It seems that {=vampire!role:article} {=vampire!role} has been here, and you think there may have been a clue left behind as to their identity.", + "pactbreaker_drained": "While out last night, you are suddenly overtaken by {=vampire!role:article} {=vampire!role:bold}! They drain your blood and your vision blurs, however you manage to make the vague shape of your assailant before they retreat, giving you a potential clue to their identity.", + "pactbreaker_drained_dead": "While out last night, you are suddenly overtaken by {=vampire!role:article} {=vampire!role:bold}! They drain the rest of your blood as your consciousness fades away...", + "pactbreaker_drained_vigilante": "While out last night, you are suddenly overtaken by {=vampire!role:article} {=vampire!role:bold}! They drain the rest of your blood as your consciousness fades away. Shortly after, you reawaken in your own home with an unnatural hunger. It seems you have become {0!role:article} {0!role:bold} yourself!", "pactbreaker_vote": [ "The village has decided to lock {0:@} into the stocks until tomorrow." ], diff --git a/src/defaultsettings.yml b/src/defaultsettings.yml index fe517444..612a5cbe 100644 --- a/src/defaultsettings.yml +++ b/src/defaultsettings.yml @@ -1133,15 +1133,11 @@ gameplay: &gameplay _type: - float - int - _default: 0.5 + _default: 0.4 bite: _desc: The maximum number of clue tokens drawn when someone is the target of a vampire bite. _type: int - _default: 2 - witness: - _desc: The maximum number of clue tokens drawn when someone is the witness of a vampire bite. - _type: int - _default: 1 + _default: 3 identify: _desc: The minimum number of clue tokens required to use the !id command during day. _type: int diff --git a/src/gamemodes/pactbreaker.py b/src/gamemodes/pactbreaker.py index bbd81336..0e977e28 100644 --- a/src/gamemodes/pactbreaker.py +++ b/src/gamemodes/pactbreaker.py @@ -359,24 +359,12 @@ def on_night_kills(self, evt: Event, var: GameState): # handle evidence card num_evidence = sum(1 for c in cards if c == "evidence") evidence_target = None - if location is Forest: - if visitor not in all_wolves: - random.shuffle(wl) - for wolf in wl: - if wolf is not visitor and wolf not in self.collected_evidence[visitor]["wolf"]: - evidence_target = wolf - break - # is a wolf or has evidence on every wolf - if evidence_target is None: - for other in vl: - if other is visitor or (other in all_cursed and visitor not in all_wolves): - continue - other_role = get_main_role(var, other) - if other_role == "vampire": - other_role = "vigilante" if evidence_target in self.turned else "villager" - if other not in self.collected_evidence[visitor][other_role]: - evidence_target = other - break + if location is Forest and visitor not in all_wolves: + random.shuffle(wl) + for wolf in wl: + if wolf is not visitor and wolf not in self.collected_evidence[visitor]["wolf"]: + evidence_target = wolf + break elif location is Streets and num_evidence == 3: # refute fake evidence that the visitor may have collected, # in order of cursed -> villager and then vigilante -> vampire @@ -452,27 +440,9 @@ def on_player_protected(self, victim_tokens = min(config.Main.get("gameplay.modes.pactbreaker.clue.bite"), self.clue_pool) self.clue_pool -= victim_tokens self.clue_tokens[target] += victim_tokens - # hand out clue tokens to witnesses - victim_location = self.visiting[target] - witnesses = set() - if victim_location is not Limbo: - for other, visited in self.visiting.items(): - if victim_location is visited and other is not target and get_main_role(var, other) != "vampire": - witnesses.add(other) - if witnesses: - witness_tokens = min(config.Main.get("gameplay.modes.pactbreaker.clue.witness"), - math.floor(self.clue_pool / len(witnesses))) - if witness_tokens > 0: - for witness in witnesses: - witness.queue_message(messages["pactbreaker_drained_witness"]) - self.clue_pool -= witness_tokens - self.clue_tokens[witness] += witness_tokens - User.send_messages() - elif protector_role == "vigilante": # if the vampire fully drains a vigilante, they might turn into a vampire instead of dying # this protection triggering means they should turn - # No witnesses here, as the vampires drag the body away with them leaving the scene empty attacker.send(messages["pactbreaker_drain_turn"].format(target)) change_role(var, target, get_main_role(var, target), "vampire", message="pactbreaker_drained_vigilante") self.turned.add(target) @@ -488,22 +458,6 @@ def on_night_death_message(self, evt: Event, var: GameState, victim: User, kille if killer_role == "vampire": victim.send(messages["pactbreaker_drained_dead"]) killer.send(messages["pactbreaker_drain_kill"].format(victim)) - # hand out clue tokens to witnesses - victim_location = self.visiting[victim] - witnesses = set() - if victim_location is not Limbo: - for other, visited in self.visiting.items(): - if victim_location is visited and other is not victim and get_main_role(var, other) != "vampire": - witnesses.add(other) - if witnesses: - witness_tokens = min(config.Main.get("gameplay.modes.pactbreaker.clue.witness"), - math.floor(self.clue_pool / len(witnesses))) - if witness_tokens > 0: - for witness in witnesses: - witness.queue_message(messages["pactbreaker_drain_witness"]) - self.clue_pool -= witness_tokens - self.clue_tokens[witness] += witness_tokens - User.send_messages() elif killer_role == "wolf" and victim is self.in_stocks: victim.send(messages["pactbreaker_hunted_stocks"]) killer.send(messages["pactbreaker_hunter_stocks"].format(victim))