Merge branch 'main' into dev
This commit is contained in:
commit
31bdeb3436
@ -1,4 +1,5 @@
|
|||||||
from typing import List, Set, Dict, Tuple, Optional
|
from __future__ import annotations
|
||||||
|
from typing import List, Set, Dict, Tuple, Optional, TYPE_CHECKING
|
||||||
import bang.expansions.fistful_of_cards.card_events as ce
|
import bang.expansions.fistful_of_cards.card_events as ce
|
||||||
import bang.expansions.high_noon.card_events as ceh
|
import bang.expansions.high_noon.card_events as ceh
|
||||||
from abc import ABC, abstractmethod
|
from abc import ABC, abstractmethod
|
||||||
@ -6,11 +7,16 @@ from enum import IntEnum
|
|||||||
import bang.roles as r
|
import bang.roles as r
|
||||||
from globals import G
|
from globals import G
|
||||||
|
|
||||||
|
if TYPE_CHECKING:
|
||||||
|
from bang.players import Player
|
||||||
|
from bang.game import Game
|
||||||
|
|
||||||
class Suit(IntEnum):
|
class Suit(IntEnum):
|
||||||
DIAMONDS = 0 # ♦
|
DIAMONDS = 0 # ♦
|
||||||
CLUBS = 1 # ♣
|
CLUBS = 1 # ♣
|
||||||
HEARTS = 2 # ♥
|
HEARTS = 2 # ♥
|
||||||
SPADES = 3 # ♠
|
SPADES = 3 # ♠
|
||||||
|
GOLD = 4 # 🤑
|
||||||
|
|
||||||
|
|
||||||
class Card(ABC):
|
class Card(ABC):
|
||||||
@ -47,14 +53,14 @@ class Card(ABC):
|
|||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
if str(self.suit).isnumeric():
|
if str(self.suit).isnumeric():
|
||||||
char = ['♦️', '♣️', '♥️', '♠️'][int(self.suit)]
|
char = ['♦️', '♣️', '♥️', '♠️', '🤑'][int(self.suit)]
|
||||||
else:
|
else:
|
||||||
char = self.suit
|
char = self.suit
|
||||||
return f'{self.name} {char}{self.number}'
|
return f'{self.name} {char}{self.number}'
|
||||||
return super().__str__()
|
return super().__str__()
|
||||||
|
|
||||||
def num_suit(self):
|
def num_suit(self):
|
||||||
return f"{['♦️', '♣️', '♥️', '♠️'][int(self.suit)]}{self.number}"
|
return f"{['♦️', '♣️', '♥️', '♠️', '🤑'][int(self.suit)]}{self.number}"
|
||||||
|
|
||||||
def reset_card(self):
|
def reset_card(self):
|
||||||
if self.usable_next_turn:
|
if self.usable_next_turn:
|
||||||
@ -64,7 +70,7 @@ class Card(ABC):
|
|||||||
if self.must_be_used:
|
if self.must_be_used:
|
||||||
self.must_be_used = False
|
self.must_be_used = False
|
||||||
|
|
||||||
def play_card(self, player, against=None, _with=None):#self --> carta
|
def play_card(self, player:Player, against:str=None, _with:int=None):#self --> carta
|
||||||
if (player.game.check_event(ce.IlGiudice)) and self.usable_next_turn and not self.can_be_used_now:
|
if (player.game.check_event(ce.IlGiudice)) and self.usable_next_turn and not self.can_be_used_now:
|
||||||
return False
|
return False
|
||||||
if self.is_equipment:
|
if self.is_equipment:
|
||||||
@ -98,10 +104,10 @@ class Card(ABC):
|
|||||||
def use_card(self, player):
|
def use_card(self, player):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
def is_duplicate_card(self, player):
|
def is_duplicate_card(self, player:Player):
|
||||||
return self.name in [c.name for c in player.equipment] or self.name in [c.name for c in player.gold_rush_equipment]
|
return any(c.name==self.name for c in player.equipment) or any(c.name==self.name for c in player.gold_rush_equipment)
|
||||||
|
|
||||||
def check_suit(self, game, accepted):
|
def check_suit(self, game:Game, accepted:List[Suit]):
|
||||||
if game.check_event(ceh.Benedizione):
|
if game.check_event(ceh.Benedizione):
|
||||||
return Suit.HEARTS in accepted
|
return Suit.HEARTS in accepted
|
||||||
elif game.check_event(ceh.Maledizione):
|
elif game.check_event(ceh.Maledizione):
|
||||||
@ -226,7 +232,7 @@ class Bang(Card):
|
|||||||
elif against is not None:
|
elif against is not None:
|
||||||
import bang.characters as chars
|
import bang.characters as chars
|
||||||
super().play_card(player, against=against)
|
super().play_card(player, against=against)
|
||||||
if not self.number == 42: # 42 gold rush
|
if not (self.number == 42 and self.suit == Suit.GOLD): # 42 gold rush
|
||||||
player.bang_used += 1
|
player.bang_used += 1
|
||||||
player.has_played_bang = True if not player.game.check_event(ceh.Sparatoria) else player.bang_used > 1
|
player.has_played_bang = True if not player.game.check_event(ceh.Sparatoria) else player.bang_used > 1
|
||||||
if player.character.check(player.game, chars.WillyTheKid):
|
if player.character.check(player.game, chars.WillyTheKid):
|
||||||
|
@ -1,8 +1,13 @@
|
|||||||
|
from __future__ import annotations
|
||||||
from abc import ABC, abstractmethod
|
from abc import ABC, abstractmethod
|
||||||
from bang.expansions import *
|
from bang.expansions import *
|
||||||
from typing import List
|
from typing import List, TYPE_CHECKING
|
||||||
from globals import G
|
from globals import G
|
||||||
|
|
||||||
|
if TYPE_CHECKING:
|
||||||
|
from bang.players import Player
|
||||||
|
from bang.game import Game
|
||||||
|
|
||||||
class Character(ABC):
|
class Character(ABC):
|
||||||
def __init__(self, name: str, max_lives: int, sight_mod: int = 0, visibility_mod: int = 0, pick_mod: int = 0, desc: str = ''):
|
def __init__(self, name: str, max_lives: int, sight_mod: int = 0, visibility_mod: int = 0, pick_mod: int = 0, desc: str = ''):
|
||||||
super().__init__()
|
super().__init__()
|
||||||
@ -16,13 +21,13 @@ class Character(ABC):
|
|||||||
self.icon = '🤷♂️'
|
self.icon = '🤷♂️'
|
||||||
self.number = ''.join(['❤️']*self.max_lives)
|
self.number = ''.join(['❤️']*self.max_lives)
|
||||||
|
|
||||||
def check(self, game, character):
|
def check(self, game:Game, character:Character):
|
||||||
import bang.expansions.high_noon.card_events as ceh
|
import bang.expansions.high_noon.card_events as ceh
|
||||||
if game.check_event(ceh.Sbornia):
|
if game.check_event(ceh.Sbornia):
|
||||||
return False
|
return False
|
||||||
return isinstance(self, character)
|
return isinstance(self, character)
|
||||||
|
|
||||||
def special(self, player, data):
|
def special(self, player:Player, data):
|
||||||
import bang.expansions.high_noon.card_events as ceh
|
import bang.expansions.high_noon.card_events as ceh
|
||||||
if player.game.check_event(ceh.Sbornia):
|
if player.game.check_event(ceh.Sbornia):
|
||||||
return False
|
return False
|
||||||
|
@ -58,7 +58,9 @@ class Bottiglia(ShopCard):
|
|||||||
|
|
||||||
def play_card(self, player, against=None, _with=None):
|
def play_card(self, player, against=None, _with=None):
|
||||||
# bang, birra, panico
|
# bang, birra, panico
|
||||||
player.available_cards = [Bang(1,42), Birra(1,42), Panico(1,42)]
|
player.available_cards = [Bang(4,42), Birra(4,42), Panico(4,42)]
|
||||||
|
if not any((player.get_sight() >= p['dist'] for p in player.game.get_visible_players(player))):
|
||||||
|
player.available_cards.pop(0)
|
||||||
for i in range(len(player.available_cards)):
|
for i in range(len(player.available_cards)):
|
||||||
player.available_cards[i].must_be_used = True
|
player.available_cards[i].must_be_used = True
|
||||||
player.choose_text = 'choose_bottiglia'
|
player.choose_text = 'choose_bottiglia'
|
||||||
@ -73,7 +75,7 @@ class Complice(ShopCard):
|
|||||||
|
|
||||||
def play_card(self, player, against=None, _with=None):
|
def play_card(self, player, against=None, _with=None):
|
||||||
# emporio, duello, Cat balou
|
# emporio, duello, Cat balou
|
||||||
player.available_cards = [Emporio(1,42), Duello(1,42), CatBalou(1,42)]
|
player.available_cards = [Emporio(4,42), Duello(4,42), CatBalou(4,42)]
|
||||||
for i in range(len(player.available_cards)):
|
for i in range(len(player.available_cards)):
|
||||||
player.available_cards[i].must_be_used = True
|
player.available_cards[i].must_be_used = True
|
||||||
player.choose_text = 'choose_complice'
|
player.choose_text = 'choose_complice'
|
||||||
|
@ -33,7 +33,24 @@ class Lemat(Card):
|
|||||||
def __init__(self, suit, number):
|
def __init__(self, suit, number):
|
||||||
super().__init__(suit, 'Lemat', number, is_equipment=True, is_weapon=True, range=1)
|
super().__init__(suit, 'Lemat', number, is_equipment=True, is_weapon=True, range=1)
|
||||||
self.icon = '🔫' # ogni carta può essere usata come bang, conta per il conteggio dei bang per turno
|
self.icon = '🔫' # ogni carta può essere usata come bang, conta per il conteggio dei bang per turno
|
||||||
#TODO
|
|
||||||
|
def play_card(self, player, against, _with=None):
|
||||||
|
if (player.game.check_event(ce.IlGiudice) and self.can_be_used_now) or (not self.can_be_used_now and player.game.check_event(ce.Lazo)):
|
||||||
|
return False
|
||||||
|
if self.can_be_used_now:
|
||||||
|
self.can_be_used_now = False
|
||||||
|
G.sio.emit('chat_message', room=player.game.name,
|
||||||
|
data=f'_play_card|{player.name}|{self.name}')
|
||||||
|
player.equipment.append(self)
|
||||||
|
player.notify_self()
|
||||||
|
return True
|
||||||
|
elif not player.has_played_bang and any((player.get_sight() >= p['dist'] for p in player.game.get_visible_players(player))):
|
||||||
|
from bang.players import PendingAction
|
||||||
|
player.available_cards = player.hand.copy()
|
||||||
|
player.pending_action = PendingAction.CHOOSE
|
||||||
|
player.choose_text = 'choose_play_as_bang'
|
||||||
|
player.notify_self()
|
||||||
|
return False
|
||||||
|
|
||||||
class SerpenteASonagli(Card):
|
class SerpenteASonagli(Card):
|
||||||
def __init__(self, suit, number):
|
def __init__(self, suit, number):
|
||||||
@ -165,7 +182,7 @@ class Mira(Card):
|
|||||||
|
|
||||||
def play_card(self, player, against, _with=None):
|
def play_card(self, player, against, _with=None):
|
||||||
if against is not None and _with is not None:
|
if against is not None and _with is not None:
|
||||||
super().play_card(player, against=against)
|
super().play_card(player, against=against, _with=_with)
|
||||||
player.game.attack(player, against, card_name=self.name)
|
player.game.attack(player, against, card_name=self.name)
|
||||||
return True
|
return True
|
||||||
return False
|
return False
|
||||||
@ -218,7 +235,7 @@ def get_starting_deck() -> List[Card]:
|
|||||||
cards = [
|
cards = [
|
||||||
Fantasma(Suit.SPADES, 9),
|
Fantasma(Suit.SPADES, 9),
|
||||||
Fantasma(Suit.SPADES, 10),
|
Fantasma(Suit.SPADES, 10),
|
||||||
# Lemat(Suit.DIAMONDS, 4),
|
Lemat(Suit.DIAMONDS, 4),
|
||||||
SerpenteASonagli(Suit.HEARTS, 7),
|
SerpenteASonagli(Suit.HEARTS, 7),
|
||||||
Shotgun(Suit.SPADES, 'K'),
|
Shotgun(Suit.SPADES, 'K'),
|
||||||
Taglia(Suit.CLUBS, 9),
|
Taglia(Suit.CLUBS, 9),
|
||||||
|
@ -9,14 +9,14 @@ class BlackFlower(Character):
|
|||||||
self.icon = '🥀'
|
self.icon = '🥀'
|
||||||
|
|
||||||
def special(self, player, data): #fiori = suit.Clubs
|
def special(self, player, data): #fiori = suit.Clubs
|
||||||
if player.special_use_count > 0 and not any((c.suit == cs.Suit.CLUBS for c in player.hand)):
|
if player.special_use_count > 0 or not any((c.suit == cs.Suit.CLUBS for c in player.hand)):
|
||||||
return False
|
return False
|
||||||
if super().special(player, data):
|
if any((player.get_sight() >= p['dist'] for p in player.game.get_visible_players(player))) and super().special(player, data):
|
||||||
from bang.players import PendingAction
|
from bang.players import PendingAction
|
||||||
player.special_use_count += 1
|
|
||||||
player.available_cards = [c for c in player.hand if c.suit == cs.Suit.CLUBS]
|
player.available_cards = [c for c in player.hand if c.suit == cs.Suit.CLUBS]
|
||||||
|
player.special_use_count += 1
|
||||||
player.pending_action = PendingAction.CHOOSE
|
player.pending_action = PendingAction.CHOOSE
|
||||||
player.choose_text = 'blackflower_special'
|
player.choose_text = 'choose_play_as_bang'
|
||||||
player.notify_self()
|
player.notify_self()
|
||||||
|
|
||||||
class ColoradoBill(Character):
|
class ColoradoBill(Character):
|
||||||
|
@ -61,7 +61,7 @@ class Game:
|
|||||||
self.initial_players = 0
|
self.initial_players = 0
|
||||||
self.password = ''
|
self.password = ''
|
||||||
self.expansions: List[str] = []
|
self.expansions: List[str] = []
|
||||||
self.available_expansions = ['dodge_city', 'fistful_of_cards', 'high_noon', 'gold_rush']
|
self.available_expansions = ['dodge_city', 'fistful_of_cards', 'high_noon', 'gold_rush', 'the_valley_of_shadows']
|
||||||
self.shutting_down = False
|
self.shutting_down = False
|
||||||
self.is_competitive = False
|
self.is_competitive = False
|
||||||
self.disconnect_bot = True
|
self.disconnect_bot = True
|
||||||
@ -446,7 +446,7 @@ class Game:
|
|||||||
{'name':self.players[self.turn].name,'cards': self.available_cards}, default=lambda o: o.__dict__))
|
{'name':self.players[self.turn].name,'cards': self.available_cards}, default=lambda o: o.__dict__))
|
||||||
self.players[self.turn].notify_self()
|
self.players[self.turn].notify_self()
|
||||||
|
|
||||||
def respond_emporio(self, player, i):
|
def respond_emporio(self, player:pl.Player, i:int):
|
||||||
card = self.available_cards.pop(i)
|
card = self.available_cards.pop(i)
|
||||||
G.sio.emit('chat_message', room=self.name, data=f'_choose_emporio|{player.name}|{card.name}')
|
G.sio.emit('chat_message', room=self.name, data=f'_choose_emporio|{player.name}|{card.name}')
|
||||||
player.hand.append(card)
|
player.hand.append(card)
|
||||||
|
@ -1,3 +1,4 @@
|
|||||||
|
from __future__ import annotations
|
||||||
from enum import IntEnum
|
from enum import IntEnum
|
||||||
import json
|
import json
|
||||||
from random import random, randrange, sample, uniform
|
from random import random, randrange, sample, uniform
|
||||||
@ -14,11 +15,14 @@ import bang.expansions.gold_rush.shop_cards as grc
|
|||||||
import bang.expansions.gold_rush.characters as grch
|
import bang.expansions.gold_rush.characters as grch
|
||||||
import bang.expansions.the_valley_of_shadows.cards as tvosc
|
import bang.expansions.the_valley_of_shadows.cards as tvosc
|
||||||
import bang.expansions.the_valley_of_shadows.characters as tvosch
|
import bang.expansions.the_valley_of_shadows.characters as tvosch
|
||||||
from typing import List
|
from typing import List, TYPE_CHECKING
|
||||||
from metrics import Metrics
|
from metrics import Metrics
|
||||||
from globals import G
|
from globals import G
|
||||||
import sys
|
import sys
|
||||||
|
|
||||||
|
if TYPE_CHECKING:
|
||||||
|
from bang.game import Game
|
||||||
|
|
||||||
robot_pictures = [
|
robot_pictures = [
|
||||||
'https://i.imgur.com/40rAFIb.jpg',
|
'https://i.imgur.com/40rAFIb.jpg',
|
||||||
'https://i.imgur.com/gG77VRR.jpg',
|
'https://i.imgur.com/gG77VRR.jpg',
|
||||||
@ -50,7 +54,7 @@ class Player:
|
|||||||
def is_admin(self):
|
def is_admin(self):
|
||||||
return self.discord_id in {'244893980960096266', '539795574019457034'}
|
return self.discord_id in {'244893980960096266', '539795574019457034'}
|
||||||
|
|
||||||
def get_avatar(self):
|
def _get_avatar(self):
|
||||||
import requests
|
import requests
|
||||||
headers = {
|
headers = {
|
||||||
'Authorization': 'Bearer ' + self.discord_token,
|
'Authorization': 'Bearer ' + self.discord_token,
|
||||||
@ -78,7 +82,6 @@ class Player:
|
|||||||
print(r)
|
print(r)
|
||||||
|
|
||||||
def __init__(self, name, sid, bot=False, discord_token=None):
|
def __init__(self, name, sid, bot=False, discord_token=None):
|
||||||
import bang.game as g
|
|
||||||
super().__init__()
|
super().__init__()
|
||||||
self.name = name
|
self.name = name
|
||||||
self.sid = sid
|
self.sid = sid
|
||||||
@ -89,8 +92,8 @@ class Player:
|
|||||||
if self.is_bot:
|
if self.is_bot:
|
||||||
self.avatar = robot_pictures[randrange(len(robot_pictures))]
|
self.avatar = robot_pictures[randrange(len(robot_pictures))]
|
||||||
if self.discord_token:
|
if self.discord_token:
|
||||||
G.sio.start_background_task(self.get_avatar)
|
G.sio.start_background_task(self._get_avatar)
|
||||||
self.game: g = None
|
self.game: Game = None
|
||||||
self.reset()
|
self.reset()
|
||||||
|
|
||||||
def reset(self):
|
def reset(self):
|
||||||
@ -187,7 +190,6 @@ class Player:
|
|||||||
self.pending_action = PendingAction.DRAW
|
self.pending_action = PendingAction.DRAW
|
||||||
self.notify_self()
|
self.notify_self()
|
||||||
|
|
||||||
|
|
||||||
def prepare(self):
|
def prepare(self):
|
||||||
self.max_lives = self.character.max_lives + self.role.health_mod
|
self.max_lives = self.character.max_lives + self.role.health_mod
|
||||||
self.lives = self.max_lives
|
self.lives = self.max_lives
|
||||||
@ -717,6 +719,7 @@ class Player:
|
|||||||
print('which is a gold rush black card')
|
print('which is a gold rush black card')
|
||||||
card: grc.ShopCard = self.gold_rush_equipment[hand_index - len(self.hand) - len(self.equipment)]
|
card: grc.ShopCard = self.gold_rush_equipment[hand_index - len(self.hand) - len(self.equipment)]
|
||||||
return card.play_card(self)
|
return card.play_card(self)
|
||||||
|
from_hand = hand_index < len(self.hand)
|
||||||
card: cs.Card = self.hand.pop(hand_index) if hand_index < len(self.hand) else self.equipment.pop(hand_index-len(self.hand))
|
card: cs.Card = self.hand.pop(hand_index) if hand_index < len(self.hand) else self.equipment.pop(hand_index-len(self.hand))
|
||||||
withCard: cs.Card = None
|
withCard: cs.Card = None
|
||||||
if _with is not None:
|
if _with is not None:
|
||||||
@ -744,7 +747,10 @@ class Player:
|
|||||||
self.equipment.insert(hand_index-len(self.hand), card)
|
self.equipment.insert(hand_index-len(self.hand), card)
|
||||||
elif card.is_equipment or (card.usable_next_turn and not card.can_be_used_now):
|
elif card.is_equipment or (card.usable_next_turn and not card.can_be_used_now):
|
||||||
if not did_play_card:
|
if not did_play_card:
|
||||||
|
if from_hand:
|
||||||
self.hand.insert(hand_index, card)
|
self.hand.insert(hand_index, card)
|
||||||
|
else:
|
||||||
|
self.equipment.insert(hand_index-len(self.hand), card)
|
||||||
else:
|
else:
|
||||||
did_play_card = True
|
did_play_card = True
|
||||||
if not self.game.is_replay:
|
if not self.game.is_replay:
|
||||||
@ -870,11 +876,11 @@ class Player:
|
|||||||
G.sio.emit('chat_message', room=player.game.name, data=f'_play_card_against|{self.name}|Sventagliata|{player.name}')
|
G.sio.emit('chat_message', room=player.game.name, data=f'_play_card_against|{self.name}|Sventagliata|{player.name}')
|
||||||
self.pending_action = PendingAction.PLAY
|
self.pending_action = PendingAction.PLAY
|
||||||
self.notify_self()
|
self.notify_self()
|
||||||
elif 'blackflower_special' in self.choose_text:
|
elif 'choose_play_as_bang' in self.choose_text:
|
||||||
if card_index <= len(self.available_cards):
|
if card_index <= len(self.available_cards):
|
||||||
self.hand.remove(self.available_cards[card_index])
|
self.hand.remove(self.available_cards[card_index])
|
||||||
self.game.deck.scrap(self.available_cards[card_index], player=self)
|
self.game.deck.scrap(self.available_cards[card_index], player=self)
|
||||||
self.hand.append(cs.Bang(cs.Suit.CLUBS,42))
|
self.hand.append(cs.Bang(self.available_cards[card_index].suit, 42))
|
||||||
self.pending_action = PendingAction.PLAY
|
self.pending_action = PendingAction.PLAY
|
||||||
self.notify_self()
|
self.notify_self()
|
||||||
elif 'choose_tornado' in self.choose_text:
|
elif 'choose_tornado' in self.choose_text:
|
||||||
|
@ -56,12 +56,12 @@ HASTEBIN_HEADERS = {
|
|||||||
}
|
}
|
||||||
|
|
||||||
app = socketio.WSGIApp(sio, static_files=static_files)
|
app = socketio.WSGIApp(sio, static_files=static_files)
|
||||||
games: List[Game] = []
|
games: dict[str, Game] = {}
|
||||||
online_players = 0
|
online_players = 0
|
||||||
blacklist: List[str] = []
|
blacklist: List[str] = []
|
||||||
|
|
||||||
def send_to_debug(error):
|
def send_to_debug(error):
|
||||||
for g in games:
|
for g in games.values():
|
||||||
if g.debug:
|
if g.debug:
|
||||||
sio.emit('chat_message', room=g.name, data={'color': f'red','text':json.dumps({'ERROR':error}), 'type':'json'})
|
sio.emit('chat_message', room=g.name, data={'color': f'red','text':json.dumps({'ERROR':error}), 'type':'json'})
|
||||||
elif any((p.is_admin() for p in g.players)):
|
elif any((p.is_admin() for p in g.players)):
|
||||||
@ -85,9 +85,10 @@ def bang_handler(func):
|
|||||||
return wrapper_func
|
return wrapper_func
|
||||||
|
|
||||||
def advertise_lobbies():
|
def advertise_lobbies():
|
||||||
sio.emit('lobbies', room='lobby', data=[{'name': g.name, 'players': len(g.players), 'locked': g.password != ''} for g in games if not g.started and len(g.players) < 10 and not g.is_hidden])
|
open_lobbies = [g for g in games.values() if 0 < len(g.players) < 10 and not g.is_hidden][-10:]
|
||||||
sio.emit('spectate_lobbies', room='lobby', data=[{'name': g.name, 'players': len(g.players), 'locked': g.password != ''} for g in games if g.started and not g.is_hidden and len(g.players) > 0])
|
sio.emit('lobbies', room='lobby', data=[{'name': g.name, 'players': len(g.players), 'locked': g.password != ''} for g in open_lobbies if not g.started])
|
||||||
Metrics.send_metric('lobbies', points=[sum(not g.is_replay for g in games)])
|
sio.emit('spectate_lobbies', room='lobby', data=[{'name': g.name, 'players': len(g.players), 'locked': g.password != ''} for g in open_lobbies if g.started])
|
||||||
|
Metrics.send_metric('lobbies', points=[sum(not g.is_replay for g in games.values())])
|
||||||
Metrics.send_metric('online_players', points=[online_players])
|
Metrics.send_metric('online_players', points=[online_players])
|
||||||
|
|
||||||
@sio.event
|
@sio.event
|
||||||
@ -137,7 +138,7 @@ def set_username(sid, username):
|
|||||||
ses = sio.get_session(sid)
|
ses = sio.get_session(sid)
|
||||||
if not isinstance(ses, Player):
|
if not isinstance(ses, Player):
|
||||||
dt = username["discord_token"] if 'discord_token' in username else None
|
dt = username["discord_token"] if 'discord_token' in username else None
|
||||||
sio.save_session(sid, Player(username["name"], sid, discord_token=dt))
|
sio.save_session(sid, Player(username.get('name', 'player'), sid, discord_token=dt))
|
||||||
print(f'{sid} is now {username}')
|
print(f'{sid} is now {username}')
|
||||||
advertise_lobbies()
|
advertise_lobbies()
|
||||||
elif ses.game is None or not ses.game.started:
|
elif ses.game is None or not ses.game.started:
|
||||||
@ -178,7 +179,7 @@ def get_me(sid, data):
|
|||||||
else:
|
else:
|
||||||
sid.game.replay(log, speed=0, fast_forward=int(data['ffw']))
|
sid.game.replay(log, speed=0, fast_forward=int(data['ffw']))
|
||||||
return
|
return
|
||||||
if (room := next((g for g in games if g.name == data['name']), None)) is not None:
|
if data['name'] in games and (room := games[data['name']]) is not None:
|
||||||
if not room.started:
|
if not room.started:
|
||||||
join_room(sid, data)
|
join_room(sid, data)
|
||||||
elif room.started:
|
elif room.started:
|
||||||
@ -233,8 +234,7 @@ def disconnect(sid):
|
|||||||
sio.emit('players', room='lobby', data=online_players)
|
sio.emit('players', room='lobby', data=online_players)
|
||||||
if p.game and p.disconnect():
|
if p.game and p.disconnect():
|
||||||
sio.close_room(p.game.name)
|
sio.close_room(p.game.name)
|
||||||
if p.game in games:
|
games.pop(p.game.name)
|
||||||
games.pop(games.index(p.game))
|
|
||||||
print('disconnect ', sid)
|
print('disconnect ', sid)
|
||||||
advertise_lobbies()
|
advertise_lobbies()
|
||||||
Metrics.send_metric('online_players', points=[online_players])
|
Metrics.send_metric('online_players', points=[online_players])
|
||||||
@ -243,15 +243,15 @@ def disconnect(sid):
|
|||||||
@bang_handler
|
@bang_handler
|
||||||
def create_room(sid, room_name):
|
def create_room(sid, room_name):
|
||||||
if (p := sio.get_session(sid)).game is None:
|
if (p := sio.get_session(sid)).game is None:
|
||||||
while any((g.name == room_name for g in games)):
|
while room_name in games:
|
||||||
room_name += f'_{random.randint(0,100)}'
|
room_name += f'_{random.randint(0, 10000)}'
|
||||||
sio.leave_room(sid, 'lobby')
|
sio.leave_room(sid, 'lobby')
|
||||||
sio.enter_room(sid, room_name)
|
sio.enter_room(sid, room_name)
|
||||||
g = Game(room_name)
|
g = Game(room_name)
|
||||||
g.add_player(p)
|
g.add_player(p)
|
||||||
if room_name in blacklist:
|
if room_name in blacklist:
|
||||||
g.is_hidden = True
|
g.is_hidden = True
|
||||||
games.append(g)
|
games[room_name] = g
|
||||||
print(f'{sid} created a room named {room_name}')
|
print(f'{sid} created a room named {room_name}')
|
||||||
advertise_lobbies()
|
advertise_lobbies()
|
||||||
|
|
||||||
@ -282,27 +282,26 @@ def toggle_replace_with_bot(sid):
|
|||||||
@bang_handler
|
@bang_handler
|
||||||
def join_room(sid, room):
|
def join_room(sid, room):
|
||||||
room_name = room['name']
|
room_name = room['name']
|
||||||
i = [g.name for g in games].index(room_name)
|
if games[room_name].password != '' and games[room_name].password != room.get('password', '').upper():
|
||||||
if games[i].password != '' and games[i].password != room.get('password', '').upper():
|
|
||||||
return
|
return
|
||||||
if not games[i].started:
|
if not games[room_name].started:
|
||||||
print(f'{sid} joined a room named {room_name}')
|
print(f'{sid} joined a room named {room_name}')
|
||||||
sio.leave_room(sid, 'lobby')
|
sio.leave_room(sid, 'lobby')
|
||||||
sio.enter_room(sid, room_name)
|
sio.enter_room(sid, room_name)
|
||||||
while any((p.name == sio.get_session(sid).name and not p.is_bot for p in games[i].players)):
|
while any((p.name == sio.get_session(sid).name and not p.is_bot for p in games[room_name].players)):
|
||||||
sio.get_session(sid).name += f'_{random.randint(0,100)}'
|
sio.get_session(sid).name += f'_{random.randint(0,100)}'
|
||||||
sio.emit('me', data=sio.get_session(sid).name, room=sid)
|
sio.emit('me', data=sio.get_session(sid).name, room=sid)
|
||||||
games[i].add_player(sio.get_session(sid))
|
games[room_name].add_player(sio.get_session(sid))
|
||||||
advertise_lobbies()
|
advertise_lobbies()
|
||||||
else:
|
else:
|
||||||
games[i].spectators.append(sio.get_session(sid))
|
games[room_name].spectators.append(sio.get_session(sid))
|
||||||
sio.get_session(sid).game = games[i]
|
sio.get_session(sid).game = games[room_name]
|
||||||
sio.get_session(sid).pending_action = PendingAction.WAIT
|
sio.get_session(sid).pending_action = PendingAction.WAIT
|
||||||
sio.enter_room(sid, games[0].name)
|
sio.enter_room(sid, games[room_name].name)
|
||||||
games[i].notify_room(sid)
|
games[room_name].notify_room(sid)
|
||||||
eventlet.sleep(0.5)
|
eventlet.sleep(0.5)
|
||||||
games[i].notify_room(sid)
|
games[room_name].notify_room(sid)
|
||||||
games[i].notify_all()
|
games[room_name].notify_all()
|
||||||
|
|
||||||
"""
|
"""
|
||||||
Sockets for the status page
|
Sockets for the status page
|
||||||
@ -324,7 +323,7 @@ def get_all_rooms(sid, deploy_key):
|
|||||||
'incremental_turn': g.incremental_turn,
|
'incremental_turn': g.incremental_turn,
|
||||||
'debug': g.debug,
|
'debug': g.debug,
|
||||||
'spectators': len(g.spectators)
|
'spectators': len(g.spectators)
|
||||||
} for g in games])
|
} for g in games.values()])
|
||||||
|
|
||||||
@sio.event
|
@sio.event
|
||||||
@bang_handler
|
@bang_handler
|
||||||
@ -339,16 +338,16 @@ def reset(sid, data):
|
|||||||
global games
|
global games
|
||||||
ses = sio.get_session(sid)
|
ses = sio.get_session(sid)
|
||||||
if ('DEPLOY_KEY' in os.environ and 'key' in data and data['key'] == os.environ['DEPLOY_KEY']) or (isinstance(ses, Player) and ses.is_admin()):
|
if ('DEPLOY_KEY' in os.environ and 'key' in data and data['key'] == os.environ['DEPLOY_KEY']) or (isinstance(ses, Player) and ses.is_admin()):
|
||||||
for g in games:
|
for g in games.values():
|
||||||
sio.emit('kicked', room=g.name)
|
sio.emit('kicked', room=g.name)
|
||||||
games = []
|
games = {}
|
||||||
|
|
||||||
@sio.event
|
@sio.event
|
||||||
@bang_handler
|
@bang_handler
|
||||||
def hide_toogle(sid, data):
|
def hide_toogle(sid, data):
|
||||||
ses = sio.get_session(sid)
|
ses = sio.get_session(sid)
|
||||||
if ('DEPLOY_KEY' in os.environ and 'key' in data and data['key'] == os.environ['DEPLOY_KEY']) or (isinstance(ses, Player) and ses.is_admin()):
|
if ('DEPLOY_KEY' in os.environ and 'key' in data and data['key'] == os.environ['DEPLOY_KEY']) or (isinstance(ses, Player) and ses.is_admin()):
|
||||||
game = [g for g in games if g.name==data['room']]
|
game = games['room']
|
||||||
if len(games) > 0:
|
if len(games) > 0:
|
||||||
game[0].is_hidden = not game[0].is_hidden
|
game[0].is_hidden = not game[0].is_hidden
|
||||||
if game[0].is_hidden:
|
if game[0].is_hidden:
|
||||||
@ -797,7 +796,7 @@ def discord_auth(sid, data):
|
|||||||
def pool_metrics():
|
def pool_metrics():
|
||||||
while True:
|
while True:
|
||||||
sio.sleep(60)
|
sio.sleep(60)
|
||||||
Metrics.send_metric('lobbies', points=[sum(not g.is_replay for g in games)])
|
Metrics.send_metric('lobbies', points=[sum(not g.is_replay for g in games.values())])
|
||||||
Metrics.send_metric('online_players', points=[online_players])
|
Metrics.send_metric('online_players', points=[online_players])
|
||||||
|
|
||||||
import urllib.parse
|
import urllib.parse
|
||||||
@ -830,14 +829,15 @@ def save_games():
|
|||||||
if not os.path.exists("save"):
|
if not os.path.exists("save"):
|
||||||
os.mkdir("save")
|
os.mkdir("save")
|
||||||
with open('./save/games.pickle', 'wb') as f:
|
with open('./save/games.pickle', 'wb') as f:
|
||||||
pickle.dump([g for g in games if g.started and not g.is_replay and not g.is_hidden and len(g.players) > 0], f)
|
pickle.dump([g for g in games.values() if g.started and not g.is_replay and not g.is_hidden and len(g.players) > 0], f)
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
if os.path.exists('./save/games.pickle'):
|
if os.path.exists('./save/games.pickle'):
|
||||||
try:
|
try:
|
||||||
with open('./save/games.pickle', 'rb') as file:
|
with open('./save/games.pickle', 'rb') as file:
|
||||||
games = pickle.load(file)
|
temp_g = pickle.load(file)
|
||||||
for g in games:
|
games = {g.name: g for g in temp_g}
|
||||||
|
for g in games.values():
|
||||||
g.spectators = []
|
g.spectators = []
|
||||||
for p in g.players:
|
for p in g.players:
|
||||||
if p.sid != 'bot':
|
if p.sid != 'bot':
|
||||||
|
@ -50,3 +50,22 @@ def test_ColoradoBill():
|
|||||||
assert p1.lives == 3
|
assert p1.lives == 3
|
||||||
p.play_card(0, p1.name)
|
p.play_card(0, p1.name)
|
||||||
assert p1.pending_action == PendingAction.RESPOND
|
assert p1.pending_action == PendingAction.RESPOND
|
||||||
|
|
||||||
|
# test BlackFlower
|
||||||
|
def test_BlackFlower():
|
||||||
|
g = Game('test')
|
||||||
|
ps = [Player(f'p{i}', f'p{i}') for i in range(2)]
|
||||||
|
for p in ps:
|
||||||
|
g.add_player(p)
|
||||||
|
g.start_game()
|
||||||
|
for p in ps:
|
||||||
|
p.available_characters = [BlackFlower()]
|
||||||
|
p.set_character(p.available_characters[0].name)
|
||||||
|
p = g.players[g.turn]
|
||||||
|
p.draw('')
|
||||||
|
p.hand = [cs.Volcanic(cs.Suit.DIAMONDS,0)]
|
||||||
|
p.special('')
|
||||||
|
assert p.pending_action == PendingAction.PLAY
|
||||||
|
p.hand = [cs.Volcanic(cs.Suit.CLUBS,0)]
|
||||||
|
p.special('')
|
||||||
|
assert p.pending_action == PendingAction.CHOOSE
|
||||||
|
@ -6,9 +6,16 @@
|
|||||||
<div v-else class="center-stuff">
|
<div v-else class="center-stuff">
|
||||||
<h2>{{$t("warning")}}</h2>
|
<h2>{{$t("warning")}}</h2>
|
||||||
<p>{{$t("connection_error")}}</p>
|
<p>{{$t("connection_error")}}</p>
|
||||||
|
<ul v-if="shouldShowBackendSuggestions">
|
||||||
|
Connect to one of these backends:
|
||||||
|
<li v-for="suggestion in backendSuggestions" :key="suggestion.name" @click="changeBackend(suggestion)">
|
||||||
|
{{suggestion.name}}
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
<help v-if="showHelp"/>
|
<help v-if="showHelp"/>
|
||||||
<div style="position:fixed;bottom:4pt;right:4pt;display:flex;z-index:10">
|
<div style="position:fixed;bottom:4pt;right:4pt;display:flex;z-index:10">
|
||||||
|
<input v-if="connect_dev" type=button class="btn" style="min-width:28pt;cursor:pointer;" @click="resetConnection" :value="'💚'+connect_dev" />
|
||||||
<input type=button class="btn" style="min-width:28pt;cursor:pointer;" @click="()=>{sending_report = true}" :value=" $t('report') " />
|
<input type=button class="btn" style="min-width:28pt;cursor:pointer;" @click="()=>{sending_report = true}" :value=" $t('report') " />
|
||||||
<input type="button" class="btn" value="" style="min-width:28pt;cursor:pointer;background-position:center;background-image:url('https://img.icons8.com/color/48/discord-logo.png');background-size:1.5em;background-repeat: no-repeat;" @click="joinDiscord"/>
|
<input type="button" class="btn" value="" style="min-width:28pt;cursor:pointer;background-position:center;background-image:url('https://img.icons8.com/color/48/discord-logo.png');background-size:1.5em;background-repeat: no-repeat;" @click="joinDiscord"/>
|
||||||
<input type="button" class="btn" :value="(showHelp?'X':'?')" style="min-width:28pt;border-radius:100%;cursor:pointer;" @click="getHelp"/>
|
<input type="button" class="btn" :value="(showHelp?'X':'?')" style="min-width:28pt;border-radius:100%;cursor:pointer;" @click="getHelp"/>
|
||||||
@ -63,8 +70,17 @@ export default {
|
|||||||
theme: 'light',
|
theme: 'light',
|
||||||
report: '',
|
report: '',
|
||||||
sending_report: false,
|
sending_report: false,
|
||||||
|
connect_dev: undefined,
|
||||||
|
backendSuggestions: [
|
||||||
|
{ name: 'Bang Xamin', url: 'https://bang.xamin.it' },
|
||||||
|
{ name: 'Bang Miga', url: 'https://bang.migani.synology.me/' },
|
||||||
|
{ name: 'Localhost', url: 'http://localhost:5001' },
|
||||||
|
],
|
||||||
}),
|
}),
|
||||||
computed: {
|
computed: {
|
||||||
|
shouldShowBackendSuggestions() {
|
||||||
|
return window.location.origin.indexOf('vercel') !== -1 || window.location.origin.indexOf('localhost') !== -1
|
||||||
|
},
|
||||||
},
|
},
|
||||||
sockets: {
|
sockets: {
|
||||||
connect() {
|
connect() {
|
||||||
@ -98,6 +114,16 @@ export default {
|
|||||||
// Send message to SW to skip the waiting and activate the new SW
|
// Send message to SW to skip the waiting and activate the new SW
|
||||||
this.registration.waiting.postMessage({ type: 'SKIP_WAITING' })
|
this.registration.waiting.postMessage({ type: 'SKIP_WAITING' })
|
||||||
},
|
},
|
||||||
|
changeBackend(suggestion) {
|
||||||
|
this.$socket.disconnect();
|
||||||
|
window.localStorage.setItem('connect-dev', suggestion.url);
|
||||||
|
window.location.reload();
|
||||||
|
},
|
||||||
|
resetConnection() {
|
||||||
|
this.$socket.disconnect();
|
||||||
|
window.localStorage.removeItem('connect-dev');
|
||||||
|
window.navigation.reload();
|
||||||
|
},
|
||||||
detectColorScheme() {
|
detectColorScheme() {
|
||||||
if(localStorage.getItem("theme")){
|
if(localStorage.getItem("theme")){
|
||||||
this.theme = localStorage.getItem("theme")
|
this.theme = localStorage.getItem("theme")
|
||||||
@ -146,6 +172,9 @@ export default {
|
|||||||
userLang = 'en';
|
userLang = 'en';
|
||||||
this.$i18n.locale = userLang.split('-')[0]
|
this.$i18n.locale = userLang.split('-')[0]
|
||||||
}
|
}
|
||||||
|
if (window.localStorage.getItem('connect-dev')) {
|
||||||
|
this.connect_dev = window.localStorage.getItem('connect-dev')
|
||||||
|
}
|
||||||
this.detectColorScheme()
|
this.detectColorScheme()
|
||||||
if (window.location.origin.indexOf('localhost') !== -1) return;
|
if (window.location.origin.indexOf('localhost') !== -1) return;
|
||||||
datadogRum.init({
|
datadogRum.init({
|
||||||
|
@ -32,7 +32,7 @@ export default {
|
|||||||
},
|
},
|
||||||
suit() {
|
suit() {
|
||||||
if (this.card && !isNaN(this.card.suit)) {
|
if (this.card && !isNaN(this.card.suit)) {
|
||||||
let x = ['♦️','♣️','♥️','♠️']
|
let x = ['♦️','♣️','♥️','♠️','🤑']
|
||||||
return x[this.card.suit];
|
return x[this.card.suit];
|
||||||
} else if (this.card.suit) {
|
} else if (this.card.suit) {
|
||||||
return this.card.suit;
|
return this.card.suit;
|
||||||
@ -89,6 +89,19 @@ export default {
|
|||||||
#816b45 10px
|
#816b45 10px
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
.card:not(.back,.fistful-of-cards,.high-noon,.gold-rush):before{
|
||||||
|
content: "";
|
||||||
|
background-image: radial-gradient(var(--bg-color) 13%, #0000 5%),
|
||||||
|
radial-gradient(var(--bg-color) 14%, transparent 5%),
|
||||||
|
radial-gradient(var(--bg-color) 8%, transparent 5%);
|
||||||
|
background-position: -12px 0, 12px 14px, 0 -12pt;
|
||||||
|
background-size: 50px 50px;
|
||||||
|
position: absolute;
|
||||||
|
top: -10px;
|
||||||
|
left: -10px;
|
||||||
|
bottom: -4px;
|
||||||
|
right: -4px;
|
||||||
|
}
|
||||||
.card.equipment {
|
.card.equipment {
|
||||||
box-shadow:
|
box-shadow:
|
||||||
0 0 0 3pt #5c5e83,
|
0 0 0 3pt #5c5e83,
|
||||||
|
@ -61,7 +61,7 @@
|
|||||||
<div class="tiny-equipment">
|
<div class="tiny-equipment">
|
||||||
<Card v-for="(card, i) in p.equipment" v-bind:key="card.name+card.number"
|
<Card v-for="(card, i) in p.equipment" v-bind:key="card.name+card.number"
|
||||||
:card="card" @click.native="selectedInfo = p.equipment"
|
:card="card" @click.native="selectedInfo = p.equipment"
|
||||||
:style="`margin-top: ${i<1?10:-(Math.min((p.equipment.length+p.gold_rush_equipment.length+1)*12,80))}pt`"/>
|
:style="`margin-top: ${i < 1 ? 10 : -(Math.min((p.equipment.length + p.gold_rush_equipment.length + 1) * 12, 80))}pt;`"/>
|
||||||
<Card v-for="(card, i) in p.gold_rush_equipment" v-bind:key="card.name+card.number"
|
<Card v-for="(card, i) in p.gold_rush_equipment" v-bind:key="card.name+card.number"
|
||||||
:card="card" @click.native="selectedInfo = p.gold_rush_equipment"
|
:card="card" @click.native="selectedInfo = p.gold_rush_equipment"
|
||||||
:style="`margin-top: ${i+p.equipment.length<1?10:-(Math.min((p.equipment.length+p.gold_rush_equipment.length+1)*12,80))}pt`"/>
|
:style="`margin-top: ${i+p.equipment.length<1?10:-(Math.min((p.equipment.length+p.gold_rush_equipment.length+1)*12,80))}pt`"/>
|
||||||
@ -531,8 +531,14 @@ export default {
|
|||||||
transform: scale(0.8);
|
transform: scale(0.8);
|
||||||
margin-bottom: -4pt;
|
margin-bottom: -4pt;
|
||||||
}
|
}
|
||||||
|
.tiny-equipment .card {
|
||||||
|
transform: rotate(2deg);
|
||||||
|
}
|
||||||
|
.tiny-equipment .card:nth-child(odd) {
|
||||||
|
transform: rotate(-2deg);
|
||||||
|
}
|
||||||
.tiny-equipment .card:hover {
|
.tiny-equipment .card:hover {
|
||||||
transform: translateY(10px) scale(1.1);
|
transform: translateY(10px) scale(1.2);
|
||||||
z-index: 1;
|
z-index: 1;
|
||||||
}
|
}
|
||||||
.tiny-character {
|
.tiny-character {
|
||||||
|
@ -169,6 +169,10 @@ export default {
|
|||||||
'Authorization': 'Bearer ' + localStorage.getItem('discord_token')
|
'Authorization': 'Bearer ' + localStorage.getItem('discord_token')
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
.then((res) => {
|
||||||
|
if (res.status !== 200) throw new Error(res.status)
|
||||||
|
return res
|
||||||
|
})
|
||||||
.then(response => response.json())
|
.then(response => response.json())
|
||||||
.then(data => {
|
.then(data => {
|
||||||
console.log(data)
|
console.log(data)
|
||||||
|
@ -3,13 +3,13 @@
|
|||||||
<p v-if="instruction && (lives > 0 || is_ghost)" class="center-stuff">{{instruction}}</p>
|
<p v-if="instruction && (lives > 0 || is_ghost)" class="center-stuff">{{instruction}}</p>
|
||||||
<!-- <button v-if="canEndTurn" @click="end_turn">Termina Turno</button> -->
|
<!-- <button v-if="canEndTurn" @click="end_turn">Termina Turno</button> -->
|
||||||
<div class="equipment-slot">
|
<div class="equipment-slot">
|
||||||
<Card v-if="my_role" :card="my_role" class="back"
|
<Card v-if="my_role" :card="my_role" class="back" style="transform:rotate(-2deg)"
|
||||||
@pointerenter.native="desc=($i18n.locale=='it'?my_role.goal:my_role.goal_eng)" @pointerleave.native="desc=''"/>
|
@pointerenter.native="desc=($i18n.locale=='it'?my_role.goal:my_role.goal_eng)" @pointerleave.native="desc=''"/>
|
||||||
<Card v-if="character" :card="character" style="margin-left: -30pt;margin-right: 0pt;"
|
<Card v-if="character" :card="character" style="margin-left: -30pt;margin-right: 0pt;"
|
||||||
@pointerenter.native="setDesc(character)" @pointerleave.native="desc=''"/>
|
@pointerenter.native="setDesc(character)" @pointerleave.native="desc=''"/>
|
||||||
<transition-group name="list" tag="div" style="display: flex;flex-direction:column; justify-content: space-evenly; margin-left: 12pt;margin-right:-10pt;">
|
<transition-group name="list" tag="div" style="display: flex;flex-direction:column; justify-content: space-evenly; margin-left: 12pt;margin-right:-10pt;">
|
||||||
<span v-for="(n, i) in lives" v-bind:key="i" :alt="i">❤️</span>
|
|
||||||
<span v-for="(n, i) in (max_lives-lives)" v-bind:key="`${i}-sk`" :alt="i">💀</span>
|
<span v-for="(n, i) in (max_lives-lives)" v-bind:key="`${i}-sk`" :alt="i">💀</span>
|
||||||
|
<span v-for="(n, i) in lives" v-bind:key="i" :alt="i">❤️</span>
|
||||||
</transition-group>
|
</transition-group>
|
||||||
<div v-if="gold_nuggets > 0" style="display: flex;align-items: center;margin-left: 12pt;margin-right: -10pt;justify-content: space-evenly;width: 25pt;">
|
<div v-if="gold_nuggets > 0" style="display: flex;align-items: center;margin-left: 12pt;margin-right: -10pt;justify-content: space-evenly;width: 25pt;">
|
||||||
<transition name="list">
|
<transition name="list">
|
||||||
@ -17,7 +17,7 @@
|
|||||||
</transition>
|
</transition>
|
||||||
<span>💵️</span>
|
<span>💵️</span>
|
||||||
</div>
|
</div>
|
||||||
<transition-group v-if="lives > 0 || is_ghost" name="list" tag="div" style="margin: 0 0 0 10pt; display:flex;">
|
<transition-group v-if="lives > 0 || is_ghost" name="list" id="equipment" tag="div" style="margin: 0 0 0 10pt; display:flex;">
|
||||||
<Card v-for="card in equipmentComputed" v-bind:key="card.name+card.number" :card="card"
|
<Card v-for="card in equipmentComputed" v-bind:key="card.name+card.number" :card="card"
|
||||||
@pointerenter.native="setDesc(card)" @pointerleave.native="desc=''"
|
@pointerenter.native="setDesc(card)" @pointerleave.native="desc=''"
|
||||||
@click.native="play_card(card, true)" :class="{'cant-play':((eventCard && eventCard.name == 'Lazo') || (!card.can_be_used_now && !card.is_equipment))}"/>
|
@click.native="play_card(card, true)" :class="{'cant-play':((eventCard && eventCard.name == 'Lazo') || (!card.can_be_used_now && !card.is_equipment))}"/>
|
||||||
@ -390,7 +390,7 @@ export default {
|
|||||||
},
|
},
|
||||||
play_card(card, from_equipment) {
|
play_card(card, from_equipment) {
|
||||||
console.log('play ' + card.name)
|
console.log('play ' + card.name)
|
||||||
if (from_equipment && (!card.can_be_used_now || (this.eventCard && this.eventCard.name == "Lazo"))) return;
|
if (from_equipment && ((!card.can_be_used_now && !card.name == 'Lemat') || (this.eventCard && this.eventCard.name == "Lazo"))) return;
|
||||||
else if (card.usable_next_turn && !card.can_be_used_now) return this.really_play_card(card, null);
|
else if (card.usable_next_turn && !card.can_be_used_now) return this.really_play_card(card, null);
|
||||||
let calamity_special = (card.name === 'Mancato!' && this.character.name === 'Calamity Janet')
|
let calamity_special = (card.name === 'Mancato!' && this.character.name === 'Calamity Janet')
|
||||||
let cant_play_bang = (this.has_played_bang && card.number !==42 && this.equipment.filter(x => x.name == 'Volcanic').length == 0)
|
let cant_play_bang = (this.has_played_bang && card.number !==42 && this.equipment.filter(x => x.name == 'Volcanic').length == 0)
|
||||||
@ -514,8 +514,12 @@ export default {
|
|||||||
margin-left: -30pt;
|
margin-left: -30pt;
|
||||||
}
|
}
|
||||||
.hand>.card:hover {
|
.hand>.card:hover {
|
||||||
margin-right:35pt;
|
transform: translateY(-15px) translateX(-15px) rotate(-2deg);
|
||||||
transform: translateY(-15px);
|
z-index: 1;
|
||||||
|
}
|
||||||
|
.hand>.card:nth-child(1):hover, .hand>.card:last-child:hover {
|
||||||
|
transform: translateY(-15px) translateX(0) rotate(2deg);
|
||||||
|
z-index: 1;
|
||||||
}
|
}
|
||||||
#hand_text{
|
#hand_text{
|
||||||
color: var(--muted-color);
|
color: var(--muted-color);
|
||||||
@ -531,6 +535,12 @@ export default {
|
|||||||
margin: 10pt 0pt;
|
margin: 10pt 0pt;
|
||||||
overflow:auto;
|
overflow:auto;
|
||||||
}
|
}
|
||||||
|
#equipment .card:nth-child(even) {
|
||||||
|
transform: rotate(1deg);
|
||||||
|
}
|
||||||
|
#equipment .card:nth-child(odd) {
|
||||||
|
transform: rotate(-1deg);
|
||||||
|
}
|
||||||
.hurt-notify {
|
.hurt-notify {
|
||||||
pointer-events: none;
|
pointer-events: none;
|
||||||
animation: disappear 0.5s ease-in forwards;
|
animation: disappear 0.5s ease-in forwards;
|
||||||
|
@ -75,6 +75,7 @@
|
|||||||
"choose_complice": "Choose how you will play Pardner!",
|
"choose_complice": "Choose how you will play Pardner!",
|
||||||
"choose_ricercato": "Choose who you will play Wanted against.",
|
"choose_ricercato": "Choose who you will play Wanted against.",
|
||||||
"choose_birra_function": "Choose between getting 1 gold nugget by discarding beer or if you want to play the beer.",
|
"choose_birra_function": "Choose between getting 1 gold nugget by discarding beer or if you want to play the beer.",
|
||||||
|
"choose_play_as_bang": "Choose which card to play as Bang!",
|
||||||
"emporio_others": "{0} is choosing which card to get from the General Store",
|
"emporio_others": "{0} is choosing which card to get from the General Store",
|
||||||
"you_died": "YOU DIED",
|
"you_died": "YOU DIED",
|
||||||
"spectate": "SPECTATE",
|
"spectate": "SPECTATE",
|
||||||
@ -694,7 +695,7 @@
|
|||||||
},
|
},
|
||||||
"Lemat": {
|
"Lemat": {
|
||||||
"name": "Lemat",
|
"name": "Lemat",
|
||||||
"desc": "During your turn you can use any card as BANG!."
|
"desc": "During your turn you can use any card as BANG! (Click on the card once equipped)."
|
||||||
},
|
},
|
||||||
"SerpenteASonagli": {
|
"SerpenteASonagli": {
|
||||||
"name": "Serpente a Sonagli",
|
"name": "Serpente a Sonagli",
|
||||||
|
@ -75,6 +75,7 @@
|
|||||||
"choose_complice": "Scegli come giocare Complice!",
|
"choose_complice": "Scegli come giocare Complice!",
|
||||||
"choose_ricercato": "Scegli il giocatore su cui vuoi giocare Ricercato",
|
"choose_ricercato": "Scegli il giocatore su cui vuoi giocare Ricercato",
|
||||||
"choose_birra_function": "Scegli tra ottenere 1 pepita scartando la birra oppure giocare la birra.",
|
"choose_birra_function": "Scegli tra ottenere 1 pepita scartando la birra oppure giocare la birra.",
|
||||||
|
"choose_play_as_bang": "Scegli che carta giocare come Bang!",
|
||||||
"emporio_others": "{0} sta scegliendo che carta prendere dall'emporio",
|
"emporio_others": "{0} sta scegliendo che carta prendere dall'emporio",
|
||||||
"you_died": "SEI MORTO",
|
"you_died": "SEI MORTO",
|
||||||
"spectate": "SPETTATORE",
|
"spectate": "SPETTATORE",
|
||||||
@ -694,7 +695,7 @@
|
|||||||
},
|
},
|
||||||
"Lemat": {
|
"Lemat": {
|
||||||
"name": "Lemat",
|
"name": "Lemat",
|
||||||
"desc": "Puoi usare ogni carta in mano come BANG!."
|
"desc": "Puoi usare ogni carta in mano come BANG! (Clicca la carta una volta equipaggiata)."
|
||||||
},
|
},
|
||||||
"SerpenteASonagli": {
|
"SerpenteASonagli": {
|
||||||
"name": "Serpente a Sonagli",
|
"name": "Serpente a Sonagli",
|
||||||
|
@ -3,10 +3,17 @@ import App from './App.vue'
|
|||||||
|
|
||||||
Vue.config.productionTip = false
|
Vue.config.productionTip = false
|
||||||
import VueSocketIO from 'bang-vue-socket.io'
|
import VueSocketIO from 'bang-vue-socket.io'
|
||||||
|
if (window.localStorage.getItem('connect-dev')) {
|
||||||
|
Vue.use(new VueSocketIO({
|
||||||
|
debug: true,
|
||||||
|
connection: window.localStorage.getItem('connect-dev'),
|
||||||
|
}))
|
||||||
|
} else {
|
||||||
Vue.use(new VueSocketIO({
|
Vue.use(new VueSocketIO({
|
||||||
debug: Vue.config.devtools,
|
debug: Vue.config.devtools,
|
||||||
connection: Vue.config.devtools ? `http://${window.location.hostname}:5001` : window.location.origin,
|
connection: (Vue.config.devtools) ? `http://${window.location.hostname}:5001` : window.location.origin,
|
||||||
}))
|
}))
|
||||||
|
}
|
||||||
|
|
||||||
import PrettyCheckbox from 'pretty-checkbox-vue';
|
import PrettyCheckbox from 'pretty-checkbox-vue';
|
||||||
Vue.use(PrettyCheckbox)
|
Vue.use(PrettyCheckbox)
|
||||||
|
Loading…
Reference in New Issue
Block a user