Add unlimited new-game
Add pitcher substitution Add AI pitcher subs
This commit is contained in:
parent
e850ee5519
commit
7d54d9ea34
164
cogs/gameplay.py
164
cogs/gameplay.py
@ -13,7 +13,7 @@ import sqlalchemy
|
|||||||
from sqlmodel import func, or_
|
from sqlmodel import func, or_
|
||||||
|
|
||||||
from api_calls import db_get
|
from api_calls import db_get
|
||||||
from command_logic.logic_gameplay import bunts, chaos, complete_game, doubles, flyballs, frame_checks, get_full_roster_from_sheets, checks_log_interaction, complete_play, get_scorebug_embed, groundballs, hit_by_pitch, homeruns, is_game_over, lineouts, manual_end_game, new_game_checks, new_game_conflicts, popouts, read_lineup, select_ai_reliever, show_defense_cards, singles, starting_pitcher_dropdown_view, steals, strikeouts, sub_batter_dropdown_view, substitute_player, triples, undo_play, update_game_settings, walks, xchecks, activate_last_play
|
from command_logic.logic_gameplay import bunts, chaos, complete_game, doubles, flyballs, frame_checks, get_full_roster_from_sheets, checks_log_interaction, complete_play, get_scorebug_embed, groundballs, hit_by_pitch, homeruns, is_game_over, lineouts, manual_end_game, new_game_checks, new_game_conflicts, popouts, read_lineup, relief_pitcher_dropdown_view, select_ai_reliever, show_defense_cards, singles, starting_pitcher_dropdown_view, steals, strikeouts, sub_batter_dropdown_view, substitute_player, triples, undo_play, update_game_settings, walks, xchecks, activate_last_play
|
||||||
from dice import ab_roll
|
from dice import ab_roll
|
||||||
from exceptions import *
|
from exceptions import *
|
||||||
import gauntlets
|
import gauntlets
|
||||||
@ -23,9 +23,9 @@ from helpers import CARDSETS, DEFENSE_LITERAL, PD_PLAYERS_ROLE_NAME, SELECT_CARD
|
|||||||
from in_game.ai_manager import get_starting_pitcher, get_starting_lineup
|
from in_game.ai_manager import get_starting_pitcher, get_starting_lineup
|
||||||
from in_game.game_helpers import PUBLIC_FIELDS_CATEGORY_NAME, legal_check
|
from in_game.game_helpers import PUBLIC_FIELDS_CATEGORY_NAME, legal_check
|
||||||
from in_game.gameplay_models import GameCardsetLink, Lineup, Play, Session, engine, player_description, select, Game
|
from in_game.gameplay_models import GameCardsetLink, Lineup, Play, Session, engine, player_description, select, Game
|
||||||
from in_game.gameplay_queries import get_cardset_or_none, get_one_lineup, get_position, get_channel_game_or_none, get_active_games_by_team, get_game_lineups, get_team_or_none
|
from in_game.gameplay_queries import get_cardset_or_none, get_one_lineup, get_plays_by_pitcher, get_position, get_channel_game_or_none, get_active_games_by_team, get_game_lineups, get_team_or_none
|
||||||
|
|
||||||
from utilities.buttons import Confirm, ScorebugButtons, ask_confirm
|
from utilities.buttons import Confirm, ScorebugButtons, ask_confirm, ask_with_buttons
|
||||||
from utilities.dropdown import DropdownView
|
from utilities.dropdown import DropdownView
|
||||||
|
|
||||||
|
|
||||||
@ -434,7 +434,7 @@ class Gameplay(commands.Cog):
|
|||||||
channel_id=interaction.channel_id,
|
channel_id=interaction.channel_id,
|
||||||
season=current['season'],
|
season=current['season'],
|
||||||
week=current['week'],
|
week=current['week'],
|
||||||
first_message=None if interaction.message is None else interaction.message.channel.id,
|
first_message=None if interaction.message is None else interaction.message.id,
|
||||||
ai_team='away' if is_home else 'home',
|
ai_team='away' if is_home else 'home',
|
||||||
away_roster_id=69 if is_home else int(roster.value),
|
away_roster_id=69 if is_home else int(roster.value),
|
||||||
home_roster_id=int(roster.value) if is_home else 69,
|
home_roster_id=int(roster.value) if is_home else 69,
|
||||||
@ -552,7 +552,7 @@ class Gameplay(commands.Cog):
|
|||||||
channel_id=interaction.channel_id,
|
channel_id=interaction.channel_id,
|
||||||
season=current['season'],
|
season=current['season'],
|
||||||
week=week_num,
|
week=week_num,
|
||||||
first_message=None if interaction.message is None else interaction.message.channel.id,
|
first_message=None if interaction.message is None else interaction.message.id,
|
||||||
ai_team='away' if away_team.is_ai else 'home',
|
ai_team='away' if away_team.is_ai else 'home',
|
||||||
game_type='exhibition'
|
game_type='exhibition'
|
||||||
)
|
)
|
||||||
@ -689,8 +689,106 @@ class Gameplay(commands.Cog):
|
|||||||
view=view
|
view=view
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
# TODO: add new-game unlimited, and ranked
|
# TODO: add new-game unlimited, and ranked
|
||||||
|
@group_new_game.command(name='unlimited', description='Start a new Unlimited game against another human')
|
||||||
|
@app_commands.checks.has_any_role(PD_PLAYERS_ROLE_NAME)
|
||||||
|
async def new_game_unlimited_command(self, interaction: discord.Interaction, away_team_abbrev: str, home_team_abbrev: str):
|
||||||
|
await interaction.response.defer()
|
||||||
|
|
||||||
|
with Session(engine) as session:
|
||||||
|
teams = await new_game_checks(session, interaction, away_team_abbrev, home_team_abbrev)
|
||||||
|
if teams is None:
|
||||||
|
logger.error(f'Received None from new_game_checks, cancelling new game')
|
||||||
|
return
|
||||||
|
|
||||||
|
away_team = teams['away_team']
|
||||||
|
home_team = teams['home_team']
|
||||||
|
|
||||||
|
if away_team.is_ai or home_team.is_ai:
|
||||||
|
await interaction.edit_original_response(
|
||||||
|
content=f'Unlimited games are for two human-run teams. To play against the AI, you can play `mlb-campaign`, `gauntlet`, or `exhibition` game modes.'
|
||||||
|
)
|
||||||
|
return
|
||||||
|
|
||||||
|
current = await db_get('current')
|
||||||
|
week_num = current['week']
|
||||||
|
logger.info(f'gameplay - new_game_unlimited - Season: {current["season"]} / Week: {week_num} / Away Team: {away_team.description} / Home Team: {home_team.description}')
|
||||||
|
|
||||||
|
this_game = Game(
|
||||||
|
away_team_id=away_team.id,
|
||||||
|
home_team_id=home_team.id,
|
||||||
|
away_roster_id=None,
|
||||||
|
home_roster_id=None,
|
||||||
|
channel_id=interaction.channel_id,
|
||||||
|
season=current['season'],
|
||||||
|
week=week_num,
|
||||||
|
first_message=None if interaction.message is None else interaction.message.id,
|
||||||
|
game_type='exhibition'
|
||||||
|
)
|
||||||
|
|
||||||
|
await interaction.edit_original_response(
|
||||||
|
content=f'Let\'s get set up for **{away_team.lname}** @ **{home_team.lname}**!'
|
||||||
|
)
|
||||||
|
|
||||||
|
away_role = await team_role(interaction, away_team)
|
||||||
|
home_role = await team_role(interaction, home_team)
|
||||||
|
|
||||||
|
away_roster_id = await ask_with_buttons(
|
||||||
|
interaction=interaction,
|
||||||
|
button_options=[
|
||||||
|
'Primary', 'Secondary', 'Ranked'
|
||||||
|
],
|
||||||
|
question=f'{away_role.mention}\nWhich roster should I pull for you?',
|
||||||
|
delete_question=False,
|
||||||
|
confirmation_message=f'Got it! As soon as the {home_team.sname} select their roster, I will pull them both in at once.'
|
||||||
|
)
|
||||||
|
|
||||||
|
home_roster_id = await ask_with_buttons(
|
||||||
|
interaction=interaction,
|
||||||
|
button_options=[
|
||||||
|
'Primary', 'Secondary', 'Ranked'
|
||||||
|
],
|
||||||
|
question=f'{home_role.mention}\nWhich roster should I pull for you?',
|
||||||
|
delete_question=False,
|
||||||
|
confirmation_message=f'Got it! Off to Sheets I go for the {away_team.abbrev} roster...'
|
||||||
|
)
|
||||||
|
|
||||||
|
if away_roster_id and home_roster_id:
|
||||||
|
if away_roster_id == 'Primary':
|
||||||
|
away_roster_id = 1
|
||||||
|
elif away_roster_id == 'Secondary':
|
||||||
|
away_roster_id = 2
|
||||||
|
else:
|
||||||
|
away_roster_id = 3
|
||||||
|
|
||||||
|
if home_roster_id == 'Primary':
|
||||||
|
home_roster_id = 1
|
||||||
|
elif home_roster_id == 'Secondary':
|
||||||
|
home_roster_id = 2
|
||||||
|
else:
|
||||||
|
home_roster_id = 3
|
||||||
|
|
||||||
|
logger.info(f'Setting roster IDs - away: {away_roster_id} / home: {home_roster_id}')
|
||||||
|
this_game.away_roster_id = away_roster_id
|
||||||
|
this_game.home_roster_id = home_roster_id
|
||||||
|
session.add(this_game)
|
||||||
|
session.commit()
|
||||||
|
|
||||||
|
logger.info(f'Pulling away team\'s roster')
|
||||||
|
away_roster = await get_full_roster_from_sheets(session, interaction, self.sheets, this_game, away_team, away_roster_id)
|
||||||
|
|
||||||
|
# if away_roster:
|
||||||
|
logger.info(f'Pulling home team\'s roster')
|
||||||
|
await interaction.channel.send(
|
||||||
|
content=f'And now for the {home_team.abbrev} sheet...'
|
||||||
|
)
|
||||||
|
home_roster = await get_full_roster_from_sheets(session, interaction, self.sheets, this_game, home_team,home_roster_id)
|
||||||
|
|
||||||
|
# if home_roster:
|
||||||
|
await interaction.channel.send(
|
||||||
|
content=f'{away_role.mention} @ {home_role.mention}\n\nThe game is set, both of you may run `/set <starting-pitcher and lineup>` to start!'
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
@commands.command(name='force-endgame', help='Mod: Force a game to end without stats')
|
@commands.command(name='force-endgame', help='Mod: Force a game to end without stats')
|
||||||
async def force_end_game_command(self, ctx: commands.Context):
|
async def force_end_game_command(self, ctx: commands.Context):
|
||||||
@ -750,8 +848,11 @@ class Gameplay(commands.Cog):
|
|||||||
)
|
)
|
||||||
return
|
return
|
||||||
|
|
||||||
this_team = this_game.away_team if this_game.ai_team == 'home' else this_game.home_team
|
if this_game.away_team.gmid == interaction.user.id:
|
||||||
if interaction.user.id != this_team.gmid:
|
this_team = this_game.away_team
|
||||||
|
elif this_game.home_team.gmid == interaction.user.id:
|
||||||
|
this_team = this_game.home_team
|
||||||
|
else:
|
||||||
logger.info(f'{interaction.user.name} tried to run a command in Game {this_game.id} when they aren\'t a GM in the game.')
|
logger.info(f'{interaction.user.name} tried to run a command in Game {this_game.id} when they aren\'t a GM in the game.')
|
||||||
await interaction.edit_original_response(content='Bruh. Only GMs of the active teams can pull lineups.')
|
await interaction.edit_original_response(content='Bruh. Only GMs of the active teams can pull lineups.')
|
||||||
return
|
return
|
||||||
@ -796,8 +897,11 @@ class Gameplay(commands.Cog):
|
|||||||
)
|
)
|
||||||
return
|
return
|
||||||
|
|
||||||
this_team = this_game.human_team
|
if this_game.away_team.gmid == interaction.user.id:
|
||||||
if interaction.user.id != this_team.gmid:
|
this_team = this_game.away_team
|
||||||
|
elif this_game.home_team.gmid == interaction.user.id:
|
||||||
|
this_team = this_game.home_team
|
||||||
|
else:
|
||||||
logger.info(f'{interaction.user.name} tried to run a command in Game {this_game.id} when they aren\'t a GM in the game.')
|
logger.info(f'{interaction.user.name} tried to run a command in Game {this_game.id} when they aren\'t a GM in the game.')
|
||||||
await interaction.edit_original_response(content='Bruh. Only GMs of the active teams can pull lineups.')
|
await interaction.edit_original_response(content='Bruh. Only GMs of the active teams can pull lineups.')
|
||||||
return
|
return
|
||||||
@ -904,6 +1008,46 @@ class Gameplay(commands.Cog):
|
|||||||
bat_view = sub_batter_dropdown_view(session, this_game, owner_team, this_order, [interaction.user])
|
bat_view = sub_batter_dropdown_view(session, this_game, owner_team, this_order, [interaction.user])
|
||||||
await interaction.edit_original_response(content=f'### {owner_team.lname} Substitution', view=bat_view)
|
await interaction.edit_original_response(content=f'### {owner_team.lname} Substitution', view=bat_view)
|
||||||
|
|
||||||
|
@group_substitution.command(name='pitcher', description='Make a pitching substitution')
|
||||||
|
async def sub_pitcher_command(self, interaction: discord.Interaction, batting_order: Literal['dh-spot', '1', '2', '3', '4', '5', '6', '7', '8', '9', '10'] = '10'):
|
||||||
|
with Session(engine) as session:
|
||||||
|
this_game, owner_team, this_play = await checks_log_interaction(session, interaction, command_name='substitute batter')
|
||||||
|
|
||||||
|
if owner_team != this_play.pitcher.team:
|
||||||
|
logger.warning(f'User {interaction.user.name} ({owner_team.abbrev}) tried to run a sub for the {this_play.pitcher.team.lname}')
|
||||||
|
await interaction.edit_original_response(
|
||||||
|
content=f'Please run pitcher subs when your team is on defense. If you are pinch-hitting for a pitcher already in the lineup, use `/substitute batter`'
|
||||||
|
)
|
||||||
|
return
|
||||||
|
|
||||||
|
if batting_order != '10' and this_play.pitcher.batting_order == 10:
|
||||||
|
forfeit_dh = await ask_confirm(
|
||||||
|
interaction,
|
||||||
|
f'Are you sure you want to forfeit the DH?'
|
||||||
|
)
|
||||||
|
if not forfeit_dh:
|
||||||
|
await interaction.edit_original_response(
|
||||||
|
content=f'Fine, be that way.'
|
||||||
|
)
|
||||||
|
return
|
||||||
|
|
||||||
|
if not this_play.is_new_inning:
|
||||||
|
pitcher_plays = get_plays_by_pitcher(session, this_game, this_play.pitcher)
|
||||||
|
batters_faced = sum(1 for x in pitcher_plays if x.pa == 1)
|
||||||
|
|
||||||
|
if batters_faced < 3:
|
||||||
|
await interaction.edit_original_response(
|
||||||
|
content=f'Looks like **{this_play.pitcher.player.name}** has only faced {batters_faced} of the 3-batter minimum.'
|
||||||
|
)
|
||||||
|
return
|
||||||
|
|
||||||
|
rp_view = relief_pitcher_dropdown_view(session, this_game, this_play.pitcher.team, batting_order, responders=[interaction.user])
|
||||||
|
rp_message = await interaction.edit_original_response(
|
||||||
|
content=f'### {this_play.pitcher.team.lname} Relief Pitcher',
|
||||||
|
view=rp_view
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
group_log = app_commands.Group(name='log', description='Log a play in this channel\'s game')
|
group_log = app_commands.Group(name='log', description='Log a play in this channel\'s game')
|
||||||
|
|
||||||
@group_log.command(name='flyball', description='Flyballs: a, b, ballpark, bq, c')
|
@group_log.command(name='flyball', description='Flyballs: a, b, ballpark, bq, c')
|
||||||
|
|||||||
@ -20,7 +20,7 @@ from in_game.gameplay_models import BattingCard, Card, Game, Lineup, PositionRat
|
|||||||
from in_game.gameplay_queries import get_active_games_by_team, get_available_batters, get_batter_card, get_batting_statline, get_game_cardset_links, get_or_create_ai_card, get_pitcher_runs_by_innings, get_pitching_statline, get_plays_by_pitcher, get_position, get_available_pitchers, get_card_or_none, get_channel_game_or_none, get_db_ready_decisions, get_db_ready_plays, get_game_lineups, get_last_team_play, get_one_lineup, get_player_id_from_dict, get_player_name_from_dict, get_player_or_none, get_sorted_lineups, get_team_or_none, get_players_last_pa, post_game_rewards
|
from in_game.gameplay_queries import get_active_games_by_team, get_available_batters, get_batter_card, get_batting_statline, get_game_cardset_links, get_or_create_ai_card, get_pitcher_runs_by_innings, get_pitching_statline, get_plays_by_pitcher, get_position, get_available_pitchers, get_card_or_none, get_channel_game_or_none, get_db_ready_decisions, get_db_ready_plays, get_game_lineups, get_last_team_play, get_one_lineup, get_player_id_from_dict, get_player_name_from_dict, get_player_or_none, get_sorted_lineups, get_team_or_none, get_players_last_pa, post_game_rewards
|
||||||
from in_game.managerai_responses import DefenseResponse
|
from in_game.managerai_responses import DefenseResponse
|
||||||
from utilities.buttons import ButtonOptions, Confirm, ask_confirm, ask_with_buttons
|
from utilities.buttons import ButtonOptions, Confirm, ask_confirm, ask_with_buttons
|
||||||
from utilities.dropdown import DropdownView, SelectBatterSub, SelectStartingPitcher, SelectViewDefense
|
from utilities.dropdown import DropdownView, SelectBatterSub, SelectReliefPitcher, SelectStartingPitcher, SelectViewDefense
|
||||||
from utilities.embeds import image_embed
|
from utilities.embeds import image_embed
|
||||||
from utilities.pages import Pagination
|
from utilities.pages import Pagination
|
||||||
|
|
||||||
@ -336,6 +336,23 @@ def starting_pitcher_dropdown_view(session: Session, this_game: Game, human_team
|
|||||||
return DropdownView(dropdown_objects=[sp_selection])
|
return DropdownView(dropdown_objects=[sp_selection])
|
||||||
|
|
||||||
|
|
||||||
|
def relief_pitcher_dropdown_view(session: Session, this_game: Game, human_team: Team, batting_order: int, responders: list[discord.User] = None):
|
||||||
|
pitchers = get_available_pitchers(session, this_game, human_team)
|
||||||
|
logger.info(f'sorted pitchers: {pitchers}')
|
||||||
|
if len(pitchers) == 0:
|
||||||
|
log_exception(MissingRosterException, 'No pitchers were found to select RP')
|
||||||
|
rp_selection = SelectReliefPitcher(
|
||||||
|
this_game=this_game,
|
||||||
|
this_team=human_team,
|
||||||
|
batting_order=batting_order,
|
||||||
|
session=session,
|
||||||
|
options=[SelectOption(label=f'{x.player.name_with_desc} (S{x.pitcherscouting.pitchingcard.starter_rating}/R{x.pitcherscouting.pitchingcard.relief_rating})', value=x.id) for x in pitchers],
|
||||||
|
placeholder='Select your relief pitcher',
|
||||||
|
responders=responders
|
||||||
|
)
|
||||||
|
return DropdownView(dropdown_objects=[rp_selection])
|
||||||
|
|
||||||
|
|
||||||
def sub_batter_dropdown_view(session: Session, this_game: Game, human_team: Team, batting_order: int, responders: list[discord.User]):
|
def sub_batter_dropdown_view(session: Session, this_game: Game, human_team: Team, batting_order: int, responders: list[discord.User]):
|
||||||
batters = get_available_batters(session, this_game, human_team)
|
batters = get_available_batters(session, this_game, human_team)
|
||||||
logger.info(f'batters: {batters}')
|
logger.info(f'batters: {batters}')
|
||||||
@ -363,7 +380,7 @@ async def read_lineup(session: Session, interaction: discord.Interaction, this_g
|
|||||||
)
|
)
|
||||||
if len(existing_lineups) > 1:
|
if len(existing_lineups) > 1:
|
||||||
await interaction.edit_original_response(
|
await interaction.edit_original_response(
|
||||||
f'It looks like the {lineup_team.sname} already have a lineup. Run `/substitution` to make changes.'
|
f'It looks like the {lineup_team.sname} already have a lineup. Run `/substitute` to make changes.'
|
||||||
)
|
)
|
||||||
return
|
return
|
||||||
|
|
||||||
@ -2841,9 +2858,10 @@ def undo_play(session: Session, this_play: Play):
|
|||||||
new_player_ids = []
|
new_player_ids = []
|
||||||
new_players = session.exec(select(Lineup).where(Lineup.game == this_game, Lineup.after_play >= after_play_min)).all()
|
new_players = session.exec(select(Lineup).where(Lineup.game == this_game, Lineup.after_play >= after_play_min)).all()
|
||||||
logger.info(f'Subs to roll back: {new_players}')
|
logger.info(f'Subs to roll back: {new_players}')
|
||||||
for lineup in new_players:
|
for x in new_players:
|
||||||
new_players.append(lineup.id)
|
logger.info(f'Marking {x} for deletion')
|
||||||
old_player = session.get(Lineup, lineup.replacing_id)
|
new_player_ids.append(x.id)
|
||||||
|
old_player = session.get(Lineup, x.replacing_id)
|
||||||
old_player.active = True
|
old_player.active = True
|
||||||
session.add(old_player)
|
session.add(old_player)
|
||||||
|
|
||||||
@ -3786,13 +3804,16 @@ def substitute_player(session, this_play: Play, old_player: Lineup, new_player:
|
|||||||
replacing_id=old_player.id
|
replacing_id=old_player.id
|
||||||
)
|
)
|
||||||
logger.info(f'new_lineup: {new_lineup}')
|
logger.info(f'new_lineup: {new_lineup}')
|
||||||
|
|
||||||
session.add(new_lineup)
|
session.add(new_lineup)
|
||||||
|
|
||||||
logger.info(f'De-activating last player')
|
logger.info(f'De-activating last player')
|
||||||
old_player.active = False
|
old_player.active = False
|
||||||
|
|
||||||
session.add(old_player)
|
session.add(old_player)
|
||||||
|
|
||||||
|
logger.info(f'Updating play\'s pitcher')
|
||||||
|
this_play.pitcher = new_lineup
|
||||||
|
session.add(this_play)
|
||||||
|
|
||||||
session.commit()
|
session.commit()
|
||||||
session.refresh(new_lineup)
|
session.refresh(new_lineup)
|
||||||
return new_lineup
|
return new_lineup
|
||||||
|
|||||||
@ -325,6 +325,8 @@ INSULTS = [
|
|||||||
'Why are you even here? Get lost.',
|
'Why are you even here? Get lost.',
|
||||||
'Why are you even here? Scram.',
|
'Why are you even here? Scram.',
|
||||||
'Why are you even here? No one knows who you are.',
|
'Why are you even here? No one knows who you are.',
|
||||||
|
'HEY, DON\'T TOUCH ME!',
|
||||||
|
'Hey, don\'t touch me!'
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user