diff --git a/README.md b/README.md index 160fa72..453510b 100644 --- a/README.md +++ b/README.md @@ -20,6 +20,7 @@ Here's a few potential options, which will absolutely change over time: * Stargates/Sliders * Isekai Protag Syndrome * Gunslingers (Wild West) +* Zombies/Undead Contagion Plague that infects other dimensions ## Links And Resources diff --git a/dev-notes.md b/dev-notes.md index 39c1258..9cdafdb 100644 --- a/dev-notes.md +++ b/dev-notes.md @@ -9,12 +9,13 @@ A lock in one dimension needs a key (password) in another? It could be interesting, not necssarily a good or fun idea, but if you had another "point" or currency. Where if you spend the first one you get some kind of "cursed knowledge" point and that affects the run somehow? So the more you use your forbidden knowledge the more weird things get? If you use IRL time and date as a mechanic, go big or go home. Maybe the horror dimension is only accessible during full/new moons? + Should the selected dimension be known at the start of a run? ## Healing While not necessarily "realistic" some are more fun or interesting. - healing potion + potion of healing / greater healing / full healing nano cells (nanophage) medical bag " cocane" holy crystal @@ -33,43 +34,37 @@ As some settings are very similar you will see similar or even repeated items. S Weapons are present here are common / uncommon - rare / God like - super experimental one of a kind. - 1.) sword / club / axe - 2.) Blessed / holy Weapons / mater worked / ancestors Weapons ect. - 3.) Gift of the gods / tooth of the great dragon / diamond of the deep. + 1. sword / club / axe + 2. Blessed / holy Weapons / mater worked / ancestors Weapons ect. + 3. Gift of the gods / tooth of the great dragon / diamond of the deep. - 1.) 3d printed weapons / old world rusty / hand me down. - 2.) Branded Gucci weapons / Military grade / master Smithed construction. - 3.) Mono edge hyper blade / organic deconstruction forged / experimental titanium fusion cutters. + 1. 3d printed weapons / old world rusty / hand me down. + 2. Branded Gucci weapons / Military grade / master Smithed construction. + 3. Mono edge hyper blade / organic deconstruction forged / experimental titanium fusion cutters. - 1.) Pocket knife / house toots ( shovel / cricket bat ) ect. - 2.) Cold forged / silver / rolled and folded metal / combat proven. - 3.) Titanium / steam powered / pneumatic / dimond edge / chrome plated / + 1. Pocket knife / house tools ( shovel / cricket bat) ect. + 2. Cold forged / silver / rolled and folded metal / combat proven. + 3. Titanium / steam powered / pneumatic / dimond edge / chrome plated / - 1.) Hidden blade (shoe / wrist) / spike ring / sleep spray. - 2.) Tazer / brass knuckles / trippy spray / batton "tonfa". - 3.) One of a kind Q experimental weapons. / uranium blade / banned chemical weapons acid spray . + 1. Hidden blade (shoe / wrist) / spike ring / sleep spray. + 2. Tazer / brass knuckles / trippy spray / batton "tonfa". + 3. One of a kind Q experimental weapons. / uranium blade / banned chemical weapons acid spray . - 1.) Axe / sword / club - 2.) Monster bone / monster blood forged / slayer weapons from ancient times / Blood line inherited weapons. - 3.) Gift of the gods / God forged / meteoric metals. Slayed a demi God / used in God war / has shed the blood of gods. + 1. Axe / sword / club + 2. Monster bone / monster blood forged / slayer weapons from ancient times / Blood line inherited weapons. + 3. Gift of the gods / God forged / meteoric metals. Slayed a demi God / used in God war / has shed the blood of gods. - 1.) Kitchen knife / tools. Home made defence weapons. - 2.) Antique weapons / Exotic poison coated / battle tested. - 3.) Tooth of cathulu / esoteric mind sliver / weapons of the fallen kings of Atlantis. + 1. Kitchen knife / tools. Home made defence weapons. + 2. Antique weapons / Exotic poison coated / battle tested. + 3. Tooth of cathulu / esoteric mind sliver / weapons of the fallen kings of Atlantis. - 1.) Combat blade / basic military kit / temu mall ninja gear. - 2.) Laser eched weapons / small batch field test weapons / brand new out of box. - 3.) Gauntlets of telk / eye of ra / worm tooth of si Halood. + 1. Combat blade / basic military kit / temu mall ninja gear. + 2. Laser eched weapons / small batch field test weapons / brand new out of box. + 3. Gauntlets of telk / eye of ra / worm tooth of si Halood. - 1.) Bowie knife / tomahawk / native spear / cast iron tools ect. - 2.) Spring Steel / cold forged / rattle snake poison / mercury edged / Reverse Serrated. - 3.) Spear of the dream walker / experimental gun blade / blade of the templar / Vatican blessed holy relic. - -## Narrative Goals - - 1.) Defeat villian / kill all x in area. - 2.) Collection of item(s) - 3.) Activation or deactivate grid / power supply / ritual. + 1. Bowie knife / tomahawk / native spear / cast iron tools ect. + 2. Spring Steel / cold forged / rattle snake poison / mercury edged / Reverse Serrated. + 3. Spear of the dream walker / experimental gun blade / blade of the templar / Vatican blessed holy relic. ## Ranged Weapons @@ -77,20 +72,25 @@ As some settings are very similar you will see similar or even repeated items. S Weapons are present here are common / uncommon - rare / God like - super experimental one of a kind. - 1.) Bow / cross bow / sling / javelins ect. - 2.) Magically enchanted weapons and or ammunition / holy / master worked / Ancestors. - 3.) Gift of the gods. Dragon fire bow / soul eater crossbow / javelins of lightning. + 1. Bow / cross bow / sling / javelins ect. + 2. Magically enchanted weapons and or ammunition / holy / master worked / Ancestors. + 3. Gift of the gods. Dragon fire bow / soul eater crossbow / javelins of lightning. - 1.) 3d printed guns / rusty old word guns. Jerry rigged. - 2.) Branded Gucci guns / Military grade / bespoke special editions / specifically designed ammo (armour piecing / hollow point ect.) - 3.) Tesla hyper beam cannon / experimental thematic manipulation ray / gravidic conversion stream / anti reality fabric hacker / spontaneous combustion field / magnetic ion atom smasher. + 1. 3d printed guns / rusty old word guns. Jerry rigged. + 2. Branded Gucci guns / Military grade / bespoke special editions / specifically designed ammo (armour piecing / hollow point ect.) + 3. Tesla hyper beam cannon / experimental thematic manipulation ray / gravidic conversion stream / anti reality fabric hacker / spontaneous combustion field / magnetic ion atom smasher. - 1.) Common crystal construction / home made / fragile. - 2.) Antique construction of past generations / sturdy construction / multiple firing chambers / more exotic and rare earth minerals. - 3.) Pure untarnished faultless crystal or gem construction / soul gem that contains ally or enemy soul / pure unstable quantum core power supply. + 1. Common crystal construction / home made / fragile. + 2. Antique construction of past generations / sturdy construction / multiple firing chambers / more exotic and rare earth minerals. + 3. Pure untarnished faultless crystal or gem construction / soul gem that contains ally or enemy soul / pure unstable quantum core power supply. - 1.) Crude / poor construction / simple blow guns and projectiles. - 2.) Old world weapons / new condition or recently recovered / mint condition or cannibalised guns rifles ect. Specially designed ammunition. - 3.) Pre war experimental weapons (see cyberpunk) + 1. Crude / poor construction / simple blow guns and projectiles. + 2. Old world weapons / new condition or recently recovered / mint condition or cannibalised guns rifles ect. Specially designed ammunition. + 3. Pre war experimental weapons (see cyberpunk) +## Narrative Goals + + 1. Defeat villian / kill all x in area. + 2. Collection of item(s) + 3. Activation or deactivate grid / power supply / ritual. \ No newline at end of file diff --git a/source/actions.py b/source/actions.py index 25d527b..febb8c3 100644 --- a/source/actions.py +++ b/source/actions.py @@ -10,9 +10,10 @@ if TYPE_CHECKING: from entity import Entity class BaseAction: - entity: Entity #the entity to which this action applies + """Base type for the various actions to apply to a specified entity.""" + entity: Entity - def __init__(self, entity): + def __init__(self, entity: Entity): self.entity = entity def perform(self) -> bool: @@ -95,7 +96,7 @@ class MeleeAction(BaseAction): engine.message_log.add_message(text = msg_text) - #actually applying the change here, so the player's death event is at the bottom of the message log + #performing the actual change here, so the player's death event is at the bottom of the message log target.stats.current_hp -= damage return True diff --git a/source/entity.py b/source/entity.py index ed1ba0d..040f251 100644 --- a/source/entity.py +++ b/source/entity.py @@ -1,17 +1,21 @@ from __future__ import annotations import copy -from typing import Optional, Tuple, Type +from typing import Optional, Tuple, Type, TYPE_CHECKING -from stats import Stats from ai import BaseAI -from useable import BaseUseable +from stats import Stats from inventory import Inventory +from useable import BaseUseable + +if TYPE_CHECKING: + from floor_map import FloorMap class Entity: - stats: Stats - ai: BaseAI - useable: BaseUseable + ai: Optional[BaseAI] = None + stats: Optional[Stats] = None + inventory: Optional[Inventory] = None + useable: Optional[BaseUseable] = None def __init__( self, @@ -19,17 +23,18 @@ class Entity: y: int = 0, char: str = "?", color: Tuple[int, int, int] = (255, 255, 255), + *, name: str = "", walkable: bool = True, - floor_map = None, + floor_map: FloorMap = None, #monster-specific stuff ai_class: Type[BaseAI] = None, stats: Stats = None, #item-specific stuff - useable: BaseUseable = None, inventory: Inventory = None, + useable: BaseUseable = None, ): self.x = x self.y = y @@ -41,17 +46,21 @@ class Entity: #monster-specific stuff if ai_class: - self.ai: Optional[BaseAI] = ai_class(self) + self.ai = ai_class(self) - self.stats = stats - self.stats.entity = self + if stats: + self.stats = stats + self.stats.entity = self #item-specific stuff - self.useable = useable - self.inventory = inventory + if inventory: + self.inventory = inventory + + if useable: + self.useable = useable #generic entity stuff - def spawn(self, x: int, y: int, floor_map): + def spawn(self, x: int, y: int, floor_map: FloorMap): clone = copy.deepcopy(self) clone.x = x clone.y = y diff --git a/source/entity_types.py b/source/entity_types.py index 3c653d4..091d907 100644 --- a/source/entity_types.py +++ b/source/entity_types.py @@ -3,6 +3,7 @@ from ai import BaseAI, AggressiveWhenSeen from stats import Stats from inventory import Inventory +#player and utils player = Entity( char = "@", color = (255, 255, 255), @@ -13,7 +14,7 @@ player = Entity( inventory=Inventory(), ) -#gobbos +#monsters - gobbos gobbo = Entity( char = "g", color = (30, 168, 41), @@ -32,4 +33,5 @@ gobbo_red = Entity( stats = Stats(hp = 5, attack = 1, defense = 0), #this guy can't catch a break ) -#TODO: healing potion, spawned in the map \ No newline at end of file +#items - conumables +#TODO: potion of healing entity \ No newline at end of file diff --git a/source/event_handlers.py b/source/event_handlers.py index 0d72c9c..eab556a 100644 --- a/source/event_handlers.py +++ b/source/event_handlers.py @@ -283,9 +283,11 @@ class InventoryViewer(EventHandler): self.engine.event_handler = OptionSelector(self.engine, self, title=f"Drop The {item.name}?", options=["Yes", "No"], - callback=lambda x: self.drop_callback(x) + callback=lambda x: self.selector_callback(x) ) + #TODO: hotkeys via a config + elif event.sym == tcod.event.KeySym.HOME: self.cursor = 0 elif event.sym == tcod.event.KeySym.END: @@ -295,17 +297,22 @@ class InventoryViewer(EventHandler): self.engine.event_handler = self.parent_handler #utils - def drop_callback(self, answer: int) -> Optional[BaseAction]: - #process the answer, giving the signal of what to do - if answer == 0: - c = self.cursor + def selector_callback(self, answer: int) -> Optional[BaseAction]: + #TODO: insert a sub-selection box to choose what to do with this item + if answer == 0: #TODO: Use, Drop, Back + return self.drop() + + def drop(self) -> Optional[BaseAction]: + """Drop the item at the cursor's position, and adjust the cursor if needed.""" + if self.length > 0: + index = self.cursor #bounds self.length -= 1 if self.cursor >= self.length: self.cursor = self.length - 1 - return DropAction(self.entity, c) + return DropAction(self.entity, index) #generic tools @@ -377,7 +384,7 @@ class OptionSelector(EventHandler): elif event.sym in CURSOR_CONFIRM_KEYS: self.engine.event_handler = self.parent_handler - return self.callback(self.cursor) #confirm this selection, and exit + return self.callback(self.cursor) elif event.sym == tcod.event.KeySym.HOME: self.cursor = 0 diff --git a/source/stats.py b/source/stats.py index ddbe3f5..021ba15 100644 --- a/source/stats.py +++ b/source/stats.py @@ -14,8 +14,6 @@ class Stats: """Handles stats for an Entity""" entity: Entity - #TODO: better combat system - def __init__(self, hp: int, attack: int, defense: int): self._maximum_hp = hp self._current_hp = hp @@ -53,5 +51,5 @@ class Stats: self.entity.color = (191, 0, 0) self.entity.walkable = True self.entity.ai = None #TODO: Could decay over time - self.entity.useable = BaseUseable(self.entity) #TMP + self.entity.useable = BaseUseable() #TODO: dummied in a "usable" to let dead objects be treated like items self.entity.name = f"Dead {self.entity.name}" diff --git a/source/useable.py b/source/useable.py index a2e16bf..cb8bb5b 100644 --- a/source/useable.py +++ b/source/useable.py @@ -1,26 +1,31 @@ from __future__ import annotations -from typing import List, Tuple, TYPE_CHECKING +from typing import TYPE_CHECKING -from actions import BaseAction, MeleeAction, MovementAction, WaitAction +from actions import BaseAction if TYPE_CHECKING: - from entity import Entity + from stats import Stats class BaseUseable: """Base type for useable items, with various utilities""" - entity: Entity - def __init__(self, entity): - self.entity = entity - - def activate(self) -> BaseAction: - """Activate this item's effect""" + def apply(self, stats: Stats) -> BaseAction: + """Use this item's effects""" raise NotImplementedError() -class Consumable(BaseUseable): - """This disappears after use""" - def activate(self) -> BaseAction: - pass +class PotionOfHealing(BaseUseable): #TODO: Finish the potion of healing + """Restore a specified amount of health to the given Stats object""" + amount: int -#TODO: finish useable items, with distinct effects \ No newline at end of file + def __init__(self, amount: int): + self.amount = amount + + def apply(self, stats: Stats) -> BaseAction: + """Use this item's effects""" + raise NotImplementedError() + +# NOTE: NetHack's version +# Healing: 8d4 | 6d4 | 4d4. If the result is above MaxHP, MaxHP is incrased by 1 | 1 | 0. +# Extra Healing: 8d8 | 6d8 | 4d8. If the result is above MaxHP, MaxHP is incrased by 5 | 2 | 0. +# Full Healing: 400 | 400 | 400. If the result is above MaxHP, MaxHP is incrased by 8 | 4 | 0.