mirror of
https://github.com/evennia/evennia.git
synced 2026-03-16 21:06:30 +01:00
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)
|
||||
|
||||
```{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
|
||||
|
|
|
|||
|
|
@ -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 = ""
|
||||
|
||||
|
||||
## -----------------------------------------------------------------------------------
|
||||
|
|
|
|||
|
|
@ -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"]
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue