Added a Bow, related to #64

This commit is contained in:
eichhornchen 2021-01-08 18:06:26 +01:00
parent bde33e9232
commit f6210a6356
7 changed files with 105 additions and 6 deletions

View File

@ -21,6 +21,7 @@ class TexturePack:
BODY_SNATCH_POTION: str BODY_SNATCH_POTION: str
BOMB: str BOMB: str
BOW: str
CHESTPLATE: str CHESTPLATE: str
EAGLE: str EAGLE: str
EMPTY: str EMPTY: str
@ -34,6 +35,7 @@ class TexturePack:
RABBIT: str RABBIT: str
RING_OF_CRITICAL_DAMAGE: str RING_OF_CRITICAL_DAMAGE: str
RING_OF_MORE_EXPERIENCE: str RING_OF_MORE_EXPERIENCE: str
RULER: str
SCROLL_OF_DAMAGE: str SCROLL_OF_DAMAGE: str
SCROLL_OF_WEAKENING: str SCROLL_OF_WEAKENING: str
SHIELD: str SHIELD: str
@ -75,6 +77,7 @@ TexturePack.ASCII_PACK = TexturePack(
BODY_SNATCH_POTION='S', BODY_SNATCH_POTION='S',
BOMB='ç', BOMB='ç',
BOW=')',
CHESTPLATE='(', CHESTPLATE='(',
EAGLE='µ', EAGLE='µ',
EMPTY=' ', EMPTY=' ',
@ -90,6 +93,7 @@ TexturePack.ASCII_PACK = TexturePack(
RABBIT='Y', RABBIT='Y',
RING_OF_CRITICAL_DAMAGE='o', RING_OF_CRITICAL_DAMAGE='o',
RING_OF_MORE_EXPERIENCE='o', RING_OF_MORE_EXPERIENCE='o',
RULER='\\',
SHIELD='D', SHIELD='D',
SUNFLOWER='I', SUNFLOWER='I',
SWORD='\u2020', SWORD='\u2020',
@ -112,6 +116,7 @@ TexturePack.SQUIRREL_PACK = TexturePack(
BODY_SNATCH_POTION='🔀', BODY_SNATCH_POTION='🔀',
BOMB='💣', BOMB='💣',
BOW='🏹',
CHESTPLATE='🦺', CHESTPLATE='🦺',
EAGLE='🦅', EAGLE='🦅',
EMPTY=' ', EMPTY=' ',
@ -128,6 +133,7 @@ TexturePack.SQUIRREL_PACK = TexturePack(
RABBIT='🐇', RABBIT='🐇',
RING_OF_CRITICAL_DAMAGE='💍', RING_OF_CRITICAL_DAMAGE='💍',
RING_OF_MORE_EXPERIENCE='💍', RING_OF_MORE_EXPERIENCE='💍',
RULER='📏',
SHIELD='🛡️ ', SHIELD='🛡️ ',
SUNFLOWER='🌻', SUNFLOWER='🌻',
SWORD='🗡️ ', SWORD='🗡️ ',

View File

@ -40,6 +40,11 @@ class Item(Entity):
Indicates what should be done when the item is used. Indicates what should be done when the item is used.
""" """
def throw(self, direction: int) -> None:
"""
Indicates what should be done when the item is thrown.
"""
def equip(self) -> None: def equip(self) -> None:
""" """
Indicates what should be done when the item is equipped. Indicates what should be done when the item is equipped.
@ -81,7 +86,7 @@ class Item(Entity):
""" """
return [BodySnatchPotion, Bomb, Heart, Shield, Sword,\ return [BodySnatchPotion, Bomb, Heart, Shield, Sword,\
Chestplate, Helmet, RingCritical, RingXP, \ Chestplate, Helmet, RingCritical, RingXP, \
ScrollofDamage, ScrollofWeakening] ScrollofDamage, ScrollofWeakening, Ruler, Bow]
def be_sold(self, buyer: InventoryHolder, seller: InventoryHolder) -> bool: def be_sold(self, buyer: InventoryHolder, seller: InventoryHolder) -> bool:
""" """
@ -251,6 +256,13 @@ class Sword(Weapon):
*args, **kwargs): *args, **kwargs):
super().__init__(name=name, price=price, *args, **kwargs) super().__init__(name=name, price=price, *args, **kwargs)
class Ruler(Weapon):
"""
A basic weapon
"""
def __init__(self, name: str = "ruler", price: int = 2,
damage: int = 1, *args, **kwargs):
super().__init__(name=name, price=price, damage=damage, *args, **kwargs)
class Armor(Item): class Armor(Item):
""" """
@ -428,7 +440,6 @@ class ScrollofDamage(Item):
""" """
A scroll that, when used, deals damage to all entities in a certain radius. A scroll that, when used, deals damage to all entities in a certain radius.
""" """
def __init__(self, name: str = "scroll_of_damage", price: int = 18, def __init__(self, name: str = "scroll_of_damage", price: int = 18,
*args, **kwargs): *args, **kwargs):
super().__init__(name=name, price=price, *args, **kwargs) super().__init__(name=name, price=price, *args, **kwargs)
@ -449,7 +460,6 @@ class ScrollofWeakening(Item):
""" """
A scroll that, when used, reduces the damage of the ennemies for 3 turn. A scroll that, when used, reduces the damage of the ennemies for 3 turn.
""" """
def __init__(self, name: str = "scroll_of_weakening", price: int = 13, def __init__(self, name: str = "scroll_of_weakening", price: int = 13,
*args, **kwargs): *args, **kwargs):
super().__init__(name=name, price=price, *args, **kwargs) super().__init__(name=name, price=price, *args, **kwargs)
@ -459,10 +469,52 @@ class ScrollofWeakening(Item):
Find all entities and reduce their damage. Find all entities and reduce their damage.
""" """
for entity in self.held_by.map.entities: for entity in self.held_by.map.entities:
if entity.is_fighting_entity(): #and not entity == self.held_by: if entity.is_fighting_entity() and not entity == self.held_by:
entity.strength = entity.strength - max(1, self.held_by.intelligence//2) entity.strength = entity.strength - max(1, self.held_by.intelligence//2)
entity.effects.append(["strength", \ entity.effects.append(["strength", \
-max(1, self.held_by.intelligence//2), 3]) -max(1, self.held_by.intelligence//2), 3])
self.held_by.map.logs.add_message(\ self.held_by.map.logs.add_message(\
_(f"The ennemies have -{max(1, self.held_by.intelligence//2)} strength for 3 turns")) _(f"The ennemies have -{max(1, self.held_by.intelligence//2)} strength for 3 turns"))
self.held_by.inventory.remove(self) self.held_by.inventory.remove(self)
class Bow(Item):
"""
A type of throwable weapon that deals damage based on the player's dexterity.
"""
def __init__(self, name: str = "bow", price: int = 22, damage = 4,
rang = 3, *args, **kwargs):
super().__init__(name=name, price=price, *args, **kwargs)
self.damage = damage
self.range = rang
def throw(self, direction: int) -> str:
to_kill = None
for entity in self.held_by.map.entities:
if entity.is_fighting_entity():
if direction == 0 and self.held_by.x == entity.x \
and self.held_by.y-entity.y>0 and \
self.held_by.y-entity.y<=self.range:
to_kill = entity
elif direction == 2 and self.held_by.x == entity.x \
and entity.y-self.held_by.y>0 and \
entity.y-self.held_by.y<=self.range:
to_kill = entity
elif direction == 1 and self.held_by.y == entity.y \
and entity.x-self.held_by.x>0 and \
entity.x-self.held_by.x<=self.range:
to_kill = entity
elif direction == 3 and self.held_by.y == entity.y \
and self.held_by.x-entity.x>0 and \
self.held_by.x-entity.x<=self.range:
to_kill = entity
if to_kill:
self.held_by.map.logs.add_message(_("{name} is shot by an arrow.")\
.format(name=to_kill.translated_name.capitalize())+ " " \
+ to_kill.take_damage(self.held_by, self.damage + self.held_by.dexterity))
def equip(self) -> None:
"""
Equip the bow.
"""
self.held_by.remove_from_inventory(self)
self.held_by.equipped_main = self

View File

@ -4,7 +4,7 @@
from random import randint from random import randint
from typing import Dict, Optional, Tuple from typing import Dict, Optional, Tuple
from .items import Item from .items import Item, Bow
from ..interfaces import FightingEntity, InventoryHolder from ..interfaces import FightingEntity, InventoryHolder
@ -38,6 +38,9 @@ class Player(InventoryHolder, FightingEntity):
self.max_xp = max_xp self.max_xp = max_xp
self.xp_buff = xp_buff self.xp_buff = xp_buff
self.inventory = self.translate_inventory(inventory or []) self.inventory = self.translate_inventory(inventory or [])
b = Bow()
b.held_by=self
self.inventory.append(b)
self.paths = dict() self.paths = dict()
self.hazel = hazel self.hazel = hazel
self.equipped_main = self.dict_to_item(equipped_main) \ self.equipped_main = self.dict_to_item(equipped_main) \

View File

@ -48,6 +48,7 @@ class KeyValues(Enum):
CHAT = auto() CHAT = auto()
WAIT = auto() WAIT = auto()
LADDER = auto() LADDER = auto()
LAUNCH = auto()
@staticmethod @staticmethod
def translate_key(key: str, settings: Settings) -> Optional["KeyValues"]: def translate_key(key: str, settings: Settings) -> Optional["KeyValues"]:
@ -84,4 +85,6 @@ class KeyValues(Enum):
return KeyValues.WAIT return KeyValues.WAIT
elif key == settings.KEY_LADDER: elif key == settings.KEY_LADDER:
return KeyValues.LADDER return KeyValues.LADDER
elif key == settings.KEY_LAUNCH:
return KeyValues.LAUNCH
return None return None

View File

@ -35,6 +35,7 @@ class Game:
""" """
self.state = GameMode.MAINMENU self.state = GameMode.MAINMENU
self.waiting_for_friendly_key = False self.waiting_for_friendly_key = False
self.waiting_for_launch_key = False
self.is_in_store_menu = True self.is_in_store_menu = True
self.settings = Settings() self.settings = Settings()
self.settings.load_settings() self.settings.load_settings()
@ -117,6 +118,9 @@ class Game:
if self.waiting_for_friendly_key: if self.waiting_for_friendly_key:
# The player requested to talk with a friendly entity # The player requested to talk with a friendly entity
self.handle_friendly_entity_chat(key) self.handle_friendly_entity_chat(key)
elif self.waiting_for_launch_key:
# The player requested to launch
self.handle_launch(key)
else: else:
self.handle_key_pressed_play(key) self.handle_key_pressed_play(key)
elif self.state == GameMode.INVENTORY: elif self.state == GameMode.INVENTORY:
@ -155,6 +159,9 @@ class Game:
self.player.equipped_main.use() self.player.equipped_main.use()
if self.player.equipped_secondary: if self.player.equipped_secondary:
self.player.equipped_secondary.use() self.player.equipped_secondary.use()
elif key == KeyValues.LAUNCH:
# Wait for the direction to launch in
self.waiting_for_launch_key = True
elif key == KeyValues.SPACE: elif key == KeyValues.SPACE:
self.state = GameMode.MAINMENU self.state = GameMode.MAINMENU
elif key == KeyValues.CHAT: elif key == KeyValues.CHAT:
@ -247,6 +254,31 @@ class Game:
self.store_menu.update_merchant(entity) self.store_menu.update_merchant(entity)
self.display_actions(DisplayActions.UPDATE) self.display_actions(DisplayActions.UPDATE)
def handle_launch(self, key: KeyValues) -> None:
"""
If the player tries to throw something in a direction, the game looks
for entities in that direction and within the range of the player's
weapon and adds damage
"""
if not self.waiting_for_launch_key:
return
self.waiting_for_launch_key = False
if key == KeyValues.UP:
direction = 0
elif key == KeyValues.DOWN:
direction = 2
elif key == KeyValues.LEFT:
direction = 3
elif key == KeyValues.RIGHT:
direction = 1
else:
return
if self.player.equipped_main:
self.player.equipped_main.throw(direction)
def handle_key_pressed_inventory(self, key: KeyValues) -> None: def handle_key_pressed_inventory(self, key: KeyValues) -> None:
""" """
In the inventory menu, we can interact with items or close the menu. In the inventory menu, we can interact with items or close the menu.

View File

@ -630,7 +630,7 @@ class Entity:
Trumpet Trumpet
from squirrelbattle.entities.items import BodySnatchPotion, Bomb, \ from squirrelbattle.entities.items import BodySnatchPotion, Bomb, \
Heart, Sword, Shield, Chestplate, Helmet, RingCritical, RingXP, \ Heart, Sword, Shield, Chestplate, Helmet, RingCritical, RingXP, \
ScrollofDamage, ScrollofWeakening ScrollofDamage, ScrollofWeakening, Ruler, Bow
return { return {
"Tiger": Tiger, "Tiger": Tiger,
"Bomb": Bomb, "Bomb": Bomb,
@ -650,8 +650,10 @@ class Entity:
"Helmet": Helmet, "Helmet": Helmet,
"RingCritical": RingCritical, "RingCritical": RingCritical,
"RingXP": RingXP, "RingXP": RingXP,
"Ruler": Ruler,
"ScrollofDamage": ScrollofDamage, "ScrollofDamage": ScrollofDamage,
"ScrollofWeakening": ScrollofWeakening, "ScrollofWeakening": ScrollofWeakening,
"Bow": Bow,
} }
def save_state(self) -> dict: def save_state(self) -> dict:

View File

@ -35,6 +35,7 @@ class Settings:
self.KEY_CHAT = ['t', 'Key used to talk to a friendly entity'] self.KEY_CHAT = ['t', 'Key used to talk to a friendly entity']
self.KEY_WAIT = ['w', 'Key used to wait'] self.KEY_WAIT = ['w', 'Key used to wait']
self.KEY_LADDER = ['<', 'Key used to use ladders'] self.KEY_LADDER = ['<', 'Key used to use ladders']
self.KEY_LAUNCH = ['l', 'Key used to use a bow']
self.TEXTURE_PACK = ['ascii', 'Texture pack'] self.TEXTURE_PACK = ['ascii', 'Texture pack']
self.LOCALE = [locale.getlocale()[0][:2], 'Language'] self.LOCALE = [locale.getlocale()[0][:2], 'Language']