Added chests, they are immortal and contain objects the player can take for free.
This commit is contained in:
parent
175706b1e4
commit
bdbf214d8d
@ -10,7 +10,8 @@ from squirrelbattle.display.mapdisplay import MapDisplay
|
||||
from squirrelbattle.display.messagedisplay import MessageDisplay
|
||||
from squirrelbattle.display.statsdisplay import StatsDisplay
|
||||
from squirrelbattle.display.menudisplay import MainMenuDisplay, \
|
||||
PlayerInventoryDisplay, StoreInventoryDisplay, SettingsMenuDisplay
|
||||
PlayerInventoryDisplay, StoreInventoryDisplay, SettingsMenuDisplay, \
|
||||
ChestInventoryDisplay
|
||||
from squirrelbattle.display.logsdisplay import LogsDisplay
|
||||
from squirrelbattle.display.texturepack import TexturePack
|
||||
from typing import Any, List
|
||||
@ -29,6 +30,7 @@ class DisplayManager:
|
||||
self.logsdisplay = LogsDisplay(screen, pack)
|
||||
self.playerinventorydisplay = PlayerInventoryDisplay(screen, pack)
|
||||
self.storeinventorydisplay = StoreInventoryDisplay(screen, pack)
|
||||
self.chestinventorydisplay = ChestInventoryDisplay(screen, pack)
|
||||
self.mainmenudisplay = MainMenuDisplay(self.game.main_menu,
|
||||
screen, pack)
|
||||
self.settingsmenudisplay = SettingsMenuDisplay(screen, pack)
|
||||
@ -40,7 +42,8 @@ class DisplayManager:
|
||||
self.mainmenudisplay, self.settingsmenudisplay,
|
||||
self.logsdisplay, self.messagedisplay,
|
||||
self.playerinventorydisplay,
|
||||
self.storeinventorydisplay, self.creditsdisplay]
|
||||
self.storeinventorydisplay, self.creditsdisplay,
|
||||
self.chestinventorydisplay]
|
||||
self.update_game_components()
|
||||
|
||||
def handle_display_action(self, action: DisplayActions, *params) -> None:
|
||||
@ -87,7 +90,8 @@ class DisplayManager:
|
||||
|
||||
if self.game.state == GameMode.PLAY \
|
||||
or self.game.state == GameMode.INVENTORY \
|
||||
or self.game.state == GameMode.STORE:
|
||||
or self.game.state == GameMode.STORE\
|
||||
or self.game.state == GameMode.CHEST:
|
||||
# The map pad has already the good size
|
||||
self.mapdisplay.refresh(0, 0, self.rows * 4 // 5,
|
||||
self.mapdisplay.pack.tile_width
|
||||
@ -124,6 +128,19 @@ class DisplayManager:
|
||||
pack.tile_width * (2 * self.cols // (5 * pack.tile_width)))
|
||||
displays.append(self.storeinventorydisplay)
|
||||
displays.append(self.playerinventorydisplay)
|
||||
elif self.game.state == GameMode.CHEST:
|
||||
self.chestinventorydisplay.refresh(
|
||||
self.rows // 10,
|
||||
pack.tile_width * (self.cols // (2 * pack.tile_width)),
|
||||
8 * self.rows // 10,
|
||||
pack.tile_width * (2 * self.cols // (5 * pack.tile_width)))
|
||||
self.playerinventorydisplay.refresh(
|
||||
self.rows // 10,
|
||||
pack.tile_width * (self.cols // (10 * pack.tile_width)),
|
||||
8 * self.rows // 10,
|
||||
pack.tile_width * (2 * self.cols // (5 * pack.tile_width)))
|
||||
displays.append(self.chestinventorydisplay)
|
||||
displays.append(self.playerinventorydisplay)
|
||||
elif self.game.state == GameMode.MAINMENU:
|
||||
self.mainmenudisplay.refresh(0, 0, self.rows, self.cols)
|
||||
displays.append(self.mainmenudisplay)
|
||||
|
@ -5,7 +5,8 @@ import curses
|
||||
from random import randint
|
||||
from typing import List
|
||||
|
||||
from squirrelbattle.menus import Menu, MainMenu, SettingsMenu, StoreMenu
|
||||
from squirrelbattle.menus import Menu, MainMenu, SettingsMenu, StoreMenu,\
|
||||
ChestMenu
|
||||
from .display import Box, Display
|
||||
from ..entities.player import Player
|
||||
from ..enums import KeyValues, GameMode
|
||||
@ -156,13 +157,16 @@ class PlayerInventoryDisplay(MenuDisplay):
|
||||
player: Player = None
|
||||
selected: bool = True
|
||||
store_mode: bool = False
|
||||
chest_mode: bool = False
|
||||
|
||||
def update(self, game: Game) -> None:
|
||||
self.player = game.player
|
||||
self.update_menu(game.inventory_menu)
|
||||
self.store_mode = game.state == GameMode.STORE
|
||||
self.chest_mode = game.state == GameMode.CHEST
|
||||
self.selected = game.state == GameMode.INVENTORY \
|
||||
or (self.store_mode and not game.is_in_store_menu)
|
||||
or (self.store_mode and not game.is_in_store_menu)\
|
||||
or (self.chest_mode and not game.is_in_chest_menu)
|
||||
|
||||
def update_pad(self) -> None:
|
||||
self.menubox.update_title(_("INVENTORY"))
|
||||
@ -239,3 +243,39 @@ class StoreInventoryDisplay(MenuDisplay):
|
||||
self.menu.position = max(0, min(len(self.menu.values) - 1, y - 2))
|
||||
game.is_in_store_menu = True
|
||||
game.handle_key_pressed(KeyValues.ENTER)
|
||||
|
||||
class ChestInventoryDisplay(MenuDisplay):
|
||||
"""
|
||||
A class to handle the display of a merchant's inventory.
|
||||
"""
|
||||
menu: ChestMenu
|
||||
selected: bool = False
|
||||
|
||||
def update(self, game: Game) -> None:
|
||||
self.update_menu(game.chest_menu)
|
||||
self.selected = game.is_in_chest_menu
|
||||
|
||||
def update_pad(self) -> None:
|
||||
self.menubox.update_title(_("CHEST"))
|
||||
for i, item in enumerate(self.menu.values):
|
||||
rep = self.pack[item.name.upper()]
|
||||
selection = f"[{rep}]" if i == self.menu.position \
|
||||
and self.selected else f" {rep} "
|
||||
self.addstr(self.pad, i + 1, 0, selection
|
||||
+ " " + item.translated_name.capitalize())
|
||||
|
||||
@property
|
||||
def truewidth(self) -> int:
|
||||
return max(1, self.height if hasattr(self, "height") else 10)
|
||||
|
||||
@property
|
||||
def trueheight(self) -> int:
|
||||
return 2 + super().trueheight
|
||||
|
||||
def handle_click(self, y: int, x: int, game: Game) -> None:
|
||||
"""
|
||||
We can select a menu item with the mouse.
|
||||
"""
|
||||
self.menu.position = max(0, min(len(self.menu.values) - 1, y - 2))
|
||||
game.is_in_chest_menu = True
|
||||
game.handle_key_pressed(KeyValues.ENTER)
|
||||
|
@ -22,6 +22,7 @@ class TexturePack:
|
||||
BODY_SNATCH_POTION: str
|
||||
BOMB: str
|
||||
BOW: str
|
||||
CHEST: str
|
||||
CHESTPLATE: str
|
||||
EAGLE: str
|
||||
EMPTY: str
|
||||
@ -79,6 +80,7 @@ TexturePack.ASCII_PACK = TexturePack(
|
||||
BODY_SNATCH_POTION='S',
|
||||
BOMB='ç',
|
||||
BOW=')',
|
||||
CHEST='□',
|
||||
CHESTPLATE='(',
|
||||
EAGLE='µ',
|
||||
EMPTY=' ',
|
||||
@ -119,6 +121,7 @@ TexturePack.SQUIRREL_PACK = TexturePack(
|
||||
BODY_SNATCH_POTION='🔀',
|
||||
BOMB='💣',
|
||||
BOW='🏹',
|
||||
CHEST='🧰',
|
||||
CHESTPLATE='🦺',
|
||||
EAGLE='🦅',
|
||||
EMPTY=' ',
|
||||
|
@ -38,6 +38,39 @@ class Merchant(InventoryHolder, FriendlyEntity):
|
||||
"""
|
||||
self.hazel += hz
|
||||
|
||||
class Chest(InventoryHolder, FriendlyEntity):
|
||||
"""
|
||||
A class of chest inanimate entities which contain objects.
|
||||
"""
|
||||
def __init__(self, name: str = "chest", inventory: list = None,
|
||||
hazel: int = 0, *args, **kwargs):
|
||||
super().__init__(name=name, *args, **kwargs)
|
||||
self.hazel = hazel
|
||||
self.inventory = self.translate_inventory(inventory or [])
|
||||
if not self.inventory:
|
||||
for i in range(3):
|
||||
self.inventory.append(choice(Item.get_all_items())())
|
||||
|
||||
def talk_to(self, player: Player) -> str:
|
||||
"""
|
||||
This function is used to open the chest's inventory in a menu,
|
||||
and allows the player to take objects.
|
||||
"""
|
||||
return _("You have opened the chest")
|
||||
|
||||
def take_damage(self, attacker: "Entity", amount: int) -> str:
|
||||
"""
|
||||
A chest is not living, it can not take damage
|
||||
"""
|
||||
return _("It's not really effective")
|
||||
|
||||
@property
|
||||
def dead(self) -> bool:
|
||||
"""
|
||||
Chest can not die
|
||||
"""
|
||||
return False
|
||||
|
||||
|
||||
class Sunflower(FriendlyEntity):
|
||||
"""
|
||||
|
@ -88,13 +88,18 @@ class Item(Entity):
|
||||
Chestplate, Helmet, RingCritical, RingXP,
|
||||
ScrollofDamage, ScrollofWeakening, Ruler, Bow, FireBallStaff]
|
||||
|
||||
def be_sold(self, buyer: InventoryHolder, seller: InventoryHolder) -> bool:
|
||||
def be_sold(self, buyer: InventoryHolder, seller: InventoryHolder,\
|
||||
for_free: bool = False) -> bool:
|
||||
"""
|
||||
Does all necessary actions when an object is to be sold.
|
||||
Is overwritten by some classes that cannot exist in the player's
|
||||
inventory.
|
||||
"""
|
||||
if buyer.hazel >= self.price:
|
||||
if for_free:
|
||||
self.hold(buyer)
|
||||
seller.remove_from_inventory(self)
|
||||
return True
|
||||
elif buyer.hazel >= self.price:
|
||||
self.hold(buyer)
|
||||
seller.remove_from_inventory(self)
|
||||
buyer.change_hazel_balance(-self.price)
|
||||
|
@ -28,6 +28,7 @@ class GameMode(Enum):
|
||||
SETTINGS = auto()
|
||||
INVENTORY = auto()
|
||||
STORE = auto()
|
||||
CHEST = auto()
|
||||
CREDITS = auto()
|
||||
|
||||
|
||||
|
@ -37,6 +37,7 @@ class Game:
|
||||
self.waiting_for_friendly_key = False
|
||||
self.waiting_for_launch_key = False
|
||||
self.is_in_store_menu = True
|
||||
self.is_in_chest_menu = True
|
||||
self.settings = Settings()
|
||||
self.settings.load_settings()
|
||||
self.settings.write_settings()
|
||||
@ -46,6 +47,7 @@ class Game:
|
||||
self.settings_menu.update_values(self.settings)
|
||||
self.inventory_menu = menus.InventoryMenu()
|
||||
self.store_menu = menus.StoreMenu()
|
||||
self.chest_menu = menus.ChestMenu()
|
||||
self.logs = Logs()
|
||||
self.message = None
|
||||
|
||||
@ -131,6 +133,8 @@ class Game:
|
||||
self.settings_menu.handle_key_pressed(key, raw_key, self)
|
||||
elif self.state == GameMode.STORE:
|
||||
self.handle_key_pressed_store(key)
|
||||
elif self.state == GameMode.CHEST:
|
||||
self.handle_key_pressed_chest(key)
|
||||
elif self.state == GameMode.CREDITS:
|
||||
self.state = GameMode.MAINMENU
|
||||
self.display_actions(DisplayActions.REFRESH)
|
||||
@ -253,6 +257,11 @@ class Game:
|
||||
self.is_in_store_menu = True
|
||||
self.store_menu.update_merchant(entity)
|
||||
self.display_actions(DisplayActions.UPDATE)
|
||||
elif entity.is_chest():
|
||||
self.state = GameMode.CHEST
|
||||
self.is_in_chest_menu = True
|
||||
self.chest_menu.update_chest(entity)
|
||||
self.display_actions(DisplayActions.UPDATE)
|
||||
|
||||
def handle_launch(self, key: KeyValues) -> None:
|
||||
"""
|
||||
@ -332,6 +341,36 @@ class Game:
|
||||
self.display_actions(DisplayActions.UPDATE)
|
||||
# Ensure that the cursor has a good position
|
||||
menu.position = min(menu.position, len(menu.values) - 1)
|
||||
|
||||
def handle_key_pressed_chest(self, key: KeyValues) -> None:
|
||||
"""
|
||||
In a chest menu, we can take or put items or close the menu.
|
||||
"""
|
||||
menu = self.chest_menu if self.is_in_chest_menu else self.inventory_menu
|
||||
|
||||
if key == KeyValues.SPACE or key == KeyValues.INVENTORY:
|
||||
self.state = GameMode.PLAY
|
||||
elif key == KeyValues.UP:
|
||||
menu.go_up()
|
||||
elif key == KeyValues.DOWN:
|
||||
menu.go_down()
|
||||
elif key == KeyValues.LEFT:
|
||||
self.is_in_chest_menu = False
|
||||
self.display_actions(DisplayActions.UPDATE)
|
||||
elif key == KeyValues.RIGHT:
|
||||
self.is_in_chest_menu = True
|
||||
self.display_actions(DisplayActions.UPDATE)
|
||||
if menu.values and not self.player.dead:
|
||||
if key == KeyValues.ENTER:
|
||||
item = menu.validate()
|
||||
owner = self.chest_menu.chest if self.is_in_chest_menu \
|
||||
else self.player
|
||||
buyer = self.player if self.is_in_chest_menu \
|
||||
else self.chest_menu.chest
|
||||
flag = item.be_sold(buyer, owner, for_free = True)
|
||||
self.display_actions(DisplayActions.UPDATE)
|
||||
# Ensure that the cursor has a good position
|
||||
menu.position = min(menu.position, len(menu.values) - 1)
|
||||
|
||||
def handle_key_pressed_main_menu(self, key: KeyValues) -> None:
|
||||
"""
|
||||
|
@ -589,6 +589,13 @@ class Entity:
|
||||
from squirrelbattle.entities.friendly import Merchant
|
||||
return isinstance(self, Merchant)
|
||||
|
||||
def is_chest(self) -> bool:
|
||||
"""
|
||||
Is this entity a chest?
|
||||
"""
|
||||
from squirrelbattle.entities.friendly import Chest
|
||||
return isinstance(self, Chest)
|
||||
|
||||
@property
|
||||
def translated_name(self) -> str:
|
||||
"""
|
||||
@ -605,9 +612,9 @@ class Entity:
|
||||
from squirrelbattle.entities.monsters import Tiger, Hedgehog, \
|
||||
Rabbit, TeddyBear, GiantSeaEagle
|
||||
from squirrelbattle.entities.friendly import Merchant, Sunflower, \
|
||||
Trumpet
|
||||
Trumpet, Chest
|
||||
return [BodySnatchPotion, Bomb, Heart, Hedgehog, Rabbit, TeddyBear,
|
||||
Sunflower, Tiger, Merchant, GiantSeaEagle, Trumpet]
|
||||
Sunflower, Tiger, Merchant, GiantSeaEagle, Trumpet, Chest]
|
||||
|
||||
@staticmethod
|
||||
def get_weights() -> list:
|
||||
@ -615,8 +622,7 @@ class Entity:
|
||||
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, 2]
|
||||
return [3, 5, 6, 5, 5, 5, 5, 4, 3, 1, 2, 4]
|
||||
|
||||
@staticmethod
|
||||
def get_all_entity_classes_in_a_dict() -> dict:
|
||||
@ -627,7 +633,7 @@ class Entity:
|
||||
from squirrelbattle.entities.monsters import Tiger, Hedgehog, Rabbit, \
|
||||
TeddyBear, GiantSeaEagle
|
||||
from squirrelbattle.entities.friendly import Merchant, Sunflower, \
|
||||
Trumpet
|
||||
Trumpet, Chest
|
||||
from squirrelbattle.entities.items import BodySnatchPotion, Bomb, \
|
||||
Heart, Sword, Shield, Chestplate, Helmet, RingCritical, RingXP, \
|
||||
ScrollofDamage, ScrollofWeakening, Ruler, Bow, FireBallStaff
|
||||
@ -655,6 +661,7 @@ class Entity:
|
||||
"ScrollofWeakening": ScrollofWeakening,
|
||||
"Bow": Bow,
|
||||
"FireBallStaff": FireBallStaff,
|
||||
"Chest": Chest,
|
||||
}
|
||||
|
||||
def save_state(self) -> dict:
|
||||
|
@ -6,7 +6,7 @@ from typing import Any, Optional
|
||||
|
||||
from .display.texturepack import TexturePack
|
||||
from .entities.player import Player
|
||||
from .entities.friendly import Merchant
|
||||
from .entities.friendly import Merchant, Chest
|
||||
from .enums import GameMode, KeyValues, DisplayActions
|
||||
from .settings import Settings
|
||||
from .translations import gettext as _, Translator
|
||||
@ -158,3 +158,23 @@ class StoreMenu(Menu):
|
||||
Returns the values of the menu.
|
||||
"""
|
||||
return self.merchant.inventory if self.merchant else []
|
||||
|
||||
|
||||
class ChestMenu(Menu):
|
||||
"""
|
||||
A special instance of a menu : the menu for the inventory of a chest.
|
||||
"""
|
||||
chest: Chest = None
|
||||
|
||||
def update_chest(self, chest: Chest) -> None:
|
||||
"""
|
||||
Updates the player.
|
||||
"""
|
||||
self.chest = chest
|
||||
|
||||
@property
|
||||
def values(self) -> list:
|
||||
"""
|
||||
Returns the values of the menu.
|
||||
"""
|
||||
return self.chest.inventory if self.chest else []
|
||||
|
Loading…
Reference in New Issue
Block a user