Merge pull request #11 from albertoxamin/dev

gameplay and localization fixes
This commit is contained in:
Alberto Xamin 2020-12-13 11:36:44 +01:00 committed by GitHub
commit baa9723536
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
10 changed files with 119 additions and 29 deletions

View File

@ -58,13 +58,38 @@ def get_me(sid, room):
de_games = [g for g in games if g.name == room['name']]
if len(de_games) == 1 and not de_games[0].started:
join_room(sid, room)
elif len(de_games) == 1 and de_games[0].started:
print('room exists')
if room['username'] != None and any([p.name == room['username'] for p in de_games[0].players if p.is_bot]):
print('getting inside the bot')
bot = [p for p in de_games[0].players if p.is_bot][0]
bot.sid = sid
bot.is_bot = False
sio.enter_room(sid, de_games[0].name)
sio.save_session(sid, bot)
de_games[0].notify_room(sid)
eventlet.sleep(0.1)
de_games[0].notify_all()
sio.emit('role', room=sid, data=json.dumps(bot.role, default=lambda o: o.__dict__))
bot.notify_self()
else: #spectate
de_games[0].dead_players.append(sio.get_session(sid))
sio.get_session(sid).game = de_games[0]
sio.enter_room(sid, de_games[0].name)
de_games[0].notify_room(sid)
else:
create_room(sid, room['name'])
if sio.get_session(sid).game == None:
sio.emit('me', data={'error':'Wrong password/Cannot connect'}, room=sid)
else:
sio.emit('me', data=sio.get_session(sid).name, room=sid)
sio.emit('change_username', room=sid)
if room['username'] == None or any([p.name == room['username'] for p in sio.get_session(sid).game.players]):
sio.emit('change_username', room=sid)
else:
sio.get_session(sid).name = room['username']
sio.emit('me', data=sio.get_session(sid).name, room=sid)
if not sio.get_session(sid).game.started:
sio.get_session(sid).game.notify_room()
@sio.event
def disconnect(sid):
@ -101,6 +126,14 @@ def toggle_expansion(sid, expansion_name):
g = sio.get_session(sid).game
g.toggle_expansion(expansion_name)
@sio.event
def toggle_comp(sid):
sio.get_session(sid).game.toggle_competitive()
@sio.event
def toggle_replace_with_bot(sid):
sio.get_session(sid).game.toggle_disconnect_bot()
@sio.event
def join_room(sid, room):
room_name = room['name']
@ -130,9 +163,13 @@ def chat_message(sid, msg):
elif '/removebot' in msg and not ses.game.started:
if any([p.is_bot for p in ses.game.players]):
[p for p in ses.game.players if p.is_bot][-1].disconnect()
elif '/suicide' in msg and ses.game.started:
elif '/suicide' in msg and ses.game.started and ses.lives > 0:
ses.lives = 0
ses.notify_self()
elif '/togglecomp' in msg and ses.game:
ses.game.toggle_competitive()
elif '/togglebot' in msg and ses.game:
ses.game.toggle_disconnect_bot()
elif '/cancelgame' in msg and ses.game.started:
ses.game.reset()
elif '/gameinfo' in msg:

View File

@ -316,7 +316,7 @@ class Mancato(Card):
import bang.characters as chars
if (not player.has_played_bang and against != None and isinstance(player.character, chars.CalamityJanet)):
player.sio.emit('chat_message', room=player.game.name,
data=f'_calamity_special|{player.name}|{self.name}|{against}')
data=f'_special_calamity|{player.name}|{self.name}|{against}')
player.has_played_bang = True
player.game.attack(player, against)
return True

View File

@ -47,7 +47,7 @@ class MollyStark(Character):
def __init__(self):
super().__init__("Molly Stark", max_lives=4)
self.desc = "Quando usa volontariamente una carta che ha in mano, fuori dal suo turno, ne ottiene un'altra dal mazzo"
self.desc_eng = "When she uses a card from her hand outside her turn, he draws a card."
self.desc_eng = "When she uses a card from her hand outside her turn, she draws a card."
self.icon = '🙅‍♀️'
class ApacheKid(Character):

View File

@ -24,14 +24,18 @@ class Game:
self.password = ''
self.expansions = []
self.shutting_down = False
self.is_competitive = False
self.disconnect_bot = True
def notify_room(self):
if len([p for p in self.players if p.character == None]) != 0:
self.sio.emit('room', room=self.name, data={
def notify_room(self, sid=None):
if len([p for p in self.players if p.character == None]) != 0 or sid:
self.sio.emit('room', room=self.name if not sid else sid, data={
'name': self.name,
'started': self.started,
'players': [{'name':p.name, 'ready': p.character != None} for p in self.players],
'password': self.password,
'is_competitive': self.is_competitive,
'disconnect_bot': self.disconnect_bot,
'expansions': self.expansions,
})
@ -44,6 +48,14 @@ class Game:
self.expansions.append(expansion_name)
self.notify_room()
def toggle_competitive(self):
self.is_competitive = not self.is_competitive
self.notify_room()
def toggle_disconnect_bot(self):
self.disconnect_bot = not self.disconnect_bot
self.notify_room()
def add_player(self, player: players.Player):
if player.is_bot and len(self.players) >= 8:
return
@ -73,7 +85,7 @@ class Game:
print(self.name)
print(self.players[i].name)
print(self.players[i].character)
self.sio.emit('chat_message', room=self.name, data=f'_choose_character|{self.players[i].name}|{self.players[i].character.name}|{self.players[i].character.desc}')
self.sio.emit('chat_message', room=self.name, data=f'_choose_character|{self.players[i].name}|{self.players[i].character.name}|{self.players[i].character.desc}|{self.players[i].character.desc_eng}')
self.players[i].prepare()
for k in range(self.players[i].max_lives):
self.players[i].hand.append(self.deck.draw())
@ -102,9 +114,9 @@ class Game:
available_roles: List[roles.Role] = []
if len(self.players) == 3:
available_roles = [
roles.Vice('Elimina il Rinnegato 🦅, se non lo elimini tu elimina anche il Fuorilegge'),
roles.Renegade('Elimina il Fuorilegge 🐺, se non lo elimini tu elimina anche il Vice'),
roles.Outlaw('Elimina il Vice 🎖, se non lo elimini tu elimina anche il Rinnegato')
roles.Vice('Elimina il Rinnegato 🦅, se non lo elimini tu elimina anche il Fuorilegge', 'Kill the Renegade 🦅, if you are not the one who kills him then kill the Outlaw!'),
roles.Renegade('Elimina il Fuorilegge 🐺, se non lo elimini tu elimina anche il Vice', 'Kill the Outlaw 🐺, if you are not the one who kills him then kill the Vice!'),
roles.Outlaw('Elimina il Vice 🎖, se non lo elimini tu elimina anche il Rinnegato', 'Kill the Vice 🎖, if you are not the one who kills him then kill the Renegade!')
]
elif len(self.players) >= 4:
available_roles = [roles.Sheriff(), roles.Renegade(), roles.Outlaw(), roles.Outlaw(), roles.Vice(), roles.Outlaw(), roles.Vice(), roles.Renegade(), roles.Outlaw(), roles.Vice(), roles.Outlaw()]
@ -215,7 +227,10 @@ class Game:
def handle_disconnect(self, player: players.Player):
print(f'player {player.name} left the game {self.name}')
if player in self.players:
self.player_death(player=player, disconnected=True)
if self.disconnect_bot and self.started:
player.is_bot = True
else:
self.player_death(player=player, disconnected=True)
else:
self.dead_players.remove(player)
if len([p for p in self.players if not p.is_bot])+len([p for p in self.dead_players if not p.is_bot]) == 0:
@ -228,9 +243,10 @@ class Game:
else: return False
def player_death(self, player: players.Player, disconnected=False):
if not player in self.players: return
import bang.expansions.dodge_city.characters as chd
print(player.attacker)
if player.attacker and isinstance(player.attacker, roles.Sheriff) and isinstance(player.role, roles.Vice):
if player.attacker and isinstance(player.attacker.role, roles.Sheriff) and isinstance(player.role, roles.Vice):
for i in range(len(player.attacker.hand)):
self.deck.scrap(player.attacker.hand.pop())
for i in range(len(player.attacker.equipment)):
@ -303,6 +319,7 @@ class Game:
print('resetting lobby')
self.players.extend(self.dead_players)
self.dead_players = []
self.players = [p for p in self.players if not p.is_bot]
print(self.players)
self.started = False
self.waiting_for = 0

View File

@ -256,7 +256,11 @@ class Player:
self.choose(randrange(0, len(self.available_cards)))
else:
target = self.game.get_player_named(self.target_p)
self.choose(randrange(0, len(target.hand)+len(target.equipment)))
if len(target.hand)+len(target.equipment) == 0:
self.pending_action = PendingAction.PLAY
self.notify_self()
else:
self.choose(randrange(0, len(target.hand)+len(target.equipment)))
def play_turn(self):
if self.lives == 0:
@ -470,7 +474,7 @@ class Player:
if self.mancato_needed <= 0:
self.game.responders_did_respond_resume_turn()
return
if len([c for c in self.hand if isinstance(c, cs.Mancato) or (isinstance(self.character, chars.CalamityJanet) and isinstance(c, cs.Bang)) or isinstance(self.character, chd.ElenaFuente)]) == 0\
if not self.game.is_competitive and len([c for c in self.hand if isinstance(c, cs.Mancato) or (isinstance(self.character, chars.CalamityJanet) and isinstance(c, cs.Bang)) or isinstance(self.character, chd.ElenaFuente)]) == 0\
and len([c for c in self.equipment if c.can_be_used_now and isinstance(c, cs.Mancato)]) == 0:
self.take_damage_response()
self.game.responders_did_respond_resume_turn()
@ -488,7 +492,7 @@ class Player:
for i in range(len(self.equipment)):
if self.equipment[i].can_be_used_now:
print('usable', self.equipment[i])
if len([c for c in self.equipment if isinstance(c, cs.Barile)]) == 0 and not isinstance(self.character, chars.Jourdonnais)\
if not self.game.is_competitive and len([c for c in self.equipment if isinstance(c, cs.Barile)]) == 0 and not isinstance(self.character, chars.Jourdonnais)\
and len([c for c in self.hand if isinstance(c, cs.Mancato) or (isinstance(self.character, chars.CalamityJanet) and isinstance(c, cs.Bang)) or isinstance(self.character, chd.ElenaFuente)]) == 0\
and len([c for c in self.equipment if c.can_be_used_now and isinstance(c, cs.Mancato)]) == 0:
print('Cant defend')
@ -510,7 +514,7 @@ class Player:
def get_indians(self, attacker):
self.attacker = attacker
if len([c for c in self.hand if isinstance(c, cs.Bang) or (isinstance(self.character, chars.CalamityJanet) and isinstance(c, cs.Mancato))]) == 0:
if not self.game.is_competitive and len([c for c in self.hand if isinstance(c, cs.Bang) or (isinstance(self.character, chars.CalamityJanet) and isinstance(c, cs.Mancato))]) == 0:
print('Cant defend')
self.take_damage_response()
return False
@ -524,7 +528,7 @@ class Player:
def get_dueled(self, attacker):
self.attacker = attacker
if len([c for c in self.hand if isinstance(c, cs.Bang) or (isinstance(self.character, chars.CalamityJanet) and isinstance(c, cs.Mancato))]) == 0:
if not self.game.is_competitive and len([c for c in self.hand if isinstance(c, cs.Bang) or (isinstance(self.character, chars.CalamityJanet) and isinstance(c, cs.Mancato))]) == 0:
print('Cant defend')
self.take_damage_response()
self.game.responders_did_respond_resume_turn()

View File

@ -28,11 +28,12 @@ class Sheriff(Role):
class Vice(Role):
def __init__(self, alternative_goal=None):
def __init__(self, alternative_goal=None, alternative_goal_eng=None):
super().__init__("Vice", "Proteggi lo Sceriffo! Elimina tutti i Fuorilegge e il Rinnegato!")
self.goal_eng = "Protect the Sheriff! Kill the Outlaws and the Renegade!"
if alternative_goal:
self.goal = alternative_goal
self.goal_eng = alternative_goal_eng
self.max_players = 2
self.icon = '🎖'
@ -47,11 +48,12 @@ class Vice(Role):
return False
class Outlaw(Role):
def __init__(self, alternative_goal=None):
def __init__(self, alternative_goal=None, alternative_goal_eng=None):
super().__init__("Fuorilegge", "Elimina lo Sceriffo!")
self.goal_eng = "Kill the Sheriff!"
self.goal_eng = "Kill the sSheriff!"
if alternative_goal:
self.goal = alternative_goal
self.goal_eng = alternative_goal_eng
self.max_players = 3
self.icon = '🐺'
@ -66,11 +68,12 @@ class Outlaw(Role):
return False
class Renegade(Role):
def __init__(self, alternative_goal=None):
def __init__(self, alternative_goal=None, alternative_goal_eng=None):
super().__init__("Rinnegato", "Rimani l'ultimo personaggio in gioco!")
self.goal_eng = "Be the last man standing!"
if alternative_goal:
self.goal = alternative_goal
self.goal_eng = alternative_goal_eng
self.max_players = 1
self.icon = '🦅'

View File

@ -7,7 +7,7 @@
<h2>{{$t("warning")}}</h2>
<p>{{$t("connection_error")}}</p>
</div>
<select style="position:fixed;bottom:4pt;right:4pt;" v-model="$i18n.locale">
<select style="position:fixed;bottom:4pt;right:4pt;" v-model="$i18n.locale" @change="storeLangPref">
<option
v-for="(lang, i) in ['it.🇮🇹.Italiano', 'en.🇬🇧.English']"
:key="`lang-${i}`"
@ -42,8 +42,13 @@ export default {
},
},
methods: {
storeLangPref() {
localStorage.setItem('lang', this.$i18n.locale)
}
},
mounted() {
if (localStorage.getItem('lang'))
this.$i18n.locale = localStorage.getItem('lang')
},
}
</script>

View File

@ -31,6 +31,10 @@
<div v-if="!started">
<h3>{{$t("expansions")}}</h3>
<PrettyCheck @click.native="toggleExpansions('dodge_city')" :disabled="!isRoomOwner" v-model="useDodgeCity" class="p-switch p-fill" style="margin-top:5px; margin-bottom:3px;">Dodge City</PrettyCheck>
<h3>{{$t('mods')}}</h3>
<PrettyCheck @click.native="toggleCompetitive" :disabled="!isRoomOwner" v-model="is_competitive" class="p-switch p-fill" style="margin-top:5px; margin-bottom:3px;">{{$t('mod_comp')}}</PrettyCheck>
<br>
<PrettyCheck @click.native="toggleReplaceWithBot" :disabled="!isRoomOwner" v-model="disconnect_bot" class="p-switch p-fill" style="margin-top:5px; margin-bottom:3px;">{{$t('disconnect_bot')}}</PrettyCheck>
</div>
<div v-if="started">
<deck :endTurnAction="()=>{wantsToEndTurn = true}"/>
@ -85,12 +89,17 @@ export default {
password: '',
useDodgeCity: false,
hasToSetUsername: false,
is_competitive: false,
disconnect_bot: false,
}),
sockets: {
room(data) {
this.lobbyName = data.name
this.started = data.started
this.password = data.password
this.privateRoom = data.password !== ''
this.is_competitive = data.is_competitive
this.disconnect_bot = data.disconnect_bot
this.useDodgeCity = data.expansions.indexOf('dodge_city') !== -1
this.players = data.players.map(x => {
return {
@ -160,6 +169,14 @@ export default {
if (!this.isRoomOwner) return;
this.$socket.emit('toggle_expansion', name)
},
toggleCompetitive() {
if (!this.isRoomOwner) return;
this.$socket.emit('toggle_comp')
},
toggleReplaceWithBot() {
if (!this.isRoomOwner) return;
this.$socket.emit('toggle_replace_with_bot')
},
getActionEmoji(p) {
if (p.is_my_turn === undefined || p.pending_action === undefined) return '';
if (p.pending_action != 4) {
@ -221,15 +238,16 @@ export default {
},
},
watch: {
privateRoom() {
this.$socket.emit('private')
privateRoom(old, _new) {
if (this.isRoomOwner && old !== _new)
this.$socket.emit('private')
}
},
mounted() {
console.log('mounted lobby')
if (!this.$route.query.code)
return this.$router.push('/')
this.$socket.emit('get_me', {name:this.$route.query.code, password:this.$route.query.pwd})
this.$socket.emit('get_me', {name:this.$route.query.code, password:this.$route.query.pwd, username: localStorage.getItem('username')})
},
}
</script>

View File

@ -59,7 +59,7 @@
"died": "{0} died",
"died_role": "{0} was a {1}!",
"won": "{0} won!",
"choose_character": "{0} has {1} as character, his special ability is: {2}!",
"choose_character": "{0} has {1} as character, his special ability is: {3}!",
"starting": "The game is starting!",
"sheriff": "{0} is the sheriff!",
"did_choose_character": "{0} did choose the character.",
@ -79,5 +79,8 @@
"special_bart_cassidy": "{0} received a compensation because he was injured.",
"special_el_gringo": "{0} stole a card from {1} when he was was injured.",
"special_calamity": "{0} played {1} as Bang! against {2}."
}
},
"mods": "Modifiers",
"mod_comp": "Competitive mode (disables automatic take damage)",
"disconnect_bot": "Replace players that disconnect with bots"
}

View File

@ -79,5 +79,8 @@
"special_bart_cassidy": "{0} ha ricevuto un risarcimento perchè è stato ferito.",
"special_el_gringo": "{0} rubato una carta a {1} mentre veniva colpito.",
"special_calamity": "{0} ha giovato {1} come un Bang! contro {2}."
}
},
"mods": "Modificatori",
"mod_comp": "Modalità competitiva (disattiva il prendi danno automatico)",
"disconnect_bot": "Sostituisci i giocatori che si disconnettono con bot"
}