mirror of
https://github.com/solero/houdini.git
synced 2025-07-06 03:29:51 +00:00
add card-jitsu end game screen
This commit is contained in:
parent
ed38f66923
commit
0146804287
@ -78,8 +78,21 @@ async def handle_get_game_over(p, score: int):
|
||||
if p.room.id == 996:
|
||||
return
|
||||
|
||||
if p.room.game and not p.waddle and not p.table:
|
||||
# card-jitsus except snow have special handling
|
||||
card_jitsu_rooms = [995, 998, 997]
|
||||
is_card_jitsu = p.room.id in card_jitsu_rooms
|
||||
|
||||
# Waddle minigames don't normally need the end screen
|
||||
if p.waddle and not is_card_jitsu:
|
||||
return
|
||||
|
||||
if p.room.game and not p.table:
|
||||
coins_earned = determine_coins_earned(p, score)
|
||||
|
||||
if not is_card_jitsu:
|
||||
if await determine_coins_overdose(p, coins_earned):
|
||||
return await cheat_ban(p, p.id, comment="Coins overdose")
|
||||
|
||||
stamp_info = "", 0, 0, 0
|
||||
|
||||
if p.room.stamp_group:
|
||||
@ -88,6 +101,10 @@ async def handle_get_game_over(p, score: int):
|
||||
if stamp_info[1] == stamp_info[2]:
|
||||
coins_earned *= 2
|
||||
|
||||
if not is_card_jitsu:
|
||||
await p.update(
|
||||
coins=min(p.coins + coins_earned, p.server.config.max_coins)
|
||||
).apply()
|
||||
await p.send_xt("zo", p.coins, *stamp_info)
|
||||
|
||||
|
||||
|
@ -1,6 +1,7 @@
|
||||
import itertools
|
||||
import math
|
||||
import random
|
||||
import enum
|
||||
from collections import Counter
|
||||
from dataclasses import dataclass
|
||||
from typing import Dict, List, Union
|
||||
@ -10,6 +11,19 @@ from houdini.data.ninja import Card
|
||||
from houdini.handlers import XTPacket
|
||||
from houdini.penguin import Penguin
|
||||
|
||||
class CardStamp(enum.IntEnum):
|
||||
"""ID of Card-Jitsu stamps"""
|
||||
GRASSHOPPER = 230
|
||||
ELEMENTAL_WIN = 242
|
||||
FINE_STUDENT = 232
|
||||
FLAWLESS_VICTORY = 238
|
||||
ONE_ELEMENT = 244
|
||||
TRUE_NINJA = 234
|
||||
MATCH_MASTER = 240
|
||||
NINJA_MASTER = 236
|
||||
SENSEI_CARD = 246
|
||||
FULL_DOJO = 248
|
||||
|
||||
|
||||
@dataclass
|
||||
class Played:
|
||||
@ -44,7 +58,12 @@ class CardJitsuLogic(IWaddle):
|
||||
|
||||
ItemAwards = [4025, 4026, 4027, 4028, 4029, 4030, 4031, 4032, 4033, 104]
|
||||
PostcardAwards = {0: 177, 4: 178, 8: 179}
|
||||
StampAwards = {0: 230, 4: 232, 8: 234, 9: 236}
|
||||
StampAwards = {
|
||||
0: CardStamp.GRASSHOPPER,
|
||||
4: CardStamp.FINE_STUDENT,
|
||||
8: CardStamp.TRUE_NINJA,
|
||||
9: CardStamp.NINJA_MASTER,
|
||||
}
|
||||
StampGroupId = 38
|
||||
|
||||
def __init__(self, waddle):
|
||||
@ -235,7 +254,7 @@ async def ninja_rank_up(p, ranks=1):
|
||||
if rank in CardJitsuLogic.PostcardAwards:
|
||||
await p.add_inbox(p.server.postcards[CardJitsuLogic.PostcardAwards[rank]])
|
||||
if rank in CardJitsuLogic.StampAwards:
|
||||
await p.add_stamp(p.server.stamps[CardJitsuLogic.StampAwards[rank]])
|
||||
await p.add_card_jitsu_stamp(CardJitsuLogic.StampAwards[rank])
|
||||
await p.update(ninja_rank=p.ninja_rank + ranks).apply()
|
||||
return True
|
||||
|
||||
@ -266,20 +285,10 @@ async def ninja_progress(p, won=False):
|
||||
await ninja_rank_up(p)
|
||||
await p.send_xt('cza', p.ninja_rank)
|
||||
|
||||
async def ninja_stamps_earned(p):
|
||||
game_stamps = [stamp for stamp in p.server.stamps.values() if stamp.group_id == p.room.stamp_group]
|
||||
collected_stamps = [stamp for stamp in game_stamps if stamp.id in p.stamps]
|
||||
total_collected_stamps = len(collected_stamps)
|
||||
total_game_stamps = len(game_stamps)
|
||||
collected_stamps_string = '|'.join(str(stamp.id) for stamp in collected_stamps)
|
||||
await p.send_xt('cjsi', collected_stamps_string, total_collected_stamps, total_game_stamps)
|
||||
|
||||
|
||||
async def ninja_win(winner, loser):
|
||||
await ninja_progress(winner.penguin, won=True)
|
||||
await ninja_progress(loser.penguin, won=False)
|
||||
await ninja_stamps_earned(winner.penguin)
|
||||
await ninja_stamps_earned(loser.penguin)
|
||||
await winner.penguin.waddle.remove_penguin(winner.penguin)
|
||||
await loser.penguin.waddle.remove_penguin(loser.penguin)
|
||||
|
||||
@ -304,6 +313,8 @@ async def handle_update_game(p):
|
||||
@handlers.handler(XTPacket('lz', ext='z'))
|
||||
@handlers.waddle(CardJitsuLogic, CardJitsuMatLogic, SenseiLogic)
|
||||
async def handle_leave_game(p):
|
||||
# sending stamp info fixes the game taking a bit to close when quitting
|
||||
await p.send_card_jitsu_stamp_info()
|
||||
seat_id = p.waddle.get_seat_id(p)
|
||||
await p.waddle.send_xt('cz', p.safe_name, f=lambda penguin: penguin is not p)
|
||||
await p.waddle.send_xt('lz', seat_id, f=lambda penguin: penguin is not p)
|
||||
@ -357,9 +368,8 @@ async def handle_send_pick(p, action: str, card_id: int):
|
||||
winner_seat_id = p.waddle.get_round_winner()
|
||||
|
||||
if me.chosen.card.id == 256 or opponent.chosen.card.id == 256:
|
||||
stamp = p.server.stamps[246]
|
||||
await me.penguin.add_stamp(stamp, notify=True)
|
||||
await opponent.penguin.add_stamp(stamp, notify=True)
|
||||
await me.penguin.add_card_jitsu_stamp(CardStamp.SENSEI_CARD)
|
||||
await opponent.penguin.add_card_jitsu_stamp(CardStamp.SENSEI_CARD)
|
||||
|
||||
if me.chosen.card.power_id and me.chosen.card.power_id in CardJitsuLogic.OnPlayed:
|
||||
await p.waddle.send_xt('zm', 'power', seat_id, opponent_seat_id, me.chosen.card.power_id)
|
||||
@ -383,19 +393,18 @@ async def handle_send_pick(p, action: str, card_id: int):
|
||||
if winning_cards:
|
||||
await p.waddle.send_xt('czo', 0, winner_seat_id, *(card.id for card in winning_cards))
|
||||
|
||||
stamp = p.server.stamps[[244, 242][win_method]]
|
||||
await winner.penguin.add_stamp(stamp, notify=True)
|
||||
stamp = [CardStamp.ONE_ELEMENT, CardStamp.ELEMENTAL_WIN][win_method]
|
||||
await winner.penguin.add_card_jitsu_stamp(stamp)
|
||||
if all(not cards for cards in loser.bank.values()):
|
||||
stamp = p.server.stamps[238]
|
||||
await winner.penguin.add_stamp(stamp, notify=True)
|
||||
await winner.penguin.add_card_jitsu_stamp(
|
||||
CardStamp.FLAWLESS_VICTORY
|
||||
)
|
||||
if sum(1 for cards in winner.bank.values() for _ in cards) >= 9:
|
||||
stamp = p.server.stamps[248]
|
||||
await winner.penguin.add_stamp(stamp, notify=True)
|
||||
await winner.penguin.add_card_jitsu_stamp(CardStamp.FULL_DOJO)
|
||||
|
||||
await winner.penguin.update(ninja_matches_won=winner.penguin.ninja_matches_won+1).apply()
|
||||
if winner.penguin.ninja_matches_won == 25:
|
||||
stamp = p.server.stamps[240]
|
||||
await winner.penguin.add_stamp(stamp, notify=True)
|
||||
await winner.penguin.add_card_jitsu_stamp(CardStamp.MATCH_MASTER)
|
||||
|
||||
await ninja_win(winner, loser)
|
||||
else:
|
||||
@ -493,8 +502,7 @@ async def handle_send_sensei_pick(p, action: str, card_id: int):
|
||||
winner_seat_id = p.waddle.get_round_winner()
|
||||
|
||||
if me.chosen.card.id == 256 or sensei.chosen.card.id == 256:
|
||||
stamp = p.server.stamps[246]
|
||||
await p.add_stamp(stamp, notify=True)
|
||||
await me.penguin.add_card_jitsu_stamp(CardStamp.SENSEI_CARD)
|
||||
|
||||
if me.chosen.card.power_id and me.chosen.card.power_id in CardJitsuLogic.OnPlayed:
|
||||
await p.send_xt('zm', 'power', 1, 0, me.chosen.card.power_id)
|
||||
@ -518,21 +526,17 @@ async def handle_send_sensei_pick(p, action: str, card_id: int):
|
||||
await p.waddle.send_xt('czo', 0, winner_seat_id, *(card.id for card in winning_cards))
|
||||
|
||||
if winner == me:
|
||||
stamp = p.server.stamps[[244, 242][win_method]]
|
||||
await p.add_stamp(stamp, notify=True)
|
||||
stamp = [CardStamp.ONE_ELEMENT, CardStamp.ELEMENTAL_WIN][win_method]
|
||||
await me.penguin.add_card_jitsu_stamp(stamp)
|
||||
if all(not cards for cards in sensei.bank.values()):
|
||||
stamp = p.server.stamps[238]
|
||||
await p.add_stamp(stamp, notify=True)
|
||||
await me.penguin.add_card_jitsu_stamp(CardStamp.FLAWLESS_VICTORY)
|
||||
if sum(1 for cards in me.bank.values() for _ in cards) >= 9:
|
||||
stamp = p.server.stamps[248]
|
||||
await p.add_stamp(stamp, notify=True)
|
||||
await me.penguin.add_card_jitsu_stamp(CardStamp.FULL_DOJO)
|
||||
|
||||
await p.update(ninja_matches_won=p.ninja_matches_won + 1).apply()
|
||||
if p.ninja_matches_won == 25:
|
||||
stamp = p.server.stamps[240]
|
||||
await p.add_stamp(stamp, notify=True)
|
||||
await me.penguin.add_card_jitsu_stamp(CardStamp.MATCH_MASTER)
|
||||
|
||||
await ninja_stamps_earned(p)
|
||||
can_rank_up = await ninja_rank_up(p)
|
||||
if can_rank_up:
|
||||
await p.send_xt('cza', p.ninja_rank)
|
||||
@ -548,7 +552,6 @@ async def handle_send_sensei_pick(p, action: str, card_id: int):
|
||||
if can_rank_up:
|
||||
await p.send_xt('cza', p.ninja_rank)
|
||||
await p.waddle.send_xt('czo', 0, winner_seat_id)
|
||||
await ninja_stamps_earned(p)
|
||||
|
||||
await p.send_xt('zm', 'judge', winner_seat_id)
|
||||
me.chosen = None
|
||||
|
@ -2,6 +2,7 @@ import asyncio
|
||||
import itertools
|
||||
import math
|
||||
import random
|
||||
import enum
|
||||
from collections import Counter
|
||||
from dataclasses import dataclass, field
|
||||
from typing import List, Union
|
||||
@ -9,9 +10,18 @@ from typing import List, Union
|
||||
from houdini import IWaddle, handlers
|
||||
from houdini.data.ninja import Card
|
||||
from houdini.handlers import XTPacket
|
||||
from houdini.handlers.games.ninja.card import ninja_stamps_earned
|
||||
from houdini.penguin import Penguin
|
||||
|
||||
class FireStamp(enum.IntEnum):
|
||||
"""IDs of Card-Jitsu Fire stamps"""
|
||||
WARM_UP = 252
|
||||
SCORE_FIRE = 254
|
||||
FIRE_MIDWAY = 256
|
||||
STRONG_DEFENCE = 260
|
||||
FIRE_SUIT = 262
|
||||
FIRE_NINJA = 264
|
||||
MAX_ENERGY = 266
|
||||
FIRE_EXPERT = 268
|
||||
|
||||
@dataclass
|
||||
class FireNinja:
|
||||
@ -37,7 +47,7 @@ class CardJitsuFireLogic(IWaddle):
|
||||
AutoBattleTimeout = 22
|
||||
|
||||
ItemAwards = [6025, 4120, 2013, 1086, 3032]
|
||||
StampAwards = {2: 256, 4: 262}
|
||||
StampAwards = {2: FireStamp.FIRE_MIDWAY, 4: FireStamp.FIRE_SUIT}
|
||||
|
||||
def __init__(self, waddle):
|
||||
super().__init__(waddle)
|
||||
@ -524,7 +534,7 @@ async def fire_ninja_rank_up(p, ranks=1):
|
||||
for rank in range(p.fire_ninja_rank, p.fire_ninja_rank+ranks):
|
||||
await p.add_inventory(p.server.items[CardJitsuFireLogic.ItemAwards[rank]], notify=False)
|
||||
if rank in CardJitsuFireLogic.StampAwards:
|
||||
await p.add_stamp(p.server.stamps[CardJitsuFireLogic.StampAwards[rank]])
|
||||
await p.add_card_jitsu_stamp(CardJitsuFireLogic.StampAwards[rank])
|
||||
await p.update(
|
||||
fire_ninja_rank=p.fire_ninja_rank + ranks
|
||||
).apply()
|
||||
@ -567,18 +577,18 @@ async def end_game_stamps(ninja, finish_position):
|
||||
if finish_position == 1:
|
||||
await ninja.penguin.update(fire_matches_won=ninja.penguin.fire_matches_won + 1).apply()
|
||||
if ninja.penguin.fire_matches_won >= 10:
|
||||
await ninja.penguin.add_stamp(ninja.penguin.server.stamps[252])
|
||||
await ninja.penguin.add_card_jitsu_stamp(FireStamp.WARM_UP)
|
||||
if ninja.penguin.fire_matches_won >= 50:
|
||||
await ninja.penguin.add_stamp(ninja.penguin.server.stamps[268])
|
||||
await ninja.penguin.add_card_jitsu_stamp(FireStamp.FIRE_EXPERT)
|
||||
if ninja.energy >= 6:
|
||||
await ninja.penguin.add_stamp(ninja.penguin.server.stamps[260])
|
||||
await ninja.penguin.add_card_jitsu_stamp(FireStamp.STRONG_DEFENCE)
|
||||
if type(ninja.penguin.waddle) == FireSenseiLogic:
|
||||
await ninja.penguin.add_stamp(ninja.penguin.server.stamps[264])
|
||||
await ninja.penguin.add_card_jitsu_stamp(FireStamp.FIRE_NINJA)
|
||||
|
||||
if ninja.energy_won >= 1:
|
||||
await ninja.penguin.add_stamp(ninja.penguin.server.stamps[254])
|
||||
await ninja.penguin.add_card_jitsu_stamp(FireStamp.SCORE_FIRE)
|
||||
if ninja.energy_won >= 3:
|
||||
await ninja.penguin.add_stamp(ninja.penguin.server.stamps[266])
|
||||
await ninja.penguin.add_card_jitsu_stamp(FireStamp.MAX_ENERGY)
|
||||
|
||||
|
||||
@handlers.handler(XTPacket('gz', ext='z'))
|
||||
@ -665,5 +675,5 @@ async def handle_info_ready_sync(p):
|
||||
|
||||
@handlers.handler(XTPacket('lz', ext='z'))
|
||||
@handlers.player_in_room(CardJitsuFireLogic.room_id)
|
||||
async def handle_leave_game(p):
|
||||
await ninja_stamps_earned(p)
|
||||
async def handle_leave_game(p: Penguin):
|
||||
await p.send_card_jitsu_stamp_info()
|
||||
|
@ -12,6 +12,17 @@ from houdini.handlers import XTPacket
|
||||
from houdini.penguin import Penguin
|
||||
from houdini.data.ninja import Card
|
||||
|
||||
class WaterStamp(enum.IntEnum):
|
||||
"IDs of Card-Jitsu Water stamps"
|
||||
GONG = 270
|
||||
WATERY_FALL = 274
|
||||
WATER_EXPERT = 276
|
||||
WATER_MIDWAY = 278
|
||||
WATER_SUIT = 282
|
||||
WATER_NINJA = 284
|
||||
TWO_CLOSE = 286
|
||||
SKIPPING_STONES = 288
|
||||
|
||||
|
||||
@dataclass
|
||||
class WaterCard:
|
||||
@ -252,6 +263,13 @@ class WaterPlayer:
|
||||
cleared: int = 0
|
||||
"""Number of stones cleared in the match"""
|
||||
|
||||
left: bool = False
|
||||
"""
|
||||
Whether the player has left the game
|
||||
|
||||
Penguins remain in the board even if the player leaves
|
||||
"""
|
||||
|
||||
def get_card(self, hand_id: int) -> WaterCard:
|
||||
"""Get the card given its hand ID"""
|
||||
return next((card for card in self.hand.cards if card.hand_id == hand_id), None)
|
||||
@ -407,7 +425,11 @@ class CardJitsuWaterLogic(IWaddle):
|
||||
ITEM_AWARDS = [6026, 4121, 2025, 1087, 3032]
|
||||
"""All the items gained from ranking, indexed by their rank"""
|
||||
|
||||
STAMP_AWARDS = {1: 278, 3: 282, 4: 284}
|
||||
STAMP_AWARDS = {
|
||||
1: WaterStamp.WATER_MIDWAY,
|
||||
3: WaterStamp.WATER_SUIT,
|
||||
4: WaterStamp.WATER_NINJA,
|
||||
}
|
||||
"""Map rank and the stamp you gain from LEAVING the rank"""
|
||||
|
||||
board_cycle_handler: WaterCycleHandler
|
||||
@ -643,15 +665,12 @@ class CardJitsuWaterLogic(IWaddle):
|
||||
).apply()
|
||||
|
||||
if winner.penguin.water_matches_won >= 100:
|
||||
# Water Expert stamp
|
||||
await winner.penguin.add_stamp(winner.penguin.server.stamps[276])
|
||||
await winner.penguin.add_card_jitsu_stamp(WaterStamp.WATER_EXPERT)
|
||||
|
||||
# Gong! stamp
|
||||
await winner.penguin.add_stamp(winner.penguin.server.stamps[270])
|
||||
await winner.penguin.add_card_jitsu_stamp(WaterStamp.GONG)
|
||||
|
||||
if winner.two_close >= 2:
|
||||
# Two Close stamp
|
||||
await winner.penguin.add_stamp(winner.penguin.server.stamps[286])
|
||||
await winner.penguin.add_card_jitsu_stamp(WaterStamp.TWO_CLOSE)
|
||||
|
||||
# iterate over all players that drowned from the last place order
|
||||
for row in self.board.rows:
|
||||
@ -693,7 +712,7 @@ class CardJitsuWaterLogic(IWaddle):
|
||||
p.server.items[cls.ITEM_AWARDS[rank]], cost=0, notify=False
|
||||
)
|
||||
if rank in cls.STAMP_AWARDS:
|
||||
await p.add_stamp(p.server.stamps[cls.STAMP_AWARDS[rank]])
|
||||
await p.add_card_jitsu_stamp(cls.STAMP_AWARDS[rank])
|
||||
|
||||
await p.update(water_ninja_rank=p.water_ninja_rank + ranks).apply()
|
||||
return True
|
||||
@ -714,6 +733,8 @@ class CardJitsuWaterLogic(IWaddle):
|
||||
await player.penguin.add_stamp(player.penguin.server.stamps[274])
|
||||
|
||||
|
||||
await player.penguin.add_card_jitsu_stamp(WaterStamp.WATERY_FALL)
|
||||
|
||||
# CMD_PLAYER_KILL, meant for players who lose from falling
|
||||
player_kill_data = []
|
||||
for player in players_in_row:
|
||||
@ -997,12 +1018,15 @@ def get_water_rank_threshold(rank):
|
||||
async def handle_get_game(p: Penguin):
|
||||
"""Handle the client entering the game"""
|
||||
seat_id = p.waddle.get_seat_id(p)
|
||||
player = p.waddle.get_player_by_penguin(p)
|
||||
player: WaterPlayer = p.waddle.get_player_by_penguin(p)
|
||||
|
||||
# needs to send these or the client dies
|
||||
await p.send_xt("gz")
|
||||
await p.send_xt("jz")
|
||||
|
||||
# needed to fix client taking a bit to exit game
|
||||
await p.send_card_jitsu_stamp_info()
|
||||
|
||||
# CMD_PLAYER_INDEX
|
||||
await p.waddle.send_zm_client(player, "po", seat_id)
|
||||
|
||||
@ -1121,8 +1145,7 @@ async def handle_throw_card(p: Penguin, *, cell_id: str):
|
||||
)
|
||||
|
||||
if player.cleared >= 28:
|
||||
# Skipping Stones stamp
|
||||
await player.penguin.add_stamp(player.penguin.server.stamps[288])
|
||||
await p.add_card_jitsu_stamp(WaterStamp.SKIPPING_STONES)
|
||||
|
||||
# CMD_PLAYER_THROW
|
||||
await p.waddle.send_zm(
|
||||
|
@ -380,6 +380,19 @@ class Penguin(Spheniscidae, penguin.Penguin):
|
||||
|
||||
self.logger.info(f'{self.username} updated their background to \'{item.name}\' ' if item else
|
||||
f'{self.username} removed their background item')
|
||||
|
||||
async def send_card_jitsu_stamp_info(self):
|
||||
"""
|
||||
Send information the client requires to properly display the stamp end screen
|
||||
"""
|
||||
stamp_info = await self.get_game_end_stamps_info(False)
|
||||
await self.send_xt("cjsi", *stamp_info)
|
||||
|
||||
async def add_card_jitsu_stamp(self, stamp_id):
|
||||
"""Correct way of adding a card-jitsu (Regular, Fire, Water) stamp"""
|
||||
await self.add_stamp(self.server.stamps[stamp_id])
|
||||
await self.send_card_jitsu_stamp_info()
|
||||
|
||||
async def get_game_end_stamps_info(
|
||||
self, clear_session: bool
|
||||
) -> tuple[str, int, int, int]:
|
||||
|
Loading…
x
Reference in New Issue
Block a user