also add new animations

This commit is contained in:
Alberto Xamin 2024-06-14 18:09:24 +03:00
parent c171739db8
commit a474dfbc24
No known key found for this signature in database
GPG Key ID: 5ABFCD8A22EA6F5D
11 changed files with 104 additions and 20 deletions

View File

@ -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

View File

@ -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

View File

@ -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[

View File

@ -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(

View File

@ -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;

View File

@ -1,7 +1,7 @@
<template>
<div >
<div class="deck">
<div class="deck" :style="`position:relative;${goldRushShopOpen?'border: 2px dashed #6a6a6a42;border-radius:8pt':''}`" v-if="goldRushCards.length > 0" >
<div class="deck" id="gold-rush-deck" :style="`position:relative;${goldRushShopOpen?'border: 2px dashed #6a6a6a42;border-radius:8pt':''}`" v-if="goldRushCards.length > 0" >
<card @pointerenter.native="()=>{setGoldRushDesc(goldRushCards[0])}" @pointerleave.native="goldRushDesc=null" :style="goldRushShopOpen?``:`position:absolute; top:0; right:0; transform: rotate(95deg) translate(30px, -40px) scale(0.6)`" v-if="goldRushCards.length > 0" :key="goldRushCards[0].name" :card="goldRushCards[0]" :class="{'shop-open':goldRushShopOpen, 'cant-play': pending_action !==2 || gold_nuggets < goldRushCards[0].number - gold_rush_discount}" @click.native="() => {buy_gold_rush_card(0)}"/>
<card @pointerenter.native="()=>{setGoldRushDesc(goldRushCards[1])}" @pointerleave.native="goldRushDesc=null" :style="goldRushShopOpen?``:`position:absolute; top:0; right:0; transform: rotate(90deg) translate(0, -40px) scale(0.6)`" v-if="goldRushCards.length > 1" :key="goldRushCards[1].name" :card="goldRushCards[1]" :class="{'shop-open':goldRushShopOpen, 'cant-play': pending_action !==2 || gold_nuggets < goldRushCards[1].number - gold_rush_discount}" @click.native="() => {buy_gold_rush_card(1)}"/>
<card @pointerenter.native="()=>{setGoldRushDesc(goldRushCards[2])}" @pointerleave.native="goldRushDesc=null" :style="goldRushShopOpen?``:`position:absolute; top:0; right:0; transform: rotate(85deg) translate(-30px, -40px) scale(0.6)`" v-if="goldRushCards.length > 2" :key="goldRushCards[2].name" :card="goldRushCards[2]" :class="{'shop-open':goldRushShopOpen, 'cant-play': pending_action !==2 || gold_nuggets < goldRushCards[2].number - gold_rush_discount}" @click.native="() => {buy_gold_rush_card(2)}"/>
@ -11,7 +11,7 @@
<card :card="goldRushCardBack" :donotlocalize="true" class="gold-rush back last-event" @click.native="goldRushShopOpen = !goldRushShopOpen"/>
</div>
</div>
<div v-if="currentStations.length > 0" class="deck" :style="`position:relative;border: 2px dashed #6a6a6a42;border-radius:8pt;align-items: flex-end;flex-direction:row;`" >
<div v-if="currentStations.length > 0" id="train-robbery-deck" class="deck" :style="`position:relative;border: 2px dashed #6a6a6a42;border-radius:8pt;align-items: flex-end;flex-direction:row;`" >
<station-card @click.native="()=>{buyTrain(i)}" v-for="station, i in currentStations" :key="station.name" :card="station" :price="station.price" :trainPiece="trainPieceForStation(i)"
@pointerenter.native="()=>{setStationDesc(i)}" @pointerleave.native="stationDesc = null"/>
</div>

View File

@ -646,8 +646,15 @@ export default {
console.log("card_scrapped no deck");
return;
}
let decelOffset = cumulativeOffset(decel);
let phand = document.getElementById(`${data.player}-hand`);
if (data.pile == "train_robbery") {
decel = phand
phand = document.getElementById("train-robbery-deck");
} else if (data.pile == "gold_rush") {
decel = phand
phand = document.getElementById("gold-rush-deck");
}
let decelOffset = cumulativeOffset(decel);
if (!phand) {
console.log("card_scrapped no phand");
return;

View File

@ -104,6 +104,7 @@
"choose_mail_car": "Choose which card to give to another player",
"choose_other_player": "Choose the player to give the card to",
"choose_sleeper_car": "Choose a card to discard for Sleeper Car",
"choose_buy_train": "Discard a card to rob the train, and get the carriage",
"chat": {
"spectators": " | A spectator is watching the game | {n} spectators are watching the game",
"chat": "Chat",
@ -157,7 +158,9 @@
"choose_emporio": ";{0}; has chosen ;{1}; from General Store.",
"shotgun_scrap": "When the shotgun hit ;{0}; a card flew away from his hand (;{1};)",
"taglia_reward": "💰 ;{1}; got a card from the bounty on ;{0};",
"snake_bit": "🐍 ;{0}; was bitten by the Rattle Snake."
"snake_bit": "🐍 ;{0}; was bitten by the Rattle Snake.",
"in_private_car": "🚋💁🏻 ;{0}; is in a private car and couldn't get Bang!ed by ;{1};",
"bought_train": "🚂 ;{0}; robbed the train at ;{1}; and got the ;{2};"
},
"foc": {
"leggedelwest": "He must play this card on this turn if possible."
@ -942,7 +945,7 @@
},
"Dining Car": {
"name": "Dining Car",
"desc": "At the beginning of your turn, \"draw!\": if it's Hearts, regain 1 life point."
"desc": "At the beginning of your turn, \"pick!\": if it's Hearts, regain 1 life point."
},
"Express Car": {
"name": "Express Car",
@ -1034,7 +1037,9 @@
"highnooncards": "High Noon - Event Cards",
"foccards": "Fistful of Cards - Event Cards",
"goldrushcards": "Gold Rush Cards",
"valleyofshadowscards": "The Valley of Shadows Cards"
"valleyofshadowscards": "The Valley of Shadows Cards",
"wildwestshowcards": "Wild West Show Cards",
"trainrobberycards": "Train Robbery Cards"
},
"theme": {
"sepia": "Sepia",

View File

@ -153,7 +153,8 @@
"choose_emporio": ";{0}; ha scelto ;{1}; da Emporio.",
"shotgun_scrap": "Quando lo shotgun ha colpito ;{0}; gli ha tolto una carta (;{1};)",
"taglia_reward": "💰 ;{1}; ha ottenuto ricompensa dalla taglia su ;{0};",
"snake_bit": "🐍 ;{0}; è stato morso dal Serpente a Sonagli."
"snake_bit": "🐍 ;{0}; è stato morso dal Serpente a Sonagli.",
"in_private_car": "🚋💁🏻 ;{0}; è in una carrozza privata e non è stato attaccato da ;{1};"
},
"foc": {
"leggedelwest": "Ed è obbligato a usarla nel suo turno, se possibile"
@ -938,7 +939,7 @@
},
"Dining Car": {
"name": "Dining Car",
"desc": "A inizio turno, \"estrai!\": se è Cnori, recuperi I punto vita."
"desc": "A inizio turno, \"estrai!\": se è Cuori, recuperi I punto vita."
},
"Express Car": {
"name": "Express Car",

View File

@ -5,4 +5,5 @@ export const emojiMap = {
'fistful_of_cards': '🎴',
'the_valley_of_shadows': '👻',
'wild_west_show': '🎪',
'train_robbery': '🚂',
}

View File

@ -41,6 +41,6 @@ export const expansionsMap = {
icon: '🚂',
back: true,
expansion: 'train-roobbery',
status: 'alpha',
status: 'wip',
}
}