Prep for parallel main branch
This commit is contained in:
parent
0da5969bad
commit
cf5987d16a
12 changed files with 57 additions and 164 deletions
|
|
@ -2,8 +2,10 @@
|
||||||
|
|
||||||
### Evennia 1.0
|
### Evennia 1.0
|
||||||
|
|
||||||
> Not released yet
|
2019-2022 develop branch
|
||||||
> 2019-2022 develop branch (WIP)
|
|
||||||
|
Changed to using `main` branch to follow github standard. Old `master` branch remains
|
||||||
|
for now but will not be used anymore, so as to not break installs during transition.
|
||||||
|
|
||||||
Increase requirements: Django 4.1+, Twisted 22.10+ Python 3.10, 3.11. PostgreSQL 11+.
|
Increase requirements: Django 4.1+, Twisted 22.10+ Python 3.10, 3.11. PostgreSQL 11+.
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -126,7 +126,7 @@ for these useful functions.
|
||||||
|
|
||||||
### `git branch`, `checkout` and `merge`
|
### `git branch`, `checkout` and `merge`
|
||||||
|
|
||||||
Git allows you to work with _branches_. These are separate development paths your code may take, completely separate from each other. You can later _merge_ the code from a branch back into another branch. Evennia's `master` and `develop` branches are examples of this.
|
Git allows you to work with _branches_. These are separate development paths your code may take, completely separate from each other. You can later _merge_ the code from a branch back into another branch. Evennia's `main` and `develop` branches are examples of this.
|
||||||
|
|
||||||
git branch -b branchaname
|
git branch -b branchaname
|
||||||
|
|
||||||
|
|
@ -225,11 +225,6 @@ So far your code is only located on your private machine. A good idea is to back
|
||||||
|
|
||||||
If you don't want your code to be publicly visible, Github also allows you set up a _private_ repository, only visible to you.
|
If you don't want your code to be publicly visible, Github also allows you set up a _private_ repository, only visible to you.
|
||||||
|
|
||||||
|
|
||||||
```{note}
|
|
||||||
Github's defaults have changed to calling the primary branch 'main' rather than 'master'. While Evennia still uses 'master' branch (and this is what we refer to below), you can use either name for your personal primary branch - they are equivalent.
|
|
||||||
```
|
|
||||||
|
|
||||||
Create a new, empty repository on Github. [Github explains how here](https://help.github.com/articles/create-a-repo/) . _Don't_ allow it to add a README, license etc, that will just clash with what we upload later.
|
Create a new, empty repository on Github. [Github explains how here](https://help.github.com/articles/create-a-repo/) . _Don't_ allow it to add a README, license etc, that will just clash with what we upload later.
|
||||||
|
|
||||||
```{sidebar} Origin
|
```{sidebar} Origin
|
||||||
|
|
@ -282,7 +277,7 @@ If you also want to access Evennia's `develop` branch (the bleeding edge develop
|
||||||
|
|
||||||
Use
|
Use
|
||||||
|
|
||||||
git checkout master
|
git checkout main
|
||||||
git checkout develop
|
git checkout develop
|
||||||
|
|
||||||
to switch between the branches.
|
to switch between the branches.
|
||||||
|
|
@ -299,17 +294,17 @@ You can't do `git push upstream` unless you have write-access to the upstream Ev
|
||||||
|
|
||||||
This should be done in your fork of Evennia. You should _always_ do this in a _separate git branch_ based off the Evennia branch you want to improve.
|
This should be done in your fork of Evennia. You should _always_ do this in a _separate git branch_ based off the Evennia branch you want to improve.
|
||||||
|
|
||||||
git checkout master (or develop)
|
git checkout main (or develop)
|
||||||
git branch - b myfixbranch
|
git branch - b myfixbranch
|
||||||
|
|
||||||
Now fix whatever needs fixing. Abide by the [Evennia code style](./Evennia-Code-Style.md). You can `git commit` commit your changes along the way as normal.
|
Now fix whatever needs fixing. Abide by the [Evennia code style](./Evennia-Code-Style.md). You can `git commit` commit your changes along the way as normal.
|
||||||
|
|
||||||
Upstream Evennia is not standing still, so you want to make sure that your work is up-to-date with upstream changes. Make sure to first commit your `myfixbranch` changes, then
|
Upstream Evennia is not standing still, so you want to make sure that your work is up-to-date with upstream changes. Make sure to first commit your `myfixbranch` changes, then
|
||||||
|
|
||||||
git checkout master (or develop)
|
git checkout main (or develop)
|
||||||
git pull upstream
|
git pull upstream
|
||||||
git checkout myfixbranch
|
git checkout myfixbranch
|
||||||
git merge master (or develop)
|
git merge main (or develop)
|
||||||
|
|
||||||
Up to this point your `myfixbranch` branch only exists on your local computer. No
|
Up to this point your `myfixbranch` branch only exists on your local computer. No
|
||||||
one else can see it.
|
one else can see it.
|
||||||
|
|
|
||||||
|
|
@ -156,7 +156,7 @@ These are links to resources outside of the documentation. We also provide some
|
||||||
[evennia.com](https://evennia.com) - link to an external website.
|
[evennia.com](https://evennia.com) - link to an external website.
|
||||||
```
|
```
|
||||||
|
|
||||||
- By using `(github:evennia/objects/objects.py)` as link target, you can point to a place on the Evennia github page (master branch).
|
- By using `(github:evennia/objects/objects.py)` as link target, you can point to a place on the Evennia github page (main branch).
|
||||||
- Use `(github:develop/evennia/objects/objects.py` to target `develop` branch.
|
- Use `(github:develop/evennia/objects/objects.py` to target `develop` branch.
|
||||||
- Use `(github:issue)` to point to the github issue-creation page.
|
- Use `(github:issue)` to point to the github issue-creation page.
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -43,7 +43,7 @@ Evennia is a free and open-source project. Any monetary donations you want to of
|
||||||
[pullrequest]: https://github.com/evennia/evennia/pulls
|
[pullrequest]: https://github.com/evennia/evennia/pulls
|
||||||
[issues]: https://github.com/evennia/evennia/issues
|
[issues]: https://github.com/evennia/evennia/issues
|
||||||
[patch]: https://secure.wikimedia.org/wikipedia/en/wiki/Patch_%28computing%29
|
[patch]: https://secure.wikimedia.org/wikipedia/en/wiki/Patch_%28computing%29
|
||||||
[codestyle]: https://github.com/evennia/evennia/blob/master/CODING_STYLE.md
|
[codestyle]:: Evennia-Code-Style
|
||||||
|
|
||||||
[forum]:https://github.com/evennia/evennia/discussions
|
[forum]:https://github.com/evennia/evennia/discussions
|
||||||
[issues]:https://github.com/evennia/evennia/issues/choose
|
[issues]:https://github.com/evennia/evennia/issues/choose
|
||||||
|
|
|
||||||
|
|
@ -96,8 +96,7 @@ The flat API is defined in `__init__.py` [viewable here](github:evennia/__init__
|
||||||
|
|
||||||
### Contributions
|
### Contributions
|
||||||
|
|
||||||
- [evennia.contrib](https://github.com/evennia/evennia/blob/master/evennia/contrib/) -
|
- [evennia.contrib](Contribs-Overview) game-specific contributions and plugins
|
||||||
game-specific contributions and plugins ([docs](https://github.com/evennia/evennia/blob/master/evennia/contrib/README.md))
|
|
||||||
|
|
||||||
```{toctree}
|
```{toctree}
|
||||||
:hidden:
|
:hidden:
|
||||||
|
|
|
||||||
|
|
@ -264,9 +264,7 @@ So about that function. Line 1:
|
||||||
- `def` is short for "define" and defines a *function* (or a *method*, if sitting on an object).
|
- `def` is short for "define" and defines a *function* (or a *method*, if sitting on an object).
|
||||||
This is a [reserved Python keyword](https://docs.python.org/2.5/ref/keywords.html); try not to use
|
This is a [reserved Python keyword](https://docs.python.org/2.5/ref/keywords.html); try not to use
|
||||||
these words anywhere else.
|
these words anywhere else.
|
||||||
- A function name can not have spaces but otherwise we could have called it almost anything. We call
|
- A function name can not have spaces but otherwise we could have called it almost anything. We call it `hello_world`. Evennia follows [Python's standard naming style](iEvennia-Code-Style) with lowercase letters and underscores. We recommend you do the same.
|
||||||
it `hello_world`. Evennia follows [Python's standard naming style](https://github.com/evennia/evennia/blob/master/CODING_STYLE.md#a-quick-list-of-code-style-points)
|
|
||||||
with lowercase letters and underscores. We recommend you do the same.
|
|
||||||
- The colon (`:`) at the end of line 1 indicates that the header of the function is complete.
|
- The colon (`:`) at the end of line 1 indicates that the header of the function is complete.
|
||||||
|
|
||||||
Line 2:
|
Line 2:
|
||||||
|
|
|
||||||
|
|
@ -76,7 +76,7 @@ When you enter the address `http://localhost:4001/story` in your web browser, Dj
|
||||||
field to figure out which page you want to go to. You tell it which patterns are relevant in the
|
field to figure out which page you want to go to. You tell it which patterns are relevant in the
|
||||||
file
|
file
|
||||||
[mygame/web/urls.py](https://github.com/evennia/evennia/blob/master/evennia/game_template/web/urls.py).
|
[mygame/web/urls.py](https://github.com/evennia/evennia/blob/master/evennia/game_template/web/urls.py).
|
||||||
Open it now.
|
Open it now
|
||||||
|
|
||||||
Django looks for the variable `urlpatterns` in this file. You want to add your new pattern to the
|
Django looks for the variable `urlpatterns` in this file. You want to add your new pattern to the
|
||||||
`custom_patterns` list we have prepared - that is then merged with the default `urlpatterns`. Here's
|
`custom_patterns` list we have prepared - that is then merged with the default `urlpatterns`. Here's
|
||||||
|
|
|
||||||
|
|
@ -62,33 +62,22 @@ want to check. That is, you want something similar to this:
|
||||||
result = rules.roll_challenge(character1, character2, "swords")
|
result = rules.roll_challenge(character1, character2, "swords")
|
||||||
```
|
```
|
||||||
|
|
||||||
You might need to make these functions more or less complex depending on your game. For example the
|
You might need to make these functions more or less complex depending on your game. For example the properties of the room might matter to the outcome of a roll (if the room is dark, burning etc). Establishing just what you need to send into your game mechanic module is a great way to also get a feel for what you need to add to your engine.
|
||||||
properties of the room might matter to the outcome of a roll (if the room is dark, burning etc).
|
|
||||||
Establishing just what you need to send into your game mechanic module is a great way to also get a
|
|
||||||
feel for what you need to add to your engine.
|
|
||||||
|
|
||||||
## Coded systems
|
## Coded systems
|
||||||
|
|
||||||
Inspired by tabletop role playing games, most game systems mimic some sort of die mechanic. To this
|
Inspired by tabletop role playing games, most game systems mimic some sort of die mechanic. To this end Evennia offers a full [dice roller](https://github.com/evennia/evennia/blob/master/evennia/contrib/dice.py) in its `contrib`
|
||||||
end Evennia offers a full [dice
|
folder. For custom implementations, Python offers many ways to randomize a result using its in-built `random` module. No matter how it's implemented, we will in this text refer to the action of determining an outcome as a "roll".
|
||||||
roller](https://github.com/evennia/evennia/blob/master/evennia/contrib/dice.py) in its `contrib`
|
|
||||||
folder. For custom implementations, Python offers many ways to randomize a result using its in-built
|
|
||||||
`random` module. No matter how it's implemented, we will in this text refer to the action of
|
|
||||||
determining an outcome as a "roll".
|
|
||||||
|
|
||||||
In a freeform system, the result of the roll is just compared with values and people (or the game
|
In a freeform system, the result of the roll is just compared with values and people (or the game
|
||||||
master) just agree on what it means. In a coded system the result now needs to be processed somehow.
|
master) just agree on what it means. In a coded system the result now needs to be processed somehow. There are many things that may happen as a result of rule enforcement:
|
||||||
There are many things that may happen as a result of rule enforcement:
|
|
||||||
|
|
||||||
- Health may be added or deducted. This can effect the character in various ways.
|
- Health may be added or deducted. This can effect the character in various ways.
|
||||||
- Experience may need to be added, and if a level-based system is used, the player might need to be
|
- Experience may need to be added, and if a level-based system is used, the player might need to be informed they have increased a level.
|
||||||
informed they have increased a level.
|
|
||||||
- Room-wide effects need to be reported to the room, possibly affecting everyone in the room.
|
- Room-wide effects need to be reported to the room, possibly affecting everyone in the room.
|
||||||
|
|
||||||
There are also a slew of other things that fall under "Coded systems", including things like
|
There are also a slew of other things that fall under "Coded systems", including things like
|
||||||
weather, NPC artificial intelligence and game economy. Basically everything about the world that a
|
weather, NPC artificial intelligence and game economy. Basically everything about the world that a Game master would control in a tabletop role playing game can be mimicked to some level by coded systems.
|
||||||
Game master would control in a tabletop role playing game can be mimicked to some level by coded
|
|
||||||
systems.
|
|
||||||
|
|
||||||
|
|
||||||
## Example of Rule module
|
## Example of Rule module
|
||||||
|
|
@ -96,24 +85,17 @@ systems.
|
||||||
Here is a simple example of a rule module. This is what we assume about our simple example game:
|
Here is a simple example of a rule module. This is what we assume about our simple example game:
|
||||||
- Characters have only four numerical values:
|
- Characters have only four numerical values:
|
||||||
- Their `level`, which starts at 1.
|
- Their `level`, which starts at 1.
|
||||||
- A skill `combat`, which determines how good they are at hitting things. Starts between 5 and
|
- A skill `combat`, which determines how good they are at hitting things. Starts between 5 and 10.
|
||||||
10.
|
|
||||||
- Their Strength, `STR`, which determine how much damage they do. Starts between 1 and 10.
|
- Their Strength, `STR`, which determine how much damage they do. Starts between 1 and 10.
|
||||||
- Their Health points, `HP`, which starts at 100.
|
- Their Health points, `HP`, which starts at 100.
|
||||||
- When a Character reaches `HP = 0`, they are presumed "defeated". Their HP is reset and they get a
|
- When a Character reaches `HP = 0`, they are presumed "defeated". Their HP is reset and they get a failure message (as a stand-in for death code).
|
||||||
failure message (as a stand-in for death code).
|
|
||||||
- Abilities are stored as simple Attributes on the Character.
|
- Abilities are stored as simple Attributes on the Character.
|
||||||
- "Rolls" are done by rolling a 100-sided die. If the result is below the `combat` value, it's a
|
- "Rolls" are done by rolling a 100-sided die. If the result is below the `combat` value, it's a success and damage is rolled. Damage is rolled as a six-sided die + the value of `STR` (for this example we ignore weapons and assume `STR` is all that matters).
|
||||||
success and damage is rolled. Damage is rolled as a six-sided die + the value of `STR` (for this
|
- Every successful `attack` roll gives 1-3 experience points (`XP`). Every time the number of `XP` reaches `(level + 1) ** 2`, the Character levels up. When leveling up, the Character's `combat` value goes up by 2 points and `STR` by one (this is a stand-in for a real progression system).
|
||||||
example we ignore weapons and assume `STR` is all that matters).
|
|
||||||
- Every successful `attack` roll gives 1-3 experience points (`XP`). Every time the number of `XP`
|
|
||||||
reaches `(level + 1) ** 2`, the Character levels up. When leveling up, the Character's `combat`
|
|
||||||
value goes up by 2 points and `STR` by one (this is a stand-in for a real progression system).
|
|
||||||
|
|
||||||
### Character
|
### Character
|
||||||
|
|
||||||
The Character typeclass is simple. It goes in `mygame/typeclasses/characters.py`. There is already
|
The Character typeclass is simple. It goes in `mygame/typeclasses/characters.py`. There is already an empty `Character` class there that Evennia will look to and use.
|
||||||
an empty `Character` class there that Evennia will look to and use.
|
|
||||||
|
|
||||||
```python
|
```python
|
||||||
from random import randint
|
from random import randint
|
||||||
|
|
|
||||||
|
|
@ -9,89 +9,41 @@ list](https://groups.google.com/forum/#!msg/evennia/wnJNM2sXSfs/-dbLRrgWnYMJ).
|
||||||
|
|
||||||
Most MUDs will use some sort of combat system. There are several main variations:
|
Most MUDs will use some sort of combat system. There are several main variations:
|
||||||
|
|
||||||
- _Freeform_ - the simplest form of combat to implement, common to MUSH-style roleplaying games.
|
- _Freeform_ - the simplest form of combat to implement, common to MUSH-style roleplaying games. This means the system only supplies dice rollers or maybe commands to compare skills and spit out the result. Dice rolls are done to resolve combat according to the rules of the game and to direct the scene. A game master may be required to resolve rule disputes.
|
||||||
This means the system only supplies dice rollers or maybe commands to compare skills and spit out
|
- _Twitch_ - This is the traditional MUD hack&slash style combat. In a twitch system there is often no difference between your normal "move-around-and-explore mode" and the "combat mode". You enter an attack command and the system will calculate if the attack hits and how much damage was caused. Normally attack commands have some sort of timeout or notion of recovery/balance to reduce the advantage of spamming or client scripting. Whereas the simplest systems just means entering `kill <target>` over and over, more sophisticated twitch systems include anything from defensive stances to tactical positioning.
|
||||||
the result. Dice rolls are done to resolve combat according to the rules of the game and to direct
|
- _Turn-based_ - a turn based system means that the system pauses to make sure all combatants can choose their actions before continuing. In some systems, such entered actions happen immediately (like twitch-based) whereas in others the resolution happens simultaneously at the end of the turn. The disadvantage of a turn-based system is that the game must switch to a "combat mode" and one also needs to take special care of how to handle new combatants and the passage of time. The advantage is that success is not dependent on typing speed or of setting up quick client macros. This potentially allows for emoting as part of combat which is an advantage for roleplay-heavy games.
|
||||||
the scene. A game master may be required to resolve rule disputes.
|
|
||||||
- _Twitch_ - This is the traditional MUD hack&slash style combat. In a twitch system there is often
|
|
||||||
no difference between your normal "move-around-and-explore mode" and the "combat mode". You enter an
|
|
||||||
attack command and the system will calculate if the attack hits and how much damage was caused.
|
|
||||||
Normally attack commands have some sort of timeout or notion of recovery/balance to reduce the
|
|
||||||
advantage of spamming or client scripting. Whereas the simplest systems just means entering `kill
|
|
||||||
<target>` over and over, more sophisticated twitch systems include anything from defensive stances
|
|
||||||
to tactical positioning.
|
|
||||||
- _Turn-based_ - a turn based system means that the system pauses to make sure all combatants can
|
|
||||||
choose their actions before continuing. In some systems, such entered actions happen immediately
|
|
||||||
(like twitch-based) whereas in others the resolution happens simultaneously at the end of the turn.
|
|
||||||
The disadvantage of a turn-based system is that the game must switch to a "combat mode" and one also
|
|
||||||
needs to take special care of how to handle new combatants and the passage of time. The advantage is
|
|
||||||
that success is not dependent on typing speed or of setting up quick client macros. This potentially
|
|
||||||
allows for emoting as part of combat which is an advantage for roleplay-heavy games.
|
|
||||||
|
|
||||||
To implement a freeform combat system all you need is a dice roller and a roleplaying rulebook. See
|
To implement a freeform combat system all you need is a dice roller and a roleplaying rulebook. See [contrib/dice.py](Contrib-Dice) for an example dice roller. To implement at twitch-based system you basically need a few combat [commands](../Components/Commands.md), possibly ones with a [cooldown](./Howto-Command-Cooldown.md). You also need a [game rule module](./Implementing-a-game-rule-system.md) that makes use of it. We will focus on the turn-based variety here.
|
||||||
[contrib/dice.py](https://github.com/evennia/evennia/blob/master/evennia/contrib/dice.py) for an
|
|
||||||
example dice roller. To implement at twitch-based system you basically need a few combat
|
|
||||||
[commands](../Components/Commands.md), possibly ones with a [cooldown](./Howto-Command-Cooldown.md). You also need a [game rule
|
|
||||||
module](./Implementing-a-game-rule-system.md) that makes use of it. We will focus on the turn-based
|
|
||||||
variety here.
|
|
||||||
|
|
||||||
## Tutorial overview
|
## Tutorial overview
|
||||||
|
|
||||||
This tutorial will implement the slightly more complex turn-based combat system. Our example has the
|
This tutorial will implement the slightly more complex turn-based combat system. Our example has the following properties:
|
||||||
following properties:
|
|
||||||
|
|
||||||
- Combat is initiated with `attack <target>`, this initiates the combat mode.
|
- Combat is initiated with `attack <target>`, this initiates the combat mode.
|
||||||
- Characters may join an ongoing battle using `attack <target>` against a character already in
|
- Characters may join an ongoing battle using `attack <target>` against a character already in
|
||||||
combat.
|
combat.
|
||||||
- Each turn every combating character will get to enter two commands, their internal order matters
|
- Each turn every combating character will get to enter two commands, their internal order matters and they are compared one-to-one in the order given by each combatant. Use of `say` and `pose` is free.
|
||||||
and they are compared one-to-one in the order given by each combatant. Use of `say` and `pose` is
|
- The commands are (in our example) simple; they can either `hit <target>`, `feint <target>` or `parry <target>`. They can also `defend`, a generic passive defense. Finally they may choose to `disengage/flee`.
|
||||||
free.
|
- When attacking we use a classic [rock-paper-scissors](https://en.wikipedia.org/wiki/Rock-paper- scissors) mechanic to determine success: `hit` defeats `feint`, which defeats `parry` which defeats `hit`. `defend` is a general passive action that has a percentage chance to win against `hit` (only).
|
||||||
- The commands are (in our example) simple; they can either `hit <target>`, `feint <target>` or
|
- `disengage/flee` must be entered two times in a row and will only succeed if there is no `hit` against them in that time. If so they will leave combat mode.
|
||||||
`parry <target>`. They can also `defend`, a generic passive defense. Finally they may choose to
|
- Once every player has entered two commands, all commands are resolved in order and the result is reported. A new turn then begins.
|
||||||
`disengage/flee`.
|
|
||||||
- When attacking we use a classic [rock-paper-scissors](https://en.wikipedia.org/wiki/Rock-paper-
|
|
||||||
scissors) mechanic to determine success: `hit` defeats `feint`, which defeats `parry` which defeats
|
|
||||||
`hit`. `defend` is a general passive action that has a percentage chance to win against `hit`
|
|
||||||
(only).
|
|
||||||
- `disengage/flee` must be entered two times in a row and will only succeed if there is no `hit`
|
|
||||||
against them in that time. If so they will leave combat mode.
|
|
||||||
- Once every player has entered two commands, all commands are resolved in order and the result is
|
|
||||||
reported. A new turn then begins.
|
|
||||||
- If players are too slow the turn will time out and any unset commands will be set to `defend`.
|
- If players are too slow the turn will time out and any unset commands will be set to `defend`.
|
||||||
|
|
||||||
For creating the combat system we will need the following components:
|
For creating the combat system we will need the following components:
|
||||||
|
|
||||||
- A combat handler. This is the main mechanic of the system. This is a [Script](../Components/Scripts.md) object
|
- A combat handler. This is the main mechanic of the system. This is a [Script](../Components/Scripts.md) object created for each combat. It is not assigned to a specific object but is shared by the combating characters and handles all the combat information. Since Scripts are database entities it also means that the combat will not be affected by a server reload.
|
||||||
created for each combat. It is not assigned to a specific object but is shared by the combating
|
- A combat [command set](../Components/Command-Sets.md) with the relevant commands needed for combat, such as the various attack/defend options and the `flee/disengage` command to leave the combat mode.
|
||||||
characters and handles all the combat information. Since Scripts are database entities it also means
|
- A rule resolution system. The basics of making such a module is described in the [rule system tutorial](./Implementing-a-game-rule-system.md). We will only sketch such a module here for our end-turn combat resolution.
|
||||||
that the combat will not be affected by a server reload.
|
- An `attack` [command](../Components/Commands.md) for initiating the combat mode. This is added to the default command set. It will create the combat handler and add the character(s) to it. It will also assign the combat command set to the characters.
|
||||||
- A combat [command set](../Components/Command-Sets.md) with the relevant commands needed for combat, such as the
|
|
||||||
various attack/defend options and the `flee/disengage` command to leave the combat mode.
|
|
||||||
- A rule resolution system. The basics of making such a module is described in the [rule system
|
|
||||||
tutorial](./Implementing-a-game-rule-system.md). We will only sketch such a module here for our end-turn
|
|
||||||
combat resolution.
|
|
||||||
- An `attack` [command](../Components/Commands.md) for initiating the combat mode. This is added to the default
|
|
||||||
command set. It will create the combat handler and add the character(s) to it. It will also assign
|
|
||||||
the combat command set to the characters.
|
|
||||||
|
|
||||||
## The combat handler
|
## The combat handler
|
||||||
|
|
||||||
The _combat handler_ is implemented as a stand-alone [Script](../Components/Scripts.md). This Script is created when
|
The _combat handler_ is implemented as a stand-alone [Script](../Components/Scripts.md). This Script is created when the first Character decides to attack another and is deleted when no one is fighting any more. Each handler represents one instance of combat and one combat only. Each instance of combat can hold any number of characters but each character can only be part of one combat at a time (a player would
|
||||||
the first Character decides to attack another and is deleted when no one is fighting any more. Each
|
|
||||||
handler represents one instance of combat and one combat only. Each instance of combat can hold any
|
|
||||||
number of characters but each character can only be part of one combat at a time (a player would
|
|
||||||
need to disengage from the first combat before they could join another).
|
need to disengage from the first combat before they could join another).
|
||||||
|
|
||||||
The reason we don't store this Script "on" any specific character is because any character may leave
|
The reason we don't store this Script "on" any specific character is because any character may leave the combat at any time. Instead the script holds references to all characters involved in the combat. Vice-versa, all characters holds a back-reference to the current combat handler. While we don't use this very much here this might allow the combat commands on the characters to access and update the combat handler state directly.
|
||||||
the combat at any time. Instead the script holds references to all characters involved in the
|
|
||||||
combat. Vice-versa, all characters holds a back-reference to the current combat handler. While we
|
|
||||||
don't use this very much here this might allow the combat commands on the characters to access and
|
|
||||||
update the combat handler state directly.
|
|
||||||
|
|
||||||
_Note: Another way to implement a combat handler would be to use a normal Python object and handle
|
_Note: Another way to implement a combat handler would be to use a normal Python object and handle time-keeping with the [TickerHandler](../Components/TickerHandler.md). This would require either adding custom hook methods on the character or to implement a custom child of the TickerHandler class to track turns. Whereas the TickerHandler is easy to use, a Script offers more power in this case._
|
||||||
time-keeping with the [TickerHandler](../Components/TickerHandler.md). This would require either adding custom hook
|
|
||||||
methods on the character or to implement a custom child of the TickerHandler class to track turns.
|
|
||||||
Whereas the TickerHandler is easy to use, a Script offers more power in this case._
|
|
||||||
|
|
||||||
Here is a basic combat handler. Assuming our game folder is named `mygame`, we store it in
|
Here is a basic combat handler. Assuming our game folder is named `mygame`, we store it in
|
||||||
`mygame/typeclasses/combat_handler.py`:
|
`mygame/typeclasses/combat_handler.py`:
|
||||||
|
|
@ -267,14 +219,11 @@ is the use of the Script's standard `at_repeat` hook and the `force_repeat` meth
|
||||||
This allows for everything to go through the same mechanisms with minimal repetition of code.
|
This allows for everything to go through the same mechanisms with minimal repetition of code.
|
||||||
|
|
||||||
What is not present in this handler is a way for players to view the actions they set or to change
|
What is not present in this handler is a way for players to view the actions they set or to change
|
||||||
their actions once they have been added (but before the last one has added theirs). We leave this as
|
their actions once they have been added (but before the last one has added theirs). We leave this as an exercise.
|
||||||
an exercise.
|
|
||||||
|
|
||||||
## Combat commands
|
## Combat commands
|
||||||
|
|
||||||
Our combat commands - the commands that are to be available to us during the combat - are (in our
|
Our combat commands - the commands that are to be available to us during the combat - are (in our example) very simple. In a full implementation the commands available might be determined by the weapon(s) held by the player or by which skills they know.
|
||||||
example) very simple. In a full implementation the commands available might be determined by the
|
|
||||||
weapon(s) held by the player or by which skills they know.
|
|
||||||
|
|
||||||
We create them in `mygame/commands/combat.py`.
|
We create them in `mygame/commands/combat.py`.
|
||||||
|
|
||||||
|
|
@ -316,9 +265,7 @@ class CmdHit(Command):
|
||||||
self.caller.ndb.combat_handler.check_end_turn()
|
self.caller.ndb.combat_handler.check_end_turn()
|
||||||
```
|
```
|
||||||
|
|
||||||
The other commands `CmdParry`, `CmdFeint`, `CmdDefend` and `CmdDisengage` look basically the same.
|
The other commands `CmdParry`, `CmdFeint`, `CmdDefend` and `CmdDisengage` look basically the same. We should also add a custom `help` command to list all the available combat commands and what they do.
|
||||||
We should also add a custom `help` command to list all the available combat commands and what they
|
|
||||||
do.
|
|
||||||
|
|
||||||
We just need to put them all in a cmdset. We do this at the end of the same module:
|
We just need to put them all in a cmdset. We do this at the end of the same module:
|
||||||
|
|
||||||
|
|
@ -347,20 +294,11 @@ class CombatCmdSet(CmdSet):
|
||||||
|
|
||||||
## Rules module
|
## Rules module
|
||||||
|
|
||||||
A general way to implement a rule module is found in the [rule system tutorial](Implementing-a-game-
|
A general way to implement a rule module is found in the [rule system tutorial](Implementing-a-game- rule-system). Proper resolution would likely require us to change our Characters to store things like strength, weapon skills and so on. So for this example we will settle for a very simplistic rock-paper-scissors kind of setup with some randomness thrown in. We will not deal with damage here but just announce the results of each turn. In a real system the Character objects would hold stats to affect their skills, their chosen weapon affect the choices, they would be able to lose health etc.
|
||||||
rule-system). Proper resolution would likely require us to change our Characters to store things
|
|
||||||
like strength, weapon skills and so on. So for this example we will settle for a very simplistic
|
|
||||||
rock-paper-scissors kind of setup with some randomness thrown in. We will not deal with damage here
|
|
||||||
but just announce the results of each turn. In a real system the Character objects would hold stats
|
|
||||||
to affect their skills, their chosen weapon affect the choices, they would be able to lose health
|
|
||||||
etc.
|
|
||||||
|
|
||||||
Within each turn, there are "sub-turns", each consisting of one action per character. The actions
|
Within each turn, there are "sub-turns", each consisting of one action per character. The actions within each sub-turn happens simultaneously and only once they have all been resolved we move on to the next sub-turn (or end the full turn).
|
||||||
within each sub-turn happens simultaneously and only once they have all been resolved we move on to
|
|
||||||
the next sub-turn (or end the full turn).
|
|
||||||
|
|
||||||
*Note: In our simple example the sub-turns don't affect each other (except for `disengage/flee`),
|
*Note: In our simple example the sub-turns don't affect each other (except for `disengage/flee`), nor do any effects carry over between turns. The real power of a turn-based system would be to add
|
||||||
nor do any effects carry over between turns. The real power of a turn-based system would be to add
|
|
||||||
real tactical possibilities here though; For example if your hit got parried you could be out of
|
real tactical possibilities here though; For example if your hit got parried you could be out of
|
||||||
balance and your next action would be at a disadvantage. A successful feint would open up for a
|
balance and your next action would be at a disadvantage. A successful feint would open up for a
|
||||||
subsequent attack and so on ...*
|
subsequent attack and so on ...*
|
||||||
|
|
@ -371,8 +309,7 @@ Our rock-paper-scissor setup works like this:
|
||||||
- `parry` beats `hit`.
|
- `parry` beats `hit`.
|
||||||
- `feint` beats `parry` and is then counted as a `hit`.
|
- `feint` beats `parry` and is then counted as a `hit`.
|
||||||
- `defend` does nothing but has a chance to beat `hit`.
|
- `defend` does nothing but has a chance to beat `hit`.
|
||||||
- `flee/disengage` must succeed two times in a row (i.e. not beaten by a `hit` once during the
|
- `flee/disengage` must succeed two times in a row (i.e. not beaten by a `hit` once during the turn). If so the character leaves combat.
|
||||||
turn). If so the character leaves combat.
|
|
||||||
|
|
||||||
|
|
||||||
```python
|
```python
|
||||||
|
|
@ -455,16 +392,11 @@ def resolve_combat(combat_handler, actiondict):
|
||||||
combat_handler.remove_character(char)
|
combat_handler.remove_character(char)
|
||||||
```
|
```
|
||||||
|
|
||||||
To make it simple (and to save space), this example rule module actually resolves each interchange
|
To make it simple (and to save space), this example rule module actually resolves each interchange twice - first when it gets to each character and then again when handling the target. Also, since we use the combat handler's `msg_all` method here, the system will get pretty spammy. To clean it up, one could imagine tracking all the possible interactions to make sure each pair is only handled and reported once.
|
||||||
twice - first when it gets to each character and then again when handling the target. Also, since we
|
|
||||||
use the combat handler's `msg_all` method here, the system will get pretty spammy. To clean it up,
|
|
||||||
one could imagine tracking all the possible interactions to make sure each pair is only handled and
|
|
||||||
reported once.
|
|
||||||
|
|
||||||
## Combat initiator command
|
## Combat initiator command
|
||||||
|
|
||||||
This is the last component we need, a command to initiate combat. This will tie everything together.
|
This is the last component we need, a command to initiate combat. This will tie everything together. We store this with the other combat commands.
|
||||||
We store this with the other combat commands.
|
|
||||||
|
|
||||||
```python
|
```python
|
||||||
# mygame/commands/combat.py
|
# mygame/commands/combat.py
|
||||||
|
|
@ -506,16 +438,9 @@ class CmdAttack(Command):
|
||||||
target.msg(f"{self.caller} attacks you! You are in combat.")
|
target.msg(f"{self.caller} attacks you! You are in combat.")
|
||||||
```
|
```
|
||||||
|
|
||||||
The `attack` command will not go into the combat cmdset but rather into the default cmdset. See e.g.
|
The `attack` command will not go into the combat cmdset but rather into the default cmdset. See e.g. the [Adding Command Tutorial](Beginner-Tutorial/Part1/Beginner-Tutorial-Adding-Commands.md) if you are unsure about how to do this.
|
||||||
the [Adding Command Tutorial](Beginner-Tutorial/Part1/Beginner-Tutorial-Adding-Commands.md) if you are unsure about how to do this.
|
|
||||||
|
|
||||||
## Expanding the example
|
## Expanding the example
|
||||||
|
|
||||||
At this point you should have a simple but flexible turn-based combat system. We have taken several
|
At this point you should have a simple but flexible turn-based combat system. We have taken several shortcuts and simplifications in this example. The output to the players is likely too verbose during combat and too limited when it comes to informing about things surrounding it. Methods for changing your commands or list them, view who is in combat etc is likely needed - this will require play testing for each game and style. There is also currently no information displayed for other people happening to be in the same room as the combat - some less detailed information should probably be echoed to the room to
|
||||||
shortcuts and simplifications in this example. The output to the players is likely too verbose
|
|
||||||
during combat and too limited when it comes to informing about things surrounding it. Methods for
|
|
||||||
changing your commands or list them, view who is in combat etc is likely needed - this will require
|
|
||||||
play testing for each game and style. There is also currently no information displayed for other
|
|
||||||
people happening to be in the same room as the combat - some less detailed information should
|
|
||||||
probably be echoed to the room to
|
|
||||||
show others what's going on.
|
show others what's going on.
|
||||||
|
|
@ -1,10 +1,7 @@
|
||||||
# Licensing Q&A
|
# Licensing Q&A
|
||||||
|
|
||||||
|
|
||||||
Evennia is licensed under the very friendly [BSD](https://en.wikipedia.org/wiki/BSD_license)
|
Evennia is licensed under the very friendly [BSD](https://en.wikipedia.org/wiki/BSD_license) (3-clause) license. You can find the license as [LICENSE.txt](https://github.com/evennia/evennia/blob/master/LICENSE.txt) in the Evennia repository's root.
|
||||||
(3-clause) license. You can find the license as
|
|
||||||
[LICENSE.txt](https://github.com/evennia/evennia/blob/master/LICENSE.txt) in the Evennia
|
|
||||||
repository's root.
|
|
||||||
|
|
||||||
**Q: When creating a game using Evennia, what does the license permit me to do with it?**
|
**Q: When creating a game using Evennia, what does the license permit me to do with it?**
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -5,12 +5,7 @@
|
||||||
principle is simple - whenever a site is updated, a small text file is updated. An RSS reader can
|
principle is simple - whenever a site is updated, a small text file is updated. An RSS reader can
|
||||||
then regularly go online, check this file for updates and let the user know what's new.
|
then regularly go online, check this file for updates and let the user know what's new.
|
||||||
|
|
||||||
Evennia allows for connecting any number of RSS feeds to any number of in-game channels. Updates to
|
Evennia allows for connecting any number of RSS feeds to any number of in-game channels. Updates to the feed will be conveniently echoed to the channel. There are many potential uses for this: For example the MUD might use a separate website to host its forums. Through RSS, the players can then be notified when new posts are made. Another example is to let everyone know you updated your dev blog. Admins might also want to track the latest Evennia updates through our own RSS feed [here](https://code.google.com/feeds/p/evennia/updates/basic).
|
||||||
the feed will be conveniently echoed to the channel. There are many potential uses for this: For
|
|
||||||
example the MUD might use a separate website to host its forums. Through RSS, the players can then
|
|
||||||
be notified when new posts are made. Another example is to let everyone know you updated your dev
|
|
||||||
blog. Admins might also want to track the latest Evennia updates through our own RSS feed
|
|
||||||
[here](https://code.google.com/feeds/p/evennia/updates/basic).
|
|
||||||
|
|
||||||
## Configuring RSS
|
## Configuring RSS
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -22,7 +22,7 @@ If the upstream changes are large, you may also need to go into your gamedoor
|
||||||
|
|
||||||
This applies if you followed the [git-install instructions](./Installation-Git.md). Before Evennia 1.0, this was the only way to install Evennia.
|
This applies if you followed the [git-install instructions](./Installation-Git.md). Before Evennia 1.0, this was the only way to install Evennia.
|
||||||
|
|
||||||
At any time, development is either happening in the `master` branch (latest stable) or `develop` (experimental). Which one is active and 'latest' at a given time depends - after a release, `master` will see most updates, close to a new release, `develop` will usually be the fastest changing.
|
At any time, development is either happening in the `main` branch (latest stable) or `develop` (experimental). Which one is active and 'latest' at a given time depends - after a release, `main` will see most updates, close to a new release, `develop` will usually be the fastest changing.
|
||||||
|
|
||||||
1. Read the [changelog](../Coding/Changelog.md) to see what changed and if it means you need to make any changes to your game code.
|
1. Read the [changelog](../Coding/Changelog.md) to see what changed and if it means you need to make any changes to your game code.
|
||||||
2. If you use a [virtualenv](#Installation-Git#virtualenv), make sure it's active.
|
2. If you use a [virtualenv](#Installation-Git#virtualenv), make sure it's active.
|
||||||
|
|
@ -39,7 +39,7 @@ At any time, development is either happening in the `master` branch (latest stab
|
||||||
|
|
||||||
If you followed the [docker installation instructions] you need to pull the latest docker image for the branch you want:
|
If you followed the [docker installation instructions] you need to pull the latest docker image for the branch you want:
|
||||||
|
|
||||||
- `docker pull evennia/evennia` (master branch)
|
- `docker pull evennia/evennia` (`main` branch)
|
||||||
- `docker pull evennia/evennia:develop` (experimental `develop` branch)
|
- `docker pull evennia/evennia:develop` (experimental `develop` branch)
|
||||||
|
|
||||||
Then restart your containers.
|
Then restart your containers.
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue