Ah, ok. So I'll give two possible ways to do this; first the in-command "head-on" way and then using cmdsets.
Head on way - command with ifs
This means simply that we create the command Bob and have it check if we are in the given time slot or not. Since presumably the Wolf race has unique features (code-wise) we assume it's created as a separate Python class (let's say its path is typeclasses.wolves.Wolf
). If Wolves were, say, just members of some biker gang (so human like other humans, code-wise) we could have instead just used a Tag to tag them as "Wolf" to identify them.
from evennia import Command
from evennia.utils import gametime
def check_full_moon():
return (gametime.gametime() * 3600 * 24) % 30 == 0
class CmdBob(Command):
key = "bob"
def func(self):
if self.caller.is_typeclass("typeclasses.characters.Wolf") and self.caller.check_full_moon():
else:
Next just add Bob to the Character Command set, which all characters start out having. Again, most of the code was already filled out by Evennia from the start, so one plugs in the command where indicated.
from commands import bob
class CharacterCmdSet(CmdSet):
def at_cmdset_creation(self):
self.add(bob.CmdBob())
After a @reload
the "bob" command is available and will behave differently for wolves. Now this is straight-forward and may well be enough for your needs. It has some maintenance problems though. Say you have other classes like Druid, Fae and Moon dragon that all have special things happen during a full moon. You now have to expand CmdBob
to account for all those. What if it's not just bob, but a whole slew of commands that should change like this? You would need to update them all. So far it's certainly doable. But then what happens if Wolves lose their special Bob when someone casts a spell or hits them with silver? You would then have to expand on your if statements. To be clear - this may well be ok for your game. But it may also be easy to forget to update a particular condition and the code could become hard to read and maintain.
CmdSet way
This will instead implement two versions of the Bob command, the normal one and the Wolf one.
from evennia import Command, CmdSet
class CmdBob(Command):
key = "bob"
def func(self):
class CmdBobWolf(Command):
key = "bob"
def func(self):
class CmdSetWolf(CmdSet):
def at_cmdset_creation(self):
self.add(CmdBobWolf())
Note that if CmdBobWolf
shared a lot of features with the normal CmdBob
we could have inherited from it and just replaced some things. We also create a new cmdset CmdSetWolf only holding this single command (for now). We add the normal CmdBob to the CharacterCmdSet as shown earlier.
Next we will use a Script to track time. A Script is a sort of virtual object that has no existence in-game. It can store data etc like an in-game object but also has an in-built timer.
from evennia import Script
from typeclasses.wolves import Wolf
from commands import bob
class MoonScript(Script):
key = "moonscript"
interval = 60 * 60
persistent = True
self.db.is_full_moon = False
def at_repeat(self):
if check_full_moon():
if not self.db.is_full_moon:
self.db.is_full_moon = True
for wolf in Wolf.objects.all():
wolf.cmdset.add(bob.CmdSetWolf)
elif self.db.is_full_moon:
self.db.is_full_moon = False
for wolf in Wolf.objects.all():
wolf.cmdset.remove(bob.CmdSetWolf)
So what the Script does is that it will check every hour if there is a full moon, and if so add the CmdSetWolf
to all wolves in the game. When the check fails it removes it again, restoring the default "bob" command. In a real game you will probably let your Weather or Calendar script do this job, alongside announcing to the world that the full moon has risen.
Using cmdsets rather than if statements in one command has the advantage of containment: You could store everything wolf-related in one place, in relative isolation from others. Sure, there may be details that still require some if checks but by replacing the entire command you could plug in the command in new situations without changing of the command code.
So if a Druid casts a spell on the Wolf, all you now need to do is to call wolf.cmdset.remove(bob.CmdSetWolf)
on the wolf to have it loose all its moon-given powers at once. Importantly, if the wolf meanwhile has sipped a magical potion having it gain the AwesomeFlyingCmdSet
(giving say the "fly" and "leap" commands), removing the CmdSetWolf
will only remove that cmdset. The normal "bob" command will be used but "fly" and "leap" will remain until the Druid uses their next spell ...
This also exposes a limit with the CommandSet system - you operate on Cmdsets, not on individual Commands (one Command could go into many different cmdsets). So if you have many commands in CmdSetWolf but only wanted to remove one of them, you'd be out of luck. For that level of precision you'd either have to fall back to doing if-checks in the command, use cmdsets with one Command each or overload the cmdset anew with the changed command structure.
.
Griatch