Skip to content

Commit

Permalink
Minor tweaks
Browse files Browse the repository at this point in the history
- In pactbreaker, drawing a clue card at square now always gives 2
  tokens, rather than 1 if only two people drew clues.
- Remove !time's phase restrictions to allow it to work with custom
  phases.
- Set up timers as part of phase transitions rather than independently.
- Dullahan can no longer kill targets not on their list.
- Maybe some other things too, dunno. Probably not important ;)
  • Loading branch information
skizzerz committed Dec 24, 2024
1 parent 954d8f6 commit a15acac
Show file tree
Hide file tree
Showing 9 changed files with 375 additions and 325 deletions.
41 changes: 26 additions & 15 deletions messages/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -226,10 +226,10 @@
"whoami": ["whoami"],
"wiki": ["wiki"],

"north": ["north", "n"],
"east": ["east", "e"],
"south": ["south", "s"],
"west": ["west", "w"],
"hide": ["hide"],
"run": ["run"],
"search": ["search"],
"chase": ["chase"],
"feed": ["feed"],
"forest": ["forest"],
"square": ["square"],
Expand Down Expand Up @@ -1167,6 +1167,7 @@
"doomsayer_notify": "You are {=doomsayer!role:article} {=doomsayer!role:bold}. You can see how bad luck will befall someone at night by using \"{=see!command} <nick>\" on them. You may also use \"{=kill!command} <nick>\" to kill a villager.",
"prophet_notify": "You are {=prophet!role:article} {=prophet!role:bold}. Each night you may pray to learn one player who has a particular role. Use \"{=pray!command} <role>\" in PM to learn who has that role.",
"dullahan_targets_dead": "All your targets are already dead!",
"dullahan_not_target": "{0:@} isn't one of your targets, so killing them would be a waste.",
"dullahan_notify": "You are {=dullahan!role:article} {=dullahan!role:bold}. Every night, you may kill someone by using \"{=kill!command} <nick>\". You win when all your targets are dead.",
"dullahan_targets": "Targets: {0:join}",
"dullahan_remaining_targets": "Remaining targets: {0:join}",
Expand Down Expand Up @@ -1218,21 +1219,31 @@
"endgame_role_player_short": "{0:@}",
"endgame_role_player_long": "{0:@} ({1:join})",
"endgame_role_msg": "The {0!role:plural({1})} {=was,were:plural({1})} {1:join}.",
"sleepy_nightmare_begin": "While walking through the woods, you hear the clopping of hooves behind you. Turning around, you see a large black horse with dark red eyes and flames where its mane and tail would be. After a brief period of time, it starts chasing after you! You think if you can cross the bridge over the nearby river you'll be safe, but your surroundings are almost unrecognizable in this darkness.",
"sleepy_nightmare_navigate": "You can pm me \"{=north!command}\", \"{=east!command}\", \"{=south!command}\", and \"{=west!command}\", or their abbreviations \"n\", \"e\", \"s\", and \"w\" to navigate.",
"sleepy_nightmare_0": "You find yourself deep in the heart of the woods, with imposing trees covering up what little light exists with their dense canopy. The paths here are very twisty, and it's easy to wind up going in circles if one is not careful. Directions are {0}.",
"sleepy_nightmare_1": "You come across a small creek, the water babbling softly in the night as if nothing is amiss. As you approach, a flock of ravens bathing there disperses into all directions. Directions are {0}.",
"sleepy_nightmare_2": "The treeline starts thinning and you start feeling fresh air for the first time in a while, you must be getting close to the edge of the woods! Directions are {0}.",
"sleepy_nightmare_wake": "You break clear of the woods and see a roaring river ahead with a rope bridge going over it. You sprint to the bridge with the beast hot on your tail, your adrenaline overcoming your tired legs as you push yourself for one final burst. You make it across the bridge, and not a moment too soon as the sun starts rising up, causing you to wake from your dream in a cold sweat.",
"sleepy_nightmare_fake_1": "You break clear of the woods and see a roaring river ahead. However, look as you may you are unable to find any means of crossing it. Knowing how expansive the river is, and how fast the beast can chase you if it isn't being slowed down by the foliage, you think it's best to look for the correct side of the woods again by going back in. Cursing your bad luck, you head back into the woods.",
"sleepy_nightmare_fake_2": "You break clear of the woods only to find an expansive plains ahead of you, with no river in sight. You must have found your way out through the wrong side of the woods! Attempting to circle around the woods would result in the beast catching you in short order, so you softly curse at your bad luck as you head back into the woods to find the correct path.",
"sleepy_nightmare_invalid_direction": "That way lies madness and certain death.",
"sleepy_nightmare_restart": "You find yourself back where you started...",
"sleepy_nightmare_death": "As the sun starts rising, your legs give out, causing the beast to descend upon you and snuff out your life.",
"sleepy_nightmare_start_dullahan": "You track down {0:@} in the woods during the night and begin chasing down your quarry! Use \"{=chase!command}\" to give chase at full speed or \"{=search!command}\" to slow your pace and detect if your target has attempted to hide.",
"sleepy_nightmare_start_target": "While walking through the woods, you hear the clopping of hooves behind you. Turning around, you see a headless horseman beginning to chase after you! You think if you can cross the bridge over the nearby river you'll be safe, or you could try hiding and hoping the horseman passes you by. Use \"{=run!command}\" to run towards the river or \"{=hide!command}\" to attempt to hide.",
"sleepy_nightmare_start_target_multiple": "While walking through the woods, you hear the clopping of hooves behind you. Turning around, you see {0:bold} headless horsemen beginning to chase after you! You think if you can cross the bridge over the nearby river you'll be safe, or you could try hiding and hoping the horsemen pass you by. Use \"{=run!command}\" to run towards the river or \"{=hide!command}\" to attempt to hide.",
"sleepy_nightmare_timer_notify": "You only have {0} seconds for each decision, so act quickly!",
"sleepy_nightmare_target_step_0": "You find yourself deep in the heart of the woods, with imposing trees covering up what little moonlight exists with their dense canopy. The path ahead seems to strech on as far as you can see, and you think that you would need to run [b]4[/b] more times to make it to safety.",
"sleepy_nightmare_target_step_1": "You come across a small creek, the water babbling softly in the night as if nothing is amiss. As you approach, a flock of ravens bathing there disperses into all directions. You think that you would need to run [b]3[/b] more times to make it to safety.",
"sleepy_nightmare_target_step_2": "The treeline starts thinning and you start feeling fresh air for the first time in a while, you must be getting close to the edge of the woods! You think that you would need to run [b]2[/b] more times to make it to safety.",
"sleepy_nightmare_target_step_3": "You break clear of the woods into an expansive plains and see a roaring river ahead with a rope bridge going over it. The tall grass of the plains could provide some cover if you lay low, or you could make one final push in hopes that you make it to safety.",
"sleepy_nightmare_dullahan_step": "Your target remains ahead of you. You know that a river lies in the direction they are running, but the supernatural curse that gives you life also forbids you from crossing running water. You estimate your quarry will reach the bridge over the river should they run {0:bold} more {=time,times:plural({0})}.",
"sleepy_nightmare_escape_run": "You sprint to the bridge with the {=rider,riders:plural({0})} hot on your tail, your adrenaline overcoming your tired legs as you push yourself for one final burst. You make it across the bridge while the {=horseman remains,horsemen remain:plural({0})} behind, seemingly unable to cross over the running water.",
"sleepy_nightmare_escape_hide": "You momentarily break line of sight with your {=pursuer,pursuers:plural({0})} and take the opportunity to dive for cover. You hold your breath for what feels like an eternity as they finally rush past you. After a few more minutes, you gather enough courage to sneak back to the village.",
"sleepy_nightmare_caught": "Your attempts to evade your {=pursuer,pursuers:plural({0})} fail as they catch you...",
"sleepy_nightmare_kill": "You catch up with {0:@} with an evil grin on your face as you raise your whip...",
"sleepy_nightmare_fail_river": "Certain that your quarry has chosen to lay down in the grassy plains, you slow your pace to check for signs of movement or unnaturally flat grass. Looking up, you spot your target on the bridge, crossing to the other side of the river. Now that your target has successfully evaded you, you feel no compulsion to attack them in the future.",
"sleepy_nightmare_fail_hide": "As you continue thundering down the path, you realise something is amiss as your quarry is nowhere to be seen! You search around for some time, but are unable to find them. Now that your target has successfully evaded you, you feel no compulsion to attack them in the future.",
"sleepy_nightmare_success": "You have chosen to {0!command:bold}.",
"sleepy_nightmare_acted": "You have already made your choice!",
"sleepy_nightmare_dullahan_idle": "Because you did not act in time, you are consumed by the thrill of the hunt as you give chase to your target.",
"sleepy_nightmare_target_idle": "Because you did not act in time, your fight-or-flight response urges you to run away as fast as you can.",
"sleepy_priest_death": "The sky suddenly darkens as a thunderstorm appears from nowhere. The bell on the newly-abandoned church starts ringing in sinister tones before the building is struck repeatedly by lightning, setting it alight in a raging inferno...",
"sleepy_doomsayer_turn": "You feel something rushing into you and taking control over your mind and body. It causes you to rapidly start transforming into a werewolf, and you realize your vision powers can now be used to inflict malady on the unwary. You are now {=doomsayer!role:article} {=doomsayer!role:bold}.",
"sleepy_succubus_turn": "You feel something rushing into you and taking control over your mind and body. You are now {=succubus!role:article} {=succubus!role:bold}. Your job is to entrance the village, bringing them all under your absolute control.",
"sleepy_demoniac_turn": "You feel something rushing into you and taking control over your mind and body, showing you your new purpose in life. There are far greater evils than the wolves lurking in the shadows, and by sacrificing all of the wolves, you can unleash those evils upon the world. You are now {=demoniac!role:article} {=demoniac!role:bold}.",
"sleepy_jester_turn": "You hear dark whispers promising you power and the ability to fight back against all that is wrong with the world. You need only to shuffle off your mortal coil, they say. You cackle madly, thinking that to be a small price to pay. You are now {=jester!role:article} {=jester!role:bold}.",
"sleepy_monster_turn": "You feel something rushing into you and taking control over your mind and body. You don't need the wolves in order to ruin the village, you can do it all yourself! You are now {=monster!role:article} {=monster!role:bold}.",
"fquit_fail": "Forcing a live player to leave must be done in channel.",
"demoniac_win": "Game over! All the wolves are dead! As the villagers start preparing the BBQ, a sudden flash illuminates the sky. Demonic spirits emerge around the sacrificed wolves and possess all villagers, causing the {=demoniac,demoniacs:plural({0})} to win.",
"succubus_win": "Game over! The {=succubus,succubi:plural({0})} {=has,have:plural({0})} completely enthralled the village, making them officers in an ever-growing army set on spreading their {=master's,masters':plural({0})} control and influence throughout the entire world.",
Expand Down
29 changes: 15 additions & 14 deletions src/defaultsettings.yml
Original file line number Diff line number Diff line change
Expand Up @@ -1214,28 +1214,29 @@ gameplay: &gameplay
_desc: Settings related to the nightmare mechanic in the sleepy mode.
_type: dict
_default:
chance:
steps:
_desc: >
How often a nightmare will occur. Set to 0 to disable nightmares. 1 or above will guarantee
a nightmare will occur each night. A value between 0 and 1 is the percentage chance a nightmare
will occur (e.g. 0.42 is a 42% chance a nightmare will occur). If multiple people are allowed to
have nightmares (see gameplay.modes.sleepy.nightmare.max), this is rolled once per allowed player.
_type:
- float
- int
_default: 0.2
max:
_desc: The maximum number of people that can have a nightmare each night.
How many steps the chased needs to move forwards in order to escape the nightmare.
Reducing this makes it easier for chased to escape, increasing it makes it more difficult.
The value must be between 1 and 4, inclusive.
_type: int
_default: 1
_default: 3
time:
_desc: >
How long each round of the nightmare lasts at most. Chased who do not lock in a command in time
will default to run, whereas dullahans who do not lock in a command in time will default to chase.
No warning points are given for failing to meet time limits. The nightmare will take at most
time * steps seconds in total. Setting this to 0 disables timers during nightmares.
_type: int
_default: 20
turn:
_desc: >
How likely certain roles (seer, harlot, cultist) are to change into other roles when priest dies.
How likely certain roles (seer, harlot) are to change into other roles when priest dies.
A value between 0 and 1 is the percentage chance for these roles to turn (e.g. 0.42 is a 42% chance).
_type:
- float
- int
_default: 0.6
_default: 0.4
weight:
_desc: How likely this mode is to appear if there are no votes for gamemodes.
_type: int
Expand Down
10 changes: 4 additions & 6 deletions src/gamecmds.py
Original file line number Diff line number Diff line change
Expand Up @@ -183,11 +183,13 @@ def on_reconfigure_stats(evt: Event, var: GameState, roleset: Counter, reason: s
global LAST_STATS
LAST_STATS = None

@command("time", pm=True, phases=("join", "day", "night"))
@command("time", pm=True)
def timeleft(wrapper: MessageDispatcher, message: str):
"""Returns the time left until the next day/night transition."""
global LAST_TIME
var = wrapper.game_state
if var is None:
return

if wrapper.public:
if LAST_TIME and LAST_TIME + timedelta(seconds=config.Main.get("ratelimits.time")) > datetime.now():
Expand All @@ -198,12 +200,8 @@ def timeleft(wrapper: MessageDispatcher, message: str):

if var.current_phase == "join":
dur = int((pregame.CAN_START_TIME - datetime.now()).total_seconds())
msg = None
if dur > 0:
msg = messages["start_timer"].format(dur)

if msg is not None:
wrapper.reply(msg)
wrapper.reply(messages["start_timer"].format(dur))

if var.current_phase in trans.TIMERS or f"{var.current_phase}_limit" in trans.TIMERS:
if var.current_phase == "day":
Expand Down
24 changes: 11 additions & 13 deletions src/gamemodes/pactbreaker.py
Original file line number Diff line number Diff line change
Expand Up @@ -108,17 +108,6 @@ def __init__(self, arg=""):

def startup(self):
super().startup()
self.night_kill_messages.clear()
self.active_players.clear()
self.in_stocks = None
self.voted.clear()
self.drained.clear()
self.protected.clear()
self.turned.clear()
self.collected_evidence.clear()
self.visiting.clear()
self.killing.clear()
self.clue_tokens.clear()
# register !visit, !id, and !kill, remove all role commands
self.visit_command.register()
self.id_command.register()
Expand Down Expand Up @@ -152,6 +141,16 @@ def teardown(self):
vigilante_kill.register()
vigilante_retract.register()
vigilante_pass.register()
# clear user containers
self.visiting.clear()
self.killing.clear()
self.drained.clear()
self.protected.clear()
self.turned.clear()
self.voted.clear()
self.active_players.clear()
self.collected_evidence.clear()
self.clue_tokens.clear()

def on_del_player(self, evt: Event, var: GameState, player, all_roles, death_triggers):
# self.night_kills isn't updated because it is short-lived
Expand Down Expand Up @@ -432,8 +431,7 @@ def on_night_kills(self, evt: Event, var: GameState):
loc = self.visiting[visitor].name
visitor.send(messages[f"pactbreaker_{loc}_empty"])
elif len(shares) > 1:
num_tokens = min(len(shares) - 1,
math.floor(self.clue_pool / len(shares)),
num_tokens = min(math.floor(self.clue_pool / len(shares)),
config.Main.get("gameplay.modes.pactbreaker.clue.square"))
for visitor in shares:
loc = self.visiting[visitor].name
Expand Down
Loading

0 comments on commit a15acac

Please sign in to comment.