From a474dfbc24c2d592878f87ee8307bf15a58789d0 Mon Sep 17 00:00:00 2001 From: Alberto Xamin Date: Fri, 14 Jun 2024 18:09:24 +0300 Subject: [PATCH] also add new animations --- .../bang/expansions/train_robbery/trains.py | 32 ++++++++++---- backend/bang/game.py | 3 +- backend/bang/players.py | 42 +++++++++++++++++++ backend/server.py | 1 - frontend/src/components/Card.vue | 14 ++++++- frontend/src/components/Deck.vue | 4 +- frontend/src/components/Lobby.vue | 9 +++- frontend/src/i18n/en.json | 11 +++-- frontend/src/i18n/it.json | 5 ++- frontend/src/utils/emoji-map.js | 1 + frontend/src/utils/expansions-map.js | 2 +- 11 files changed, 104 insertions(+), 20 deletions(-) diff --git a/backend/bang/expansions/train_robbery/trains.py b/backend/bang/expansions/train_robbery/trains.py index 4ccae83..27b356d 100644 --- a/backend/bang/expansions/train_robbery/trains.py +++ b/backend/bang/expansions/train_robbery/trains.py @@ -16,6 +16,7 @@ class TrainCard(Card): self.is_locomotive = is_locomotive self.expansion = "train_robbery" self.type = "train" + self.implemented = True # Circus Wagon: gli altri giocatori @@ -122,7 +123,7 @@ class BaggageCar(TrainCard): class Caboose(TrainCard): - """Pro scartare un altra tua carta bordo blu incuso un vagone come se fosse un Mancato!""" + """Puoi scartare un altra tua carta bordo blu incuso un vagone come se fosse un Mancato!""" def __init__(self): super().__init__("Caboose") @@ -177,18 +178,21 @@ class CircusWagon(TrainCard): class CoalHopper(TrainCard): - """Scartalo: pesca una carta e scarta un vagone in gioco davanti a un giocatore a ma scelta.""" + """Scartalo: pesca una carta e scarta un vagone in gioco davanti a un giocatore a tua scelta.""" def __init__(self): super().__init__("Coal Hopper") self.icon = "๐Ÿš‹๐Ÿ”ฅ" + self.need_target = True def play_card(self, player, against=None, _with=None) -> bool: + if against is not None and len(player.game.get_player_named(against).equipment) > 0: + player.game.steal_discard(player, against, self) return True class DiningCar(TrainCard): - """A inizio turno, "estrai!": se รจ Cnori, recuperi I punto vita.""" + """A inizio turno, "estrai!": se รจ Cuori, recuperi I punto vita.""" def __init__(self): super().__init__("Dining Car") @@ -214,14 +218,15 @@ class ExpressCar(TrainCard): class GhostCar(TrainCard): - """Giocalo su chiunque tranne lo Sceritfo. Se vieni eliminato, invece resti in gioco, ma non puo guadagnare ne perdere punti vita.""" + """Giocalo su chiunque tranne lo Sceritfo. Se vieni eliminato, invece resta in gioco, ma non puo guadagnare ne perdere punti vita.""" def __init__(self): super().__init__("Ghost Car") self.icon = "๐Ÿš‹๐Ÿ‘ป" + self.implemented = False def play_card(self, player, against=None, _with=None) -> bool: - return True + return False class LoungeCar(TrainCard): @@ -230,6 +235,7 @@ class LoungeCar(TrainCard): def __init__(self): super().__init__("Lounge Car") self.icon = "๐Ÿš‹๐Ÿ›‹" + self.implemented = False def play_card(self, player, against=None, _with=None) -> bool: return True @@ -299,14 +305,23 @@ class ObservationCar(TrainCard): class PassengerCar(TrainCard): - """Scartalo: pesca una carta (in mano o in gioco) da un altro giocatore""" + """Scartalo: pesca una carta (o in mano o in gioco) da un altro giocatore""" def __init__(self): super().__init__("Passenger Car") self.icon = "๐Ÿš‹๐Ÿšถ" + self.range = 99 + self.need_target = True + def play_card(self, player, against=None, _with=None) -> bool: - return True + if ( + against is not None + and (len(player.equipment) > 0 or len(player.equipment) > 0) + ): + player.game.steal_discard(player, against, self) + return True + return False class PrisonerCar(TrainCard): @@ -321,7 +336,7 @@ class PrisonerCar(TrainCard): class PrivateCar(TrainCard): - """se non hai carte in mano. non puoi essere bersaelio di carte BANG""" + """Se non hai carte in mano, non puoi essere bersaglio di carte BANG""" def __init__(self): super().__init__("Private Car") @@ -376,6 +391,7 @@ def get_all_cards(rng=random): PrivateCar(), SleeperCar(), ] + cars = [c for c in cars if c.implemented] rng.shuffle(cars) return cars diff --git a/backend/bang/game.py b/backend/bang/game.py index 25b44e9..919e6e2 100644 --- a/backend/bang/game.py +++ b/backend/bang/game.py @@ -17,6 +17,7 @@ import bang.expansions.wild_west_show.card_events as cew import bang.expansions.gold_rush.shop_cards as grc import bang.expansions.gold_rush.characters as grch import bang.expansions.the_valley_of_shadows.cards as tvosc +import bang.expansions.train_robbery.trains as trt from metrics import Metrics from globals import G, PendingAction @@ -558,7 +559,7 @@ class Game: if p != attacker and p.get_discarded( attacker, card_name=card.name, - action="steal" if isinstance(card, cs.Panico) else "discard", + action="steal" if (isinstance(card, cs.Panico) or isinstance(card, trt.PassengerCar)) else "discard", ): self.ready_count = 0 self.waiting_for = 1 diff --git a/backend/bang/players.py b/backend/bang/players.py index 5056006..0223f37 100644 --- a/backend/bang/players.py +++ b/backend/bang/players.py @@ -737,6 +737,9 @@ class Player: self.has_played_bang = False self.special_use_count = 0 self.bang_used = 0 + if any((isinstance(c, trt.DiningCar) for c in self.equipment)): + if self.game.deck.pick_and_scrap().suit == cs.Suit.HEARTS: + self.lives = min(self.lives + 1, self.max_lives) if self.game.check_event(cew.DarlingValentine): hand = len(self.hand) for _ in range(hand): @@ -1866,6 +1869,8 @@ class Player: self.expected_response.append(cs.Bang(0, 0).name) if self.character.check(self.game, chw.BigSpencer): self.expected_response = [] + if any((isinstance(c, trt.Caboose) for c in self.equipment)): + self.expected_response.append([c.name for c in self.equipment if not c.usable_next_turn]) self.on_failed_response_cb = self.take_damage_response self.notify_self() @@ -1997,6 +2002,17 @@ class Player: self.attacker = attacker self.attacking_card = card_name print(f"attacker -> {attacker}") + # check for trt.PrivateCar + if (card_name == "Bang!" and any( + (isinstance(c, trt.PrivateCar) for c in self.equipment) + ) and len(self.hand) == 0): + self.take_no_damage_response() + G.sio.emit( + "chat_message", + room=self.game.name, + data=f"_in_private_car|{self.name}|{attacker.name}", + ) + return False if ( isinstance(attacker, Player) and attacker.character.check(self.game, tvosch.ColoradoBill) @@ -2112,6 +2128,11 @@ class Player: (isinstance(c, grc.Calumet) for c in self.gold_rush_equipment) ): return False + # check for trt.PrisonerCar + if any( + (isinstance(c, trt.PrisonerCar) for c in self.equipment) + ): + return False if ( not self.game.is_competitive and not any( @@ -2145,6 +2166,12 @@ class Player: def get_dueled(self, attacker): self.attacker = attacker self.attacking_card = "Duello" + if any( + not self.is_my_turn and + (isinstance(c, trt.PrisonerCar) for c in self.equipment) + ): + self.take_no_damage_response() + return False if (self.game.check_event(ceh.Sermone) and self.is_my_turn) or ( not self.game.is_competitive and not any( @@ -2551,6 +2578,11 @@ class Player: self.game.deck.shop_deck.append(card) self.game.deck.shop_cards[index] = None self.game.deck.fill_gold_rush_shop() + G.sio.emit( + "card_scrapped", + room=self.game.name, + data={"player": self.name, "pile": "gold_rush", "card": card.__dict__}, + ) self.notify_self() def buy_train(self, index): @@ -2569,6 +2601,16 @@ class Player: if station.check_price(self): print(f"{station=} {train=}") station.attached_train = train + G.sio.emit( + "chat_message", + room=self.game.name, + data=f"_bought_train|{self.name}|{station.name}|{train.name}", + ) + G.sio.emit( + "card_scrapped", + room=self.game.name, + data={"player": self.name, "pile": "train_robbery", "card": train.__dict__}, + ) # shift train forward for i in range(train_index, len(self.game.deck.current_train) - 1): self.game.deck.current_train[i] = self.game.deck.current_train[ diff --git a/backend/server.py b/backend/server.py index cac1360..12bfabb 100644 --- a/backend/server.py +++ b/backend/server.py @@ -1317,7 +1317,6 @@ def get_trainrobberycards(sid): import bang.expansions.train_robbery.trains as trt chs = [] - chs.extend(trs.get_all_stations()) chs.extend(trt.get_locomotives()) chs.extend(trt.get_all_cards()) sio.emit( diff --git a/frontend/src/components/Card.vue b/frontend/src/components/Card.vue index 7f2b918..9dcebb6 100644 --- a/frontend/src/components/Card.vue +++ b/frontend/src/components/Card.vue @@ -65,7 +65,7 @@ export default { }, suit() { if (this.card && !isNaN(this.card.suit)) { - let x = ["โ™ฆ๏ธ", "โ™ฃ๏ธ", "โ™ฅ๏ธ", "โ™ ๏ธ", "๐Ÿค‘"]; + let x = ["โ™ฆ๏ธ", "โ™ฃ๏ธ", "โ™ฅ๏ธ", "โ™ ๏ธ", "๐Ÿค‘", "๐Ÿš‚"]; return x[this.card.suit]; } else if (this.card.suit) { return this.card.suit; @@ -232,6 +232,18 @@ export default { padding: 4pt; border-radius: 12pt; } +.wip::after { + content: "WIP"; + position: absolute; + bottom: -12pt; + right: -12pt; + background: red; + font-size: 10pt; + font-family: "Segoe UI", Tahoma, Geneva, Verdana, sans-serif; + font-weight: bold; + padding: 4pt; + border-radius: 12pt; +} .avatar { position: absolute; width: 36pt; diff --git a/frontend/src/components/Deck.vue b/frontend/src/components/Deck.vue index 4cd4962..4d8fe89 100644 --- a/frontend/src/components/Deck.vue +++ b/frontend/src/components/Deck.vue @@ -1,7 +1,7 @@