Start turn-based menu

This commit is contained in:
Griatch 2023-03-10 21:27:15 +01:00
parent f42f4bf23e
commit 7971e6c2ff
3 changed files with 77 additions and 59 deletions

View file

@ -1,9 +1,7 @@
# Part 3: How we get there (example game)
```{warning}
The tutorial game is under development and is not yet complete, nor tested. Use the existing
lessons as inspiration and to help get you going, but don't expect out-of-the-box perfection
from it at this time.
The tutorial game is under development and is not yet complete, nor tested. Use the existing lessons as inspiration and to help get you going, but don't expect out-of-the-box perfection from it at this time.
```
```{sidebar} Beginner Tutorial Parts
@ -22,19 +20,15 @@ from it at this time.
```
In part three of the Evennia Beginner tutorial we will go through the actual creation of
our tutorial game _EvAdventure_, based on the [Knave](https://www.drivethrurpg.com/product/250888/Knave)
RPG ruleset.
This is a big part. You'll be seeing a lot of code and there are plenty of lessons to go through.
Take your time!
If you followed the previous parts of this tutorial you will have some notions about Python and where to
find and make use of things in Evennia. We also have a good idea of the type of game we will
create.
our tutorial game _EvAdventure_, based on the [Knave](https://www.drivethrurpg.com/product/250888/Knave) RPG ruleset.
Even if this is not the game-style you are interested in, following along will give you a lot
of experience using Evennia and be really helpful for doing your own thing later!
This is a big part. You'll be seeing a lot of code and there are plenty of lessons to go through. Take your time!
If you followed the previous parts of this tutorial series you will have some notions about Python and where to find and make use of things in Evennia. We also have a good idea of the type of game we will create.
Fully coded examples of all code we make in this part can be found in the
[evennia/contrib/tutorials/evadventure](../../../api/evennia.contrib.tutorials.evadventure.md) package.
@ -53,7 +47,7 @@ Beginner-Tutorial-Equipment
Beginner-Tutorial-Chargen
Beginner-Tutorial-Rooms
Beginner-Tutorial-NPCs
Beginner-Tutorial-Turnbased-Combat
Beginner-Tutorial-Combat
Beginner-Tutorial-Quests
Beginner-Tutorial-Shops
Beginner-Tutorial-Dungeon

View file

@ -437,6 +437,7 @@ class EvAdventureCombatHandler(DefaultScript):
flee_timeout = 1
# persistent storage
turn = AttributeProperty(0)
# who is involved in combat, and their action queue,
@ -569,6 +570,13 @@ class EvAdventureCombatHandler(DefaultScript):
"""
self.combatants[combatant].append(action_dict)
# track who inserted actions this turn (non-persistent)
did_action = set(self.nbd.did_action or ())
did_action.add(combatant)
if len(did_action) >= len(self.combatants):
# everyone has inserted an action. Start next turn without waiting!
self.force_repeat()
def execute_next_action(self, combatant):
"""
Perform a combatant's next queued action. Note that there is _always_ an action queued,
@ -656,6 +664,22 @@ class EvAdventureCombatHandler(DefaultScript):
self.msg(txt)
self.stop_combat()
def get_combat_summary(self, combatant):
"""
Get a 'battle report' - an overview of the current state of combat.
Goblin shaman
Ally (hurt) Goblin brawler
Bob vs Goblin grunt 1 (hurt)
Goblin grunt 2
Goblin grunt 3
"""
allies, enemies = self.get_sides(combatant)
nallies, nenemies = len(allies), len(enemies)
# make a table with three columns
def get_or_create_combathandler(combatant, combathandler_name="combathandler", combat_tick=5):
"""
@ -711,7 +735,6 @@ Examples of commands:
- |yuse <item> on <target>|n - use an item on an enemy or ally
- |yflee|n - start to flee or disengage from combat
- |yhinder|n - hinder an enemy from fleeing
Use |yhelp <command>|n for more info."""
@ -762,7 +785,6 @@ class CombatCmdSet(CmdSet):
self.add(CmdUseItem())
self.add(CmdWield())
self.add(CmdUseFlee())
self.add(CmdUseHinder())
class CmdAttack(_CmdCombatBase):
@ -965,44 +987,6 @@ class CmdFlee(_CmdCombatBase):
self.msg("You prepare to flee!")
class CmdHinder(_CmdCombatBase):
"""
Hinder an enemy from fleeing combat. This is a DEX challenge. If you
don't specify a target, you'll try to block one that flees (or a random
one if there are multiple fleeing enemies).
Usage:
hinder [target]
block [target]
"""
key = "hinder"
aliases = ["block"]
def func(self):
# see if anyone is trying to run away
combathandler = self.combathandler
allies, enemies = combathander.get_sides(self.caller)
fleeing_enemies = list(
set(enemies).intersection(set(combathandler.fleeing_combatants.values()))
)
if not fleeing_enemies:
self.caller.msg("No enemies are fleeing!")
return
if self.args:
target = self.caller.search(self.args, candidates=fleeing_enemies)
if not target:
return
else:
target = random.choice(fleeing_enemies)
combathandler.queue_action(self.caller, {"key": "hinder", "target": target})
# -----------------------------------------------------------------------------------
#
# Turn-based combat (Final Fantasy style), using a menu
@ -1010,10 +994,51 @@ class CmdHinder(_CmdCombatBase):
# -----------------------------------------------------------------------------------
def _get_menu_options(caller):
location = caller.location
def _get_combathandler(caller):
evmenu = caller.ndb._evmenu
if not hasattr(evmenu, "combathandler"):
evmenu.combathandler = get_or_create_combathandler(caller)
return evmenu.combathandler
combathandler = location.scripts.get("combathandler")
def _select_target(caller, raw_string, **kwargs):
"""Helper to set a selection"""
action_dict = kwargs["action_dict"]
action_dict["target"] = kwargs["target"]
_get_combathandler(caller).queue_action(caller, action_dict)
def node_choose_target(caller, raw_string, **kwargs):
"""
Choose target!
"""
text = kwargs.get("text", "Choose your target!")
target_type = kwargs.get("target_type", "enemies")
combathandler = _get_combathandler(caller)
allies, enemies = combathandler.get_sides(caller)
if target_type == "enemies":
targets = enemies
else:
targets = allies
options = [
{
"desc": target.get_display_name(caller),
"goto": (_select_target, {"target": target, **kwargs}),
}
for target in targets
]
return text, options
def node_combat(caller, raw_string, **kwargs):
"""Base combat menu"""
text = ""
## -----------------------------------------------------------------------------------

View file

@ -6,13 +6,12 @@ ability to run timers.
"""
from django.utils.translation import gettext as _
from twisted.internet.defer import Deferred, maybeDeferred
from twisted.internet.task import LoopingCall
from evennia.scripts.manager import ScriptManager
from evennia.scripts.models import ScriptDB
from evennia.typeclasses.models import TypeclassBase
from evennia.utils import create, logger
from twisted.internet.defer import Deferred, maybeDeferred
from twisted.internet.task import LoopingCall
__all__ = ["DefaultScript", "DoNothing", "Store"]