新增指令冷卻時間

> hit goblin with sword 
You strike goblin with the sword. It dodges! 
> hit goblin with sword 
You are off-balance and can't attack again yet.

某些型別的遊戲想要限制指令執行的頻率。如果一個 角色施展咒語 Firestorm,您可能不希望他們傳送垃圾郵件 一遍又一遍地指揮。在先進的戰鬥系統中,大幅度的擺動可能會 提供大量損壞的機會,但代價是無法重做 一會兒。

此類效果稱為「指令冷卻時間」。

本指南舉例說明瞭一種非常節省資源的冷卻方式。一個更多 「主動」方式是使用非同步延遲,如 Command-Duration howto 中建議的那樣。 如果您想在冷卻結束後向使用者回顯一些訊息,那麼將這兩個指南結合起來可能會很有用。

高效率的冷卻時間

這個想法是,當 Command 執行時,我們儲存它執行的時間。當它下次執行時,我們再次檢查當前時間。只有在自現在和上次執行以來經過了足夠的時間後,才允許執行該指令。這是一個非常有效率的實現,僅按需檢查。

# in, say, mygame/commands/spells.py

import time
from evennia import default_cmds

class CmdSpellFirestorm(default_cmds.MuxCommand):
    """
    Spell - Firestorm

    Usage:
      cast firestorm <target>

    This will unleash a storm of flame. You can only release one
    firestorm every five minutes (assuming you have the mana).
    """
    key = "cast firestorm"
    rate_of_fire = 60 * 2  # 2 minutes

    def func(self):
        "Implement the spell"

        now = time.time()
        last_cast = caller.db.firestorm_last_cast  # could be None
        if last_cast and (now - last_cast < self.rate_of_fire):
            message = "You cannot cast this spell again yet."
            self.caller.msg(message)
            return

        # [the spell effect is implemented]

        # if the spell was successfully cast, store the casting time
        self.caller.db.firestorm_last_cast = now

我們指定 rate_of_fire,然後檢查 caller. 上的 Attribute firestorm_last_cast 它是 None (因為該法術以前從未施展過)或表示該法術上次施展時間的時間戳。

非持續冷卻時間

上述實作將在重新載入後繼續存在。如果您不希望這樣,您可以改為讓 firestorm_last_cast 成為 NAtrribute。例如:

        last_cast = caller.ndb.firestorm_last_cast
        # ... 
        self.caller.ndb.firestorm_last_cast = now 

即,使用 .ndb 而不是 .db。由於 NAttributes 純粹位於記憶體中,因此它們的讀取和寫入速度比 Attribute 更快。因此,如果您的間隔很短並且需要經常改變,那麼這可能是更理想的選擇。缺點是如果伺服器重新載入,它們會重置。

建立一個冷卻感知指令父級

如果你有許多不同的法術或其他有冷卻時間的指令,你就不需要 想要每次都新增此程式碼。相反,你可以進行“冷卻” 指令 mixin”類別。mixin 是一個可以“新增”到另一個類別的類 (透過多重繼承)賦予它一些特殊的能力。這是一個例子 具有永續性儲存:

# in, for example, mygame/commands/mixins.py

import time

class CooldownCommandMixin:

    rate_of_fire = 60
    cooldown_storage_key = "last_used"
    cooldown_storage_category = "cmd_cooldowns"

    def check_cooldown(self):
        last_time = self.caller.attributes.get(
            key=self.cooldown_storage_key,
            category=self.cooldown_storage_category)
        )
        return (time.time() - last_time) < self.rate_of_fire

    def update_cooldown(self):
        self.caller.attribute.add(
            key=self.cooldown_storage_key,
            value=time.time(),
            category=self.cooldown_storage_category

        )

這意味著要混合到指令中,因此我們假設 self.caller 存在。 我們允許設定使用 Attribute 鍵/類別來儲存冷卻時間。

它還使用 Attribute-類別來確保它儲存的內容不會混淆 與呼叫者的其他屬性。

它的使用方法如下:

# in, say, mygame/commands/spells.py

from evennia import default_cmds
from .mixins import CooldownCommandMixin


class CmdSpellFirestorm(
        CooldownCommandMixin, default_cmds.MuxCommand):
    key = "cast firestorm"

    cooldown_storage_key = "firestorm_last_cast"
    rate_of_fire = 60 * 2

    def func(self):

        if not self.check_cooldown():
            self.caller.msg("You cannot cast this spell again yet.")
            return

        # [the spell effect happens]

        self.update_cooldown()

所以和以前一樣,我們剛剛隱藏了冷卻時間檢查,你可以 在所有冷卻時間中重複使用此 mixin。

指令交叉

這個冷卻檢查範例也適用於之間指令。例如, 你可以讓所有與火焰相關的法術儲存相同的冷卻時間 cooldown_storage_key(如fire_spell_last_used)。這意味著鑄造 火焰風暴會在一段時間內阻擋所有其他與火焰相關的法術。

同樣,當你揮出大劍時,其他型別的攻擊也可能會發生。 在您恢復餘額之前被封鎖。