Start turn-based menu
This commit is contained in:
parent
f42f4bf23e
commit
7971e6c2ff
3 changed files with 77 additions and 59 deletions
|
|
@ -1,9 +1,7 @@
|
||||||
# Part 3: How we get there (example game)
|
# Part 3: How we get there (example game)
|
||||||
|
|
||||||
```{warning}
|
```{warning}
|
||||||
The tutorial game is under development and is not yet complete, nor tested. Use the existing
|
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.
|
||||||
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
|
```{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
|
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)
|
our tutorial game _EvAdventure_, based on the [Knave](https://www.drivethrurpg.com/product/250888/Knave) RPG ruleset.
|
||||||
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.
|
|
||||||
|
|
||||||
Even if this is not the game-style you are interested in, following along will give you a lot
|
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!
|
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
|
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.
|
[evennia/contrib/tutorials/evadventure](../../../api/evennia.contrib.tutorials.evadventure.md) package.
|
||||||
|
|
||||||
|
|
@ -53,7 +47,7 @@ Beginner-Tutorial-Equipment
|
||||||
Beginner-Tutorial-Chargen
|
Beginner-Tutorial-Chargen
|
||||||
Beginner-Tutorial-Rooms
|
Beginner-Tutorial-Rooms
|
||||||
Beginner-Tutorial-NPCs
|
Beginner-Tutorial-NPCs
|
||||||
Beginner-Tutorial-Turnbased-Combat
|
Beginner-Tutorial-Combat
|
||||||
Beginner-Tutorial-Quests
|
Beginner-Tutorial-Quests
|
||||||
Beginner-Tutorial-Shops
|
Beginner-Tutorial-Shops
|
||||||
Beginner-Tutorial-Dungeon
|
Beginner-Tutorial-Dungeon
|
||||||
|
|
|
||||||
|
|
@ -437,6 +437,7 @@ class EvAdventureCombatHandler(DefaultScript):
|
||||||
flee_timeout = 1
|
flee_timeout = 1
|
||||||
|
|
||||||
# persistent storage
|
# persistent storage
|
||||||
|
|
||||||
turn = AttributeProperty(0)
|
turn = AttributeProperty(0)
|
||||||
|
|
||||||
# who is involved in combat, and their action queue,
|
# who is involved in combat, and their action queue,
|
||||||
|
|
@ -569,6 +570,13 @@ class EvAdventureCombatHandler(DefaultScript):
|
||||||
"""
|
"""
|
||||||
self.combatants[combatant].append(action_dict)
|
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):
|
def execute_next_action(self, combatant):
|
||||||
"""
|
"""
|
||||||
Perform a combatant's next queued action. Note that there is _always_ an action queued,
|
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.msg(txt)
|
||||||
self.stop_combat()
|
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):
|
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
|
- |yuse <item> on <target>|n - use an item on an enemy or ally
|
||||||
|
|
||||||
- |yflee|n - start to flee or disengage from combat
|
- |yflee|n - start to flee or disengage from combat
|
||||||
- |yhinder|n - hinder an enemy from fleeing
|
|
||||||
|
|
||||||
Use |yhelp <command>|n for more info."""
|
Use |yhelp <command>|n for more info."""
|
||||||
|
|
||||||
|
|
@ -762,7 +785,6 @@ class CombatCmdSet(CmdSet):
|
||||||
self.add(CmdUseItem())
|
self.add(CmdUseItem())
|
||||||
self.add(CmdWield())
|
self.add(CmdWield())
|
||||||
self.add(CmdUseFlee())
|
self.add(CmdUseFlee())
|
||||||
self.add(CmdUseHinder())
|
|
||||||
|
|
||||||
|
|
||||||
class CmdAttack(_CmdCombatBase):
|
class CmdAttack(_CmdCombatBase):
|
||||||
|
|
@ -965,44 +987,6 @@ class CmdFlee(_CmdCombatBase):
|
||||||
self.msg("You prepare to flee!")
|
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
|
# Turn-based combat (Final Fantasy style), using a menu
|
||||||
|
|
@ -1010,10 +994,51 @@ class CmdHinder(_CmdCombatBase):
|
||||||
# -----------------------------------------------------------------------------------
|
# -----------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
|
||||||
def _get_menu_options(caller):
|
def _get_combathandler(caller):
|
||||||
location = caller.location
|
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 = ""
|
||||||
|
|
||||||
|
|
||||||
## -----------------------------------------------------------------------------------
|
## -----------------------------------------------------------------------------------
|
||||||
|
|
|
||||||
|
|
@ -6,13 +6,12 @@ ability to run timers.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
from django.utils.translation import gettext as _
|
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.manager import ScriptManager
|
||||||
from evennia.scripts.models import ScriptDB
|
from evennia.scripts.models import ScriptDB
|
||||||
from evennia.typeclasses.models import TypeclassBase
|
from evennia.typeclasses.models import TypeclassBase
|
||||||
from evennia.utils import create, logger
|
from evennia.utils import create, logger
|
||||||
|
from twisted.internet.defer import Deferred, maybeDeferred
|
||||||
|
from twisted.internet.task import LoopingCall
|
||||||
|
|
||||||
__all__ = ["DefaultScript", "DoNothing", "Store"]
|
__all__ = ["DefaultScript", "DoNothing", "Store"]
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue