Merge branch 'equipment' into doc
This commit is contained in:
commit
2dc178d67c
|
@ -23,15 +23,16 @@ class StatsDisplay(Display):
|
||||||
self.player = game.player
|
self.player = game.player
|
||||||
|
|
||||||
def update_pad(self) -> None:
|
def update_pad(self) -> None:
|
||||||
string2 = "Player -- LVL {}\nEXP {}/{}\nHP {}/{}"\
|
string2 = _("player").capitalize() + " -- LVL {}\nEXP {}/{}\nHP {}/{}"\
|
||||||
.format(self.player.level, self.player.current_xp,
|
.format(self.player.level, self.player.current_xp,
|
||||||
self.player.max_xp, self.player.health,
|
self.player.max_xp, self.player.health,
|
||||||
self.player.maxhealth)
|
self.player.maxhealth)
|
||||||
self.addstr(self.pad, 0, 0, string2)
|
self.addstr(self.pad, 0, 0, string2)
|
||||||
string3 = "STR {}\nINT {}\nCHR {}\nDEX {}\nCON {}"\
|
string3 = "STR {}\nINT {}\nCHR {}\nDEX {}\nCON {}\nCRI {}%"\
|
||||||
.format(self.player.strength,
|
.format(self.player.strength,
|
||||||
self.player.intelligence, self.player.charisma,
|
self.player.intelligence, self.player.charisma,
|
||||||
self.player.dexterity, self.player.constitution)
|
self.player.dexterity, self.player.constitution,\
|
||||||
|
self.player.critical)
|
||||||
self.addstr(self.pad, 3, 0, string3)
|
self.addstr(self.pad, 3, 0, string3)
|
||||||
|
|
||||||
inventory_str = _("Inventory:") + " "
|
inventory_str = _("Inventory:") + " "
|
||||||
|
@ -47,13 +48,30 @@ class StatsDisplay(Display):
|
||||||
if count > 1:
|
if count > 1:
|
||||||
inventory_str += f"x{count} "
|
inventory_str += f"x{count} "
|
||||||
printed_items.append(item)
|
printed_items.append(item)
|
||||||
self.addstr(self.pad, 8, 0, inventory_str)
|
self.addstr(self.pad, 9, 0, inventory_str)
|
||||||
|
|
||||||
self.addstr(self.pad, 9, 0, f"{self.pack.HAZELNUT} "
|
if self.player.equipped_main:
|
||||||
f"x{self.player.hazel}")
|
self.addstr(self.pad, 10, 0,
|
||||||
|
_("Equipped main:") + " "
|
||||||
|
f"{self.pack[self.player.equipped_main.name.upper()]}")
|
||||||
|
if self.player.equipped_secondary:
|
||||||
|
self.addstr(self.pad, 11, 0,
|
||||||
|
_("Equipped secondary:") + " "
|
||||||
|
f"{self.pack[self.player.equipped_secondary.name.upper()]}")
|
||||||
|
if self.player.equipped_armor:
|
||||||
|
self.addstr(self.pad, 12, 0,
|
||||||
|
_("Equipped chestplate:") + " "
|
||||||
|
f"{self.pack[self.player.equipped_armor.name.upper()]}")
|
||||||
|
if self.player.equipped_helmet:
|
||||||
|
self.addstr(self.pad, 13, 0,
|
||||||
|
_("Equipped helmet:") + " "
|
||||||
|
f"{self.pack[self.player.equipped_helmet.name.upper()]}")
|
||||||
|
|
||||||
|
self.addstr(self.pad, 14, 0, f"{self.pack.HAZELNUT} "
|
||||||
|
f"x{self.player.hazel}")
|
||||||
|
|
||||||
if self.player.dead:
|
if self.player.dead:
|
||||||
self.addstr(self.pad, 11, 0, _("YOU ARE DEAD"), curses.COLOR_RED,
|
self.addstr(self.pad, 15, 0, _("YOU ARE DEAD"), curses.COLOR_RED,
|
||||||
bold=True, blink=True, standout=True)
|
bold=True, blink=True, standout=True)
|
||||||
|
|
||||||
def display(self) -> None:
|
def display(self) -> None:
|
||||||
|
|
|
@ -34,6 +34,12 @@ class TexturePack:
|
||||||
TIGER: str
|
TIGER: str
|
||||||
TRUMPET: str
|
TRUMPET: str
|
||||||
WALL: str
|
WALL: str
|
||||||
|
EAGLE: str
|
||||||
|
SHIELD: str
|
||||||
|
CHESTPLATE: str
|
||||||
|
HELMET: str
|
||||||
|
RING_OF_MORE_EXPERIENCE: str
|
||||||
|
RING_OF_CRITICAL_DAMAGE: str
|
||||||
|
|
||||||
ASCII_PACK: "TexturePack"
|
ASCII_PACK: "TexturePack"
|
||||||
SQUIRREL_PACK: "TexturePack"
|
SQUIRREL_PACK: "TexturePack"
|
||||||
|
@ -64,7 +70,7 @@ TexturePack.ASCII_PACK = TexturePack(
|
||||||
entity_bg_color=curses.COLOR_BLACK,
|
entity_bg_color=curses.COLOR_BLACK,
|
||||||
|
|
||||||
BODY_SNATCH_POTION='S',
|
BODY_SNATCH_POTION='S',
|
||||||
BOMB='o',
|
BOMB='ç',
|
||||||
EMPTY=' ',
|
EMPTY=' ',
|
||||||
EXPLOSION='%',
|
EXPLOSION='%',
|
||||||
FLOOR='.',
|
FLOOR='.',
|
||||||
|
@ -74,12 +80,18 @@ TexturePack.ASCII_PACK = TexturePack(
|
||||||
MERCHANT='M',
|
MERCHANT='M',
|
||||||
PLAYER='@',
|
PLAYER='@',
|
||||||
RABBIT='Y',
|
RABBIT='Y',
|
||||||
|
SHIELD='D',
|
||||||
SUNFLOWER='I',
|
SUNFLOWER='I',
|
||||||
SWORD='\u2020',
|
SWORD='\u2020',
|
||||||
TEDDY_BEAR='8',
|
TEDDY_BEAR='8',
|
||||||
TIGER='n',
|
TIGER='n',
|
||||||
TRUMPET='/',
|
TRUMPET='/',
|
||||||
WALL='#',
|
WALL='#',
|
||||||
|
EAGLE='µ',
|
||||||
|
CHESTPLATE='(',
|
||||||
|
HELMET='0',
|
||||||
|
RING_OF_MORE_EXPERIENCE='o',
|
||||||
|
RING_OF_CRITICAL_DAMAGE='o',
|
||||||
)
|
)
|
||||||
|
|
||||||
TexturePack.SQUIRREL_PACK = TexturePack(
|
TexturePack.SQUIRREL_PACK = TexturePack(
|
||||||
|
@ -101,10 +113,16 @@ TexturePack.SQUIRREL_PACK = TexturePack(
|
||||||
PLAYER='🐿️ ️',
|
PLAYER='🐿️ ️',
|
||||||
MERCHANT='🦜',
|
MERCHANT='🦜',
|
||||||
RABBIT='🐇',
|
RABBIT='🐇',
|
||||||
|
SHIELD='🛡️ ',
|
||||||
SUNFLOWER='🌻',
|
SUNFLOWER='🌻',
|
||||||
SWORD='🗡️ ',
|
SWORD='🗡️ ',
|
||||||
TEDDY_BEAR='🧸',
|
TEDDY_BEAR='🧸',
|
||||||
TIGER='🐅',
|
TIGER='🐅',
|
||||||
TRUMPET='🎺',
|
TRUMPET='🎺',
|
||||||
WALL='🧱',
|
WALL='🧱',
|
||||||
|
EAGLE='🦅',
|
||||||
|
CHESTPLATE='🦺',
|
||||||
|
HELMET='⛑️',
|
||||||
|
RING_OF_MORE_EXPERIENCE='💍',
|
||||||
|
RING_OF_CRITICAL_DAMAGE='💍',
|
||||||
)
|
)
|
||||||
|
|
|
@ -4,7 +4,6 @@
|
||||||
from random import choice, randint
|
from random import choice, randint
|
||||||
from typing import Optional
|
from typing import Optional
|
||||||
|
|
||||||
from .player import Player
|
|
||||||
from ..interfaces import Entity, FightingEntity, Map, InventoryHolder
|
from ..interfaces import Entity, FightingEntity, Map, InventoryHolder
|
||||||
from ..translations import gettext as _
|
from ..translations import gettext as _
|
||||||
|
|
||||||
|
@ -30,7 +29,7 @@ class Item(Entity):
|
||||||
The item is dropped from the inventory onto the floor.
|
The item is dropped from the inventory onto the floor.
|
||||||
"""
|
"""
|
||||||
if self.held:
|
if self.held:
|
||||||
self.held_by.inventory.remove(self)
|
self.held_by.remove_from_inventory(self)
|
||||||
self.held_by.map.add_entity(self)
|
self.held_by.map.add_entity(self)
|
||||||
self.move(self.held_by.y, self.held_by.x)
|
self.move(self.held_by.y, self.held_by.x)
|
||||||
self.held = False
|
self.held = False
|
||||||
|
@ -45,15 +44,58 @@ class Item(Entity):
|
||||||
"""
|
"""
|
||||||
Indicates what should be done when the item is equipped.
|
Indicates what should be done when the item is equipped.
|
||||||
"""
|
"""
|
||||||
|
if isinstance(self, Chestplate):
|
||||||
|
if self.held_by.equipped_armor:
|
||||||
|
self.held_by.equipped_armor.unequip()
|
||||||
|
self.held_by.remove_from_inventory(self)
|
||||||
|
self.held_by.equipped_armor = self
|
||||||
|
elif isinstance(self, Helmet):
|
||||||
|
if self.held_by.equipped_helmet:
|
||||||
|
self.held_by.equipped_helmet.unequip()
|
||||||
|
self.held_by.remove_from_inventory(self)
|
||||||
|
self.held_by.equipped_helmet = self
|
||||||
|
elif isinstance(self, Weapon):
|
||||||
|
if self.held_by.equipped_main:
|
||||||
|
if self.held_by.equipped_secondary:
|
||||||
|
self.held_by.equipped_secondary.unequip()
|
||||||
|
self.held_by.remove_from_inventory(self)
|
||||||
|
self.held_by.equipped_secondary = self
|
||||||
|
# For weapons, they are equipped as main only if main is empty.
|
||||||
|
else:
|
||||||
|
self.held_by.remove_from_inventory(self)
|
||||||
|
self.held_by.equipped_main = self
|
||||||
|
else:
|
||||||
|
# Other objects are only equipped as secondary.
|
||||||
|
if self.held_by.equipped_secondary:
|
||||||
|
self.held_by.equipped_secondary.unequip()
|
||||||
|
self.held_by.remove_from_inventory(self)
|
||||||
|
self.held_by.equipped_secondary = self
|
||||||
|
|
||||||
def hold(self, player: InventoryHolder) -> None:
|
def unequip(self) -> None:
|
||||||
|
"""
|
||||||
|
Indicates what should be done when the item is unequipped.
|
||||||
|
"""
|
||||||
|
if isinstance(self, Chestplate):
|
||||||
|
self.held_by.equipped_armor = None
|
||||||
|
elif isinstance(self, Helmet):
|
||||||
|
self.held_by.equipped_helmet = None
|
||||||
|
elif isinstance(self, Weapon):
|
||||||
|
if self.held_by.equipped_main == self:
|
||||||
|
self.held_by.equipped_main = None
|
||||||
|
else:
|
||||||
|
self.held_by.equipped_secondary = None
|
||||||
|
else:
|
||||||
|
self.held_by.equipped_secondary = None
|
||||||
|
self.held_by.add_to_inventory(self)
|
||||||
|
|
||||||
|
def hold(self, holder: InventoryHolder) -> None:
|
||||||
"""
|
"""
|
||||||
The item is taken from the floor and put into the inventory.
|
The item is taken from the floor and put into the inventory.
|
||||||
"""
|
"""
|
||||||
self.held = True
|
self.held = True
|
||||||
self.held_by = player
|
self.held_by = holder
|
||||||
self.held_by.map.remove_entity(self)
|
self.held_by.map.remove_entity(self)
|
||||||
player.add_to_inventory(self)
|
holder.add_to_inventory(self)
|
||||||
|
|
||||||
def save_state(self) -> dict:
|
def save_state(self) -> dict:
|
||||||
"""
|
"""
|
||||||
|
@ -68,7 +110,8 @@ class Item(Entity):
|
||||||
"""
|
"""
|
||||||
Returns the list of all item classes.
|
Returns the list of all item classes.
|
||||||
"""
|
"""
|
||||||
return [BodySnatchPotion, Bomb, Heart, Sword]
|
return [BodySnatchPotion, Bomb, Heart, Shield, Sword,\
|
||||||
|
Chestplate, Helmet, RingCritical, RingXP]
|
||||||
|
|
||||||
def be_sold(self, buyer: InventoryHolder, seller: InventoryHolder) -> bool:
|
def be_sold(self, buyer: InventoryHolder, seller: InventoryHolder) -> bool:
|
||||||
"""
|
"""
|
||||||
|
@ -120,7 +163,7 @@ class Bomb(Item):
|
||||||
"""
|
"""
|
||||||
damage: int = 5
|
damage: int = 5
|
||||||
exploding: bool
|
exploding: bool
|
||||||
owner: Optional["Player"]
|
owner: Optional["InventoryHolder"]
|
||||||
tick: int
|
tick: int
|
||||||
|
|
||||||
def __init__(self, name: str = "bomb", damage: int = 5,
|
def __init__(self, name: str = "bomb", damage: int = 5,
|
||||||
|
@ -214,14 +257,80 @@ class Weapon(Item):
|
||||||
d["damage"] = self.damage
|
d["damage"] = self.damage
|
||||||
return d
|
return d
|
||||||
|
|
||||||
|
def equip(self) -> None:
|
||||||
|
"""
|
||||||
|
When a weapon is equipped, the player gains strength.
|
||||||
|
"""
|
||||||
|
super().equip()
|
||||||
|
self.held_by.strength += self.damage
|
||||||
|
|
||||||
|
def unequip(self) -> None:
|
||||||
|
"""
|
||||||
|
Remove the strength earned by the weapon.
|
||||||
|
:return:
|
||||||
|
"""
|
||||||
|
super().unequip()
|
||||||
|
self.held_by.strength -= self.damage
|
||||||
|
|
||||||
|
|
||||||
class Sword(Weapon):
|
class Sword(Weapon):
|
||||||
"""
|
"""
|
||||||
A basic weapon
|
A basic weapon
|
||||||
"""
|
"""
|
||||||
def __init__(self, name: str = "sword", price: int = 20, *args, **kwargs):
|
def __init__(self, name: str = "sword", price: int = 20,
|
||||||
|
*args, **kwargs):
|
||||||
super().__init__(name=name, price=price, *args, **kwargs)
|
super().__init__(name=name, price=price, *args, **kwargs)
|
||||||
self.name = name
|
|
||||||
|
|
||||||
|
class Armor(Item):
|
||||||
|
"""
|
||||||
|
Class of items that increase the player's constitution.
|
||||||
|
"""
|
||||||
|
constitution: int
|
||||||
|
|
||||||
|
def __init__(self, constitution: int, *args, **kwargs):
|
||||||
|
super().__init__(*args, **kwargs)
|
||||||
|
self.constitution = constitution
|
||||||
|
|
||||||
|
def equip(self) -> None:
|
||||||
|
super().equip()
|
||||||
|
self.held_by.constitution += self.constitution
|
||||||
|
|
||||||
|
def unequip(self) -> None:
|
||||||
|
super().unequip()
|
||||||
|
self.held_by.constitution -= self.constitution
|
||||||
|
|
||||||
|
def save_state(self) -> dict:
|
||||||
|
d = super().save_state()
|
||||||
|
d["constitution"] = self.constitution
|
||||||
|
return d
|
||||||
|
|
||||||
|
class Shield(Armor):
|
||||||
|
"""
|
||||||
|
Class of shield items, they can be equipped in the other hand.
|
||||||
|
"""
|
||||||
|
|
||||||
|
def __init__(self, name: str = "shield", constitution: int = 2,\
|
||||||
|
price: int = 6, *args, **kwargs):
|
||||||
|
super().__init__(name=name, constitution=constitution, *args, **kwargs)
|
||||||
|
|
||||||
|
class Helmet(Armor):
|
||||||
|
"""
|
||||||
|
Class of helmet items, they can be equipped on the head.
|
||||||
|
"""
|
||||||
|
|
||||||
|
def __init__(self, name: str = "helmet", constitution: int = 2, \
|
||||||
|
price: int = 8, *args, **kwargs):
|
||||||
|
super().__init__(name=name, constitution=constitution, *args, **kwargs)
|
||||||
|
|
||||||
|
class Chestplate(Armor):
|
||||||
|
"""
|
||||||
|
Class of chestplate items, they can be equipped on the body.
|
||||||
|
"""
|
||||||
|
|
||||||
|
def __init__(self, name: str = "chestplate", constitution: int = 4,\
|
||||||
|
price: int = 15, *args, **kwargs):
|
||||||
|
super().__init__(name=name, constitution=constitution, *args, **kwargs)
|
||||||
|
|
||||||
|
|
||||||
class BodySnatchPotion(Item):
|
class BodySnatchPotion(Item):
|
||||||
|
@ -256,3 +365,69 @@ class BodySnatchPotion(Item):
|
||||||
self.held_by.recalculate_paths()
|
self.held_by.recalculate_paths()
|
||||||
|
|
||||||
self.held_by.inventory.remove(self)
|
self.held_by.inventory.remove(self)
|
||||||
|
|
||||||
|
class Ring(Item):
|
||||||
|
"""
|
||||||
|
A class of rings that boost the player's statistics.
|
||||||
|
"""
|
||||||
|
maxhealth: int
|
||||||
|
strength: int
|
||||||
|
intelligence: int
|
||||||
|
charisma: int
|
||||||
|
dexterity: int
|
||||||
|
constitution: int
|
||||||
|
critical: int
|
||||||
|
experience: float
|
||||||
|
|
||||||
|
def __init__(self, maxhealth: int = 0, strength: int = 0,\
|
||||||
|
intelligence: int = 0, charisma: int = 0,\
|
||||||
|
dexterity: int = 0, constitution: int = 0,\
|
||||||
|
critical: int = 0, experience: float = 0, *args, **kwargs):
|
||||||
|
super().__init__(*args, **kwargs)
|
||||||
|
self.maxhealth = maxhealth
|
||||||
|
self.strength = strength
|
||||||
|
self.intelligence = intelligence
|
||||||
|
self.charisma = charisma
|
||||||
|
self.dexterity = dexterity
|
||||||
|
self.constitution = constitution
|
||||||
|
self.critical = critical
|
||||||
|
self.experience = experience
|
||||||
|
|
||||||
|
def equip(self) -> None:
|
||||||
|
super().equip()
|
||||||
|
self.held_by.maxhealth += self.maxhealth
|
||||||
|
self.held_by.strength += self.strength
|
||||||
|
self.held_by.intelligence += self.intelligence
|
||||||
|
self.held_by.charisma += self.charisma
|
||||||
|
self.held_by.dexterity += self.dexterity
|
||||||
|
self.held_by.constitution += self.constitution
|
||||||
|
self.held_by.critical += self.critical
|
||||||
|
self.held_by.xp_buff += self.experience
|
||||||
|
|
||||||
|
def unequip(self) -> None:
|
||||||
|
super().unequip()
|
||||||
|
self.held_by.maxhealth -= self.maxhealth
|
||||||
|
self.held_by.strength -= self.strength
|
||||||
|
self.held_by.intelligence -= self.intelligence
|
||||||
|
self.held_by.charisma -= self.charisma
|
||||||
|
self.held_by.dexterity -= self.dexterity
|
||||||
|
self.held_by.constitution -= self.constitution
|
||||||
|
self.held_by.critical -= self.critical
|
||||||
|
self.held_by.xp_buff -= self.experience
|
||||||
|
|
||||||
|
def save_state(self) -> dict:
|
||||||
|
d = super().save_state()
|
||||||
|
d["constitution"] = self.constitution
|
||||||
|
return d
|
||||||
|
|
||||||
|
class RingCritical(Ring):
|
||||||
|
def __init__(self, name: str = "ring_of_critical_damage", price: int = 15,
|
||||||
|
critical: int = 20, *args, **kwargs):
|
||||||
|
super().__init__(name=name, price=price, critical=critical, \
|
||||||
|
*args, **kwargs)
|
||||||
|
|
||||||
|
class RingXP(Ring):
|
||||||
|
def __init__(self, name: str = "ring_of_more_experience", price: int = 25,
|
||||||
|
experience: float = 2, *args, **kwargs):
|
||||||
|
super().__init__(name=name, price=price, experience=experience, \
|
||||||
|
*args, **kwargs)
|
||||||
|
|
|
@ -94,9 +94,9 @@ class Rabbit(Monster):
|
||||||
A rabbit monster.
|
A rabbit monster.
|
||||||
"""
|
"""
|
||||||
def __init__(self, name: str = "rabbit", strength: int = 1,
|
def __init__(self, name: str = "rabbit", strength: int = 1,
|
||||||
maxhealth: int = 15, *args, **kwargs) -> None:
|
maxhealth: int = 15, critical: int = 30, *args, **kwargs) -> None:
|
||||||
super().__init__(name=name, strength=strength,
|
super().__init__(name=name, strength=strength,
|
||||||
maxhealth=maxhealth, *args, **kwargs)
|
maxhealth=maxhealth, critical=critical, *args, **kwargs)
|
||||||
|
|
||||||
|
|
||||||
class TeddyBear(Monster):
|
class TeddyBear(Monster):
|
||||||
|
@ -107,3 +107,12 @@ class TeddyBear(Monster):
|
||||||
maxhealth: int = 50, *args, **kwargs) -> None:
|
maxhealth: int = 50, *args, **kwargs) -> None:
|
||||||
super().__init__(name=name, strength=strength,
|
super().__init__(name=name, strength=strength,
|
||||||
maxhealth=maxhealth, *args, **kwargs)
|
maxhealth=maxhealth, *args, **kwargs)
|
||||||
|
|
||||||
|
class GiantSeaEagle(Monster):
|
||||||
|
"""
|
||||||
|
An eagle boss
|
||||||
|
"""
|
||||||
|
def __init__(self, name: str = "eagle", strength: int = 1000,
|
||||||
|
maxhealth: int = 5000, *args, **kwargs) -> None:
|
||||||
|
super().__init__(name=name, strength=strength,
|
||||||
|
maxhealth=maxhealth, *args, **kwargs)
|
||||||
|
|
|
@ -2,7 +2,9 @@
|
||||||
# SPDX-License-Identifier: GPL-3.0-or-later
|
# SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
|
|
||||||
from random import randint
|
from random import randint
|
||||||
|
from typing import Dict, Optional, Tuple
|
||||||
|
|
||||||
|
from .items import Item
|
||||||
from ..interfaces import FightingEntity, InventoryHolder
|
from ..interfaces import FightingEntity, InventoryHolder
|
||||||
|
|
||||||
|
|
||||||
|
@ -12,22 +14,44 @@ class Player(InventoryHolder, FightingEntity):
|
||||||
"""
|
"""
|
||||||
current_xp: int = 0
|
current_xp: int = 0
|
||||||
max_xp: int = 10
|
max_xp: int = 10
|
||||||
|
xp_buff: float = 1
|
||||||
|
paths: Dict[Tuple[int, int], Tuple[int, int]]
|
||||||
|
equipped_main: Optional[Item]
|
||||||
|
equipped_secondary: Optional[Item]
|
||||||
|
equipped_helmet: Optional[Item]
|
||||||
|
equipped_armor: Optional[Item]
|
||||||
|
|
||||||
def __init__(self, name: str = "player", maxhealth: int = 20,
|
def __init__(self, name: str = "player", maxhealth: int = 20,
|
||||||
strength: int = 5, intelligence: int = 1, charisma: int = 1,
|
strength: int = 5, intelligence: int = 1, charisma: int = 1,
|
||||||
dexterity: int = 1, constitution: int = 1, level: int = 1,
|
dexterity: int = 1, constitution: int = 1, level: int = 1,
|
||||||
current_xp: int = 0, max_xp: int = 10, inventory: list = None,
|
current_xp: int = 0, max_xp: int = 10, inventory: list = None,
|
||||||
hazel: int = 42, *args, **kwargs) \
|
hazel: int = 42, equipped_main: Optional[Item] = None,
|
||||||
-> None:
|
equipped_armor: Optional[Item] = None, critical: int = 5,\
|
||||||
|
equipped_secondary: Optional[Item] = None, \
|
||||||
|
equipped_helmet: Optional[Item] = None, xp_buff: float = 1,\
|
||||||
|
*args, **kwargs) -> None:
|
||||||
super().__init__(name=name, maxhealth=maxhealth, strength=strength,
|
super().__init__(name=name, maxhealth=maxhealth, strength=strength,
|
||||||
intelligence=intelligence, charisma=charisma,
|
intelligence=intelligence, charisma=charisma,
|
||||||
dexterity=dexterity, constitution=constitution,
|
dexterity=dexterity, constitution=constitution,
|
||||||
level=level, *args, **kwargs)
|
level=level, critical=critical, *args, **kwargs)
|
||||||
self.current_xp = current_xp
|
self.current_xp = current_xp
|
||||||
self.max_xp = max_xp
|
self.max_xp = max_xp
|
||||||
|
self.xp_buff = xp_buff
|
||||||
self.inventory = self.translate_inventory(inventory or [])
|
self.inventory = self.translate_inventory(inventory or [])
|
||||||
self.paths = dict()
|
self.paths = dict()
|
||||||
self.hazel = hazel
|
self.hazel = hazel
|
||||||
|
if isinstance(equipped_main, dict):
|
||||||
|
equipped_main = self.dict_to_item(equipped_main)
|
||||||
|
if isinstance(equipped_armor, dict):
|
||||||
|
equipped_armor = self.dict_to_item(equipped_armor)
|
||||||
|
if isinstance(equipped_secondary, dict):
|
||||||
|
equipped_secondary = self.dict_to_item(equipped_secondary)
|
||||||
|
if isinstance(equipped_helmet, dict):
|
||||||
|
equipped_helmet = self.dict_to_item(equipped_helmet)
|
||||||
|
self.equipped_main = equipped_main
|
||||||
|
self.equipped_armor = equipped_armor
|
||||||
|
self.equipped_secondary = equipped_secondary
|
||||||
|
self.equipped_helmet = equipped_helmet
|
||||||
|
|
||||||
def move(self, y: int, x: int) -> None:
|
def move(self, y: int, x: int) -> None:
|
||||||
"""
|
"""
|
||||||
|
@ -58,9 +82,24 @@ class Player(InventoryHolder, FightingEntity):
|
||||||
Adds some experience to the player.
|
Adds some experience to the player.
|
||||||
If the required amount is reached, the player levels up.
|
If the required amount is reached, the player levels up.
|
||||||
"""
|
"""
|
||||||
self.current_xp += xp
|
self.current_xp += int(xp*self.xp_buff)
|
||||||
self.level_up()
|
self.level_up()
|
||||||
|
|
||||||
|
def remove_from_inventory(self, obj: Item) -> None:
|
||||||
|
"""
|
||||||
|
Remove the given item from the inventory, even if the item is equipped.
|
||||||
|
"""
|
||||||
|
if obj == self.equipped_main:
|
||||||
|
self.equipped_main = None
|
||||||
|
elif obj == self.equipped_armor:
|
||||||
|
self.equipped_armor = None
|
||||||
|
elif obj == self.equipped_secondary:
|
||||||
|
self.equipped_secondary = None
|
||||||
|
elif obj == self.equipped_helmet:
|
||||||
|
self.equipped_helmet = None
|
||||||
|
else:
|
||||||
|
return super().remove_from_inventory(obj)
|
||||||
|
|
||||||
# noinspection PyTypeChecker,PyUnresolvedReferences
|
# noinspection PyTypeChecker,PyUnresolvedReferences
|
||||||
def check_move(self, y: int, x: int, move_if_possible: bool = False) \
|
def check_move(self, y: int, x: int, move_if_possible: bool = False) \
|
||||||
-> bool:
|
-> bool:
|
||||||
|
@ -90,4 +129,12 @@ class Player(InventoryHolder, FightingEntity):
|
||||||
d = super().save_state()
|
d = super().save_state()
|
||||||
d["current_xp"] = self.current_xp
|
d["current_xp"] = self.current_xp
|
||||||
d["max_xp"] = self.max_xp
|
d["max_xp"] = self.max_xp
|
||||||
|
d["equipped_main"] = self.equipped_main.save_state()\
|
||||||
|
if self.equipped_main else None
|
||||||
|
d["equipped_armor"] = self.equipped_armor.save_state()\
|
||||||
|
if self.equipped_armor else None
|
||||||
|
d["equipped_secondary"] = self.equipped_secondary.save_state()\
|
||||||
|
if self.equipped_secondary else None
|
||||||
|
d["equipped_helmet"] = self.equipped_helmet.save_state()\
|
||||||
|
if self.equipped_helmet else None
|
||||||
return d
|
return d
|
||||||
|
|
|
@ -128,6 +128,9 @@ class Game:
|
||||||
self.map.tick(self.player)
|
self.map.tick(self.player)
|
||||||
elif key == KeyValues.INVENTORY:
|
elif key == KeyValues.INVENTORY:
|
||||||
self.state = GameMode.INVENTORY
|
self.state = GameMode.INVENTORY
|
||||||
|
self.display_actions(DisplayActions.UPDATE)
|
||||||
|
elif key == KeyValues.USE and self.player.equipped_main:
|
||||||
|
self.player.equipped_main.use()
|
||||||
elif key == KeyValues.SPACE:
|
elif key == KeyValues.SPACE:
|
||||||
self.state = GameMode.MAINMENU
|
self.state = GameMode.MAINMENU
|
||||||
elif key == KeyValues.CHAT:
|
elif key == KeyValues.CHAT:
|
||||||
|
|
|
@ -7,6 +7,8 @@ from random import choice, randint
|
||||||
from typing import List, Optional, Any, Dict, Tuple
|
from typing import List, Optional, Any, Dict, Tuple
|
||||||
from queue import PriorityQueue
|
from queue import PriorityQueue
|
||||||
from functools import reduce
|
from functools import reduce
|
||||||
|
from random import choice, randint, choices
|
||||||
|
from typing import List, Optional, Any
|
||||||
|
|
||||||
from .display.texturepack import TexturePack
|
from .display.texturepack import TexturePack
|
||||||
from .translations import gettext as _
|
from .translations import gettext as _
|
||||||
|
@ -152,7 +154,8 @@ class Map:
|
||||||
tile = self.tiles[y][x]
|
tile = self.tiles[y][x]
|
||||||
if tile.can_walk():
|
if tile.can_walk():
|
||||||
break
|
break
|
||||||
entity = choice(Entity.get_all_entity_classes())()
|
entity = choices(Entity.get_all_entity_classes(),\
|
||||||
|
weights = Entity.get_weights(), k=1)[0]()
|
||||||
entity.move(y, x)
|
entity.move(y, x)
|
||||||
self.add_entity(entity)
|
self.add_entity(entity)
|
||||||
|
|
||||||
|
@ -421,11 +424,20 @@ class Entity:
|
||||||
"""
|
"""
|
||||||
from squirrelbattle.entities.items import BodySnatchPotion, Bomb, Heart
|
from squirrelbattle.entities.items import BodySnatchPotion, Bomb, Heart
|
||||||
from squirrelbattle.entities.monsters import Tiger, Hedgehog, \
|
from squirrelbattle.entities.monsters import Tiger, Hedgehog, \
|
||||||
Rabbit, TeddyBear
|
Rabbit, TeddyBear, GiantSeaEagle
|
||||||
from squirrelbattle.entities.friendly import Merchant, Sunflower, \
|
from squirrelbattle.entities.friendly import Merchant, Sunflower, \
|
||||||
Trumpet
|
Trumpet
|
||||||
return [BodySnatchPotion, Bomb, Heart, Hedgehog, Rabbit, TeddyBear,
|
return [BodySnatchPotion, Bomb, Heart, Hedgehog, Rabbit, TeddyBear,
|
||||||
Sunflower, Tiger, Merchant, Trumpet]
|
Sunflower, Tiger, Merchant, GiantSeaEagle, Trumpet]
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def get_weights() -> list:
|
||||||
|
"""
|
||||||
|
Returns a weigth list associated to the above function, to
|
||||||
|
be used to spawn random entities with a certain probability.
|
||||||
|
"""
|
||||||
|
return [3, 5, 6, 5, 5, 5,
|
||||||
|
5, 4, 4, 1]
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def get_all_entity_classes_in_a_dict() -> dict:
|
def get_all_entity_classes_in_a_dict() -> dict:
|
||||||
|
@ -434,11 +446,11 @@ class Entity:
|
||||||
"""
|
"""
|
||||||
from squirrelbattle.entities.player import Player
|
from squirrelbattle.entities.player import Player
|
||||||
from squirrelbattle.entities.monsters import Tiger, Hedgehog, Rabbit, \
|
from squirrelbattle.entities.monsters import Tiger, Hedgehog, Rabbit, \
|
||||||
TeddyBear
|
TeddyBear, GiantSeaEagle
|
||||||
from squirrelbattle.entities.friendly import Merchant, Sunflower, \
|
from squirrelbattle.entities.friendly import Merchant, Sunflower, \
|
||||||
Trumpet
|
Trumpet
|
||||||
from squirrelbattle.entities.items import BodySnatchPotion, Bomb, \
|
from squirrelbattle.entities.items import BodySnatchPotion, Bomb, \
|
||||||
Heart, Sword
|
Heart, Sword, Shield, Chestplate, Helmet, RingCritical, RingXP
|
||||||
return {
|
return {
|
||||||
"Tiger": Tiger,
|
"Tiger": Tiger,
|
||||||
"Bomb": Bomb,
|
"Bomb": Bomb,
|
||||||
|
@ -452,6 +464,12 @@ class Entity:
|
||||||
"Sunflower": Sunflower,
|
"Sunflower": Sunflower,
|
||||||
"Sword": Sword,
|
"Sword": Sword,
|
||||||
"Trumpet": Trumpet,
|
"Trumpet": Trumpet,
|
||||||
|
"Eagle": GiantSeaEagle,
|
||||||
|
"Shield": Shield,
|
||||||
|
"Chestplate": Chestplate,
|
||||||
|
"Helmet": Helmet,
|
||||||
|
"RingCritical": RingCritical,
|
||||||
|
"RingXP": RingXP,
|
||||||
}
|
}
|
||||||
|
|
||||||
def save_state(self) -> dict:
|
def save_state(self) -> dict:
|
||||||
|
@ -478,11 +496,12 @@ class FightingEntity(Entity):
|
||||||
dexterity: int
|
dexterity: int
|
||||||
constitution: int
|
constitution: int
|
||||||
level: int
|
level: int
|
||||||
|
critical: int
|
||||||
|
|
||||||
def __init__(self, maxhealth: int = 0, health: Optional[int] = None,
|
def __init__(self, maxhealth: int = 0, health: Optional[int] = None,
|
||||||
strength: int = 0, intelligence: int = 0, charisma: int = 0,
|
strength: int = 0, intelligence: int = 0, charisma: int = 0,
|
||||||
dexterity: int = 0, constitution: int = 0, level: int = 0,
|
dexterity: int = 0, constitution: int = 0, level: int = 0,
|
||||||
*args, **kwargs) -> None:
|
critical: int = 0, *args, **kwargs) -> None:
|
||||||
super().__init__(*args, **kwargs)
|
super().__init__(*args, **kwargs)
|
||||||
self.maxhealth = maxhealth
|
self.maxhealth = maxhealth
|
||||||
self.health = maxhealth if health is None else health
|
self.health = maxhealth if health is None else health
|
||||||
|
@ -492,6 +511,7 @@ class FightingEntity(Entity):
|
||||||
self.dexterity = dexterity
|
self.dexterity = dexterity
|
||||||
self.constitution = constitution
|
self.constitution = constitution
|
||||||
self.level = level
|
self.level = level
|
||||||
|
self.critical = critical
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def dead(self) -> bool:
|
def dead(self) -> bool:
|
||||||
|
@ -505,21 +525,28 @@ class FightingEntity(Entity):
|
||||||
The entity deals damage to the opponent
|
The entity deals damage to the opponent
|
||||||
based on their respective stats.
|
based on their respective stats.
|
||||||
"""
|
"""
|
||||||
|
diceroll = randint(0, 100)
|
||||||
|
damage = self.strength
|
||||||
|
string = " "
|
||||||
|
if diceroll <= self.critical: # It is a critical hit
|
||||||
|
damage *= 4
|
||||||
|
string = _(" It's a critical hit! ")
|
||||||
return _("{name} hits {opponent}.")\
|
return _("{name} hits {opponent}.")\
|
||||||
.format(name=_(self.translated_name.capitalize()),
|
.format(name=_(self.translated_name.capitalize()),
|
||||||
opponent=_(opponent.translated_name)) + " " + \
|
opponent=_(opponent.translated_name)) + string + \
|
||||||
opponent.take_damage(self, self.strength)
|
opponent.take_damage(self, damage)
|
||||||
|
|
||||||
def take_damage(self, attacker: "Entity", amount: int) -> str:
|
def take_damage(self, attacker: "Entity", amount: int) -> str:
|
||||||
"""
|
"""
|
||||||
The entity takes damage from the attacker
|
The entity takes damage from the attacker
|
||||||
based on their respective stats.
|
based on their respective stats.
|
||||||
"""
|
"""
|
||||||
self.health -= amount
|
damage = max(0, amount - self.constitution)
|
||||||
|
self.health -= damage
|
||||||
if self.health <= 0:
|
if self.health <= 0:
|
||||||
self.die()
|
self.die()
|
||||||
return _("{name} takes {amount} damage.")\
|
return _("{name} takes {damage} damage.")\
|
||||||
.format(name=self.translated_name.capitalize(), amount=str(amount))\
|
.format(name=self.translated_name.capitalize(), damage=str(damage))\
|
||||||
+ (" " + _("{name} dies.")
|
+ (" " + _("{name} dies.")
|
||||||
.format(name=self.translated_name.capitalize())
|
.format(name=self.translated_name.capitalize())
|
||||||
if self.health <= 0 else "")
|
if self.health <= 0 else "")
|
||||||
|
@ -576,10 +603,10 @@ class InventoryHolder(Entity):
|
||||||
"""
|
"""
|
||||||
for i in range(len(inventory)):
|
for i in range(len(inventory)):
|
||||||
if isinstance(inventory[i], dict):
|
if isinstance(inventory[i], dict):
|
||||||
inventory[i] = self.dict_to_inventory(inventory[i])
|
inventory[i] = self.dict_to_item(inventory[i])
|
||||||
return inventory
|
return inventory
|
||||||
|
|
||||||
def dict_to_inventory(self, item_dict: dict) -> Entity:
|
def dict_to_item(self, item_dict: dict) -> Entity:
|
||||||
"""
|
"""
|
||||||
Translates a dictionnary that contains the state of an item
|
Translates a dictionnary that contains the state of an item
|
||||||
into an item object.
|
into an item object.
|
||||||
|
@ -602,13 +629,15 @@ class InventoryHolder(Entity):
|
||||||
"""
|
"""
|
||||||
Adds an object to the inventory.
|
Adds an object to the inventory.
|
||||||
"""
|
"""
|
||||||
self.inventory.append(obj)
|
if obj not in self.inventory:
|
||||||
|
self.inventory.append(obj)
|
||||||
|
|
||||||
def remove_from_inventory(self, obj: Any) -> None:
|
def remove_from_inventory(self, obj: Any) -> None:
|
||||||
"""
|
"""
|
||||||
Removes an object from the inventory.
|
Removes an object from the inventory.
|
||||||
"""
|
"""
|
||||||
self.inventory.remove(obj)
|
if obj in self.inventory:
|
||||||
|
self.inventory.remove(obj)
|
||||||
|
|
||||||
def change_hazel_balance(self, hz: int) -> None:
|
def change_hazel_balance(self, hz: int) -> None:
|
||||||
"""
|
"""
|
||||||
|
|
|
@ -19,6 +19,7 @@ class TestEntities(unittest.TestCase):
|
||||||
"""
|
"""
|
||||||
self.map = Map.load(ResourceManager.get_asset_path("example_map.txt"))
|
self.map = Map.load(ResourceManager.get_asset_path("example_map.txt"))
|
||||||
self.player = Player()
|
self.player = Player()
|
||||||
|
self.player.constitution = 0
|
||||||
self.map.add_entity(self.player)
|
self.map.add_entity(self.player)
|
||||||
self.player.move(self.map.start_y, self.map.start_x)
|
self.player.move(self.map.start_y, self.map.start_x)
|
||||||
|
|
||||||
|
@ -55,6 +56,7 @@ class TestEntities(unittest.TestCase):
|
||||||
self.assertTrue(entity.dead)
|
self.assertTrue(entity.dead)
|
||||||
|
|
||||||
entity = Rabbit()
|
entity = Rabbit()
|
||||||
|
entity.critical = 0
|
||||||
self.map.add_entity(entity)
|
self.map.add_entity(entity)
|
||||||
entity.move(15, 44)
|
entity.move(15, 44)
|
||||||
# Move randomly
|
# Move randomly
|
||||||
|
|
Loading…
Reference in New Issue