まだこれを読んでいるかどうかはわかりませんが、この種の問題に長い間苦労しています。
私はさまざまな種類の影響システムを設計しました。ここで簡単に説明します。これはすべて私の経験に基づいています。私はすべての答えを知っていると主張していません。
静的修飾子
このタイプのシステムは、ほとんどの場合、変更を決定するために単純な整数に依存しています。たとえば、最大HP +100、攻撃+10などです。このシステムもパーセントを処理できます。スタックが制御不能にならないようにする必要があります。
このタイプのシステムで生成された値を実際にキャッシュしたことはありません。たとえば、何かの最大ヘルスを表示したい場合、その場で値を生成します。これにより、エラーが発生しにくくなり、関係者全員が理解しやすくなりました。
(私はJavaで作業しているため、以下はJavaベースですが、他の言語の一部の変更で機能するはずです)このシステムは、変更タイプの列挙を使用して、整数を使用して簡単に実行できます。最終結果は、キーと値の順序のペアを持つある種のコレクションに入れることができます。これは高速なルックアップと計算になるため、パフォーマンスは非常に良好です。
全体として、静的修飾子をフラット化するだけで非常にうまく機能します。ただし、修飾子を使用するには、getAttack、getMaxHP、getMeleeDamageなどの適切な場所にコードが存在する必要があります。
この方法が失敗するのは(私にとって)バフ間の非常に複雑な相互作用です。少しゲットーすることを除いて、相互作用をする本当の簡単な方法はありません。いくつかの単純な相互作用の可能性があります。そのためには、静的修飾子の格納方法を変更する必要があります。列挙型をキーとして使用する代わりに、文字列を使用します。この文字列は、Enum名+追加変数になります。10回のうち9回、余分な変数は使用されないため、列挙名をキーとして保持します。
簡単な例を見てみましょう:アンデッドクリーチャーに対するダメージを修正したい場合、次のような順序のペアを作成できます:(DAMAGE_Undead、10)DAMAGEはEnumであり、Undeadは追加の変数です。そのため、戦闘中に次のようなことができます。
dam += attacker.getMod(Mod.DAMAGE + npc.getRaceFamily()); //in this case the race family would be undead
とにかく、それはかなりうまく機能し、高速です。しかし、複雑な相互作用やどこにでも「特別な」コードがあると失敗します。たとえば、「死亡時にテレポートする確率が25%」という状況を考えてみましょう。これは「かなり」複雑なものです。上記のシステムはそれを処理できますが、次のものが必要なため、簡単ではありません。
- プレイヤーにこのmodがあるかどうかを確認します。
- どこかに、成功した場合、テレポーテーションを実行するためのコードがあります。このコードの場所はそれ自体が議論です!
- Modマップから適切なデータを取得します。値はどういう意味ですか?彼らもテレポートする部屋ですか?プレイヤーが2つのテレポートMODを持っている場合はどうなりますか?? 金額は加算されませんか?????? 失敗!
だから、これは私に私の次のものをもたらします:
究極のコンプレックスバフシステム
私はかつて自分で2D MMORPGを作成しようとしました。これはひどい間違いでしたが、私は多くを学びました!
影響システムを3回書き直しました。最初のものは、上記のそれほど強力ではないバリエーションを使用しました。2つ目は、私が話したいことです。
このシステムには、変更ごとに一連のクラスがあったため、ChangeHP、ChangeMaxHP、ChangeHPByPercent、ChangeMaxByPercentなどがあります。TeleportOnDeathのようなものでさえ、私にはこれらの人が何百万人もいました。
私のクラスには、次のことを行うものがありました。
- applyAffect
- removeAffect
- checkForInteraction <---重要
自身の説明を適用および削除します(パーセントなどの場合、影響はHPがどれだけ増加したかを追跡し、影響が消えるのを確実にしますが、追加した量のみを削除します。これはバグでした、笑、それが正しいことを確認するのに長い時間がかかった。それでも私はそれについて良い感じがしなかった。
checkForInteractionメソッドは、恐ろしく複雑なコードです。各影響(つまり:ChangeHP)クラスには、入力影響によってこれを変更する必要があるかどうかを判断するコードがあります。たとえば、次のようなものがあった場合...
- バフ1:攻撃時に10火炎ダメージを与える
- バフ2:すべての火炎ダメージが25%増加します。
- バフ3:すべての火炎ダメージが15増加します。
checkForInteractionメソッドは、これらすべての影響を処理します。これを行うには、近くにいるすべてのプレイヤーに対するそれぞれの影響をチェックする必要がありました!! これは、ある領域のスパンで複数のプレーヤーを扱った影響のタイプが原因です。これは、コードが上記のような特別なステートメントを決して持たないことを意味します-「私たちが死んだばかりなら、死亡時にテレポートを確認する必要があります」。このシステムは、適切なタイミングで自動的に正しく処理します。
このシステムを作成しようとすると、2か月ほどかかり、頭で数回爆発させました。しかし、それは非常に強力であり、非常に多くのことを行うことができます-特に私のゲームの能力について次の2つの事実を考慮すると:1.ターゲット範囲(つまり、シングル、セルフ、グループのみ、PB AEセルフ) 、PB AEターゲット、ターゲットAEなど)。2.能力は、複数の影響を与える可能性があります。
上で述べたように、これはこのゲームの3番目の影響システムの2番目でした。なぜ私はこれから離れたのですか?
このシステムは今まで見た中で最悪のパフォーマンスでした!進行中の各事柄について非常に多くのチェックを行わなければならなかったため、非常に遅くなりました。私はそれを改善しようとしましたが、失敗とみなしました。
そこで、3番目のバージョン(および別の種類のバフシステム)に進みます。
ハンドラーを含む複雑な影響クラス
したがって、これは最初の2つの組み合わせです。多くの機能と追加データを含むAffectクラスに静的変数を含めることができます。それから、何かをしたいときに、ハンドラー(私にとっては、特定のアクションのサブクラスではなく、いくつかの静的なユーティリティメソッドを呼び出します。
Affectクラスには、ターゲットタイプ、期間、使用回数、実行の機会など、ジューシーで優れたものがすべて含まれています。
状況に対処するために、たとえば死のテレポートなどの特別なコードを追加する必要があります。戦闘コードでこれを手動で確認する必要があり、存在する場合は影響のリストを取得します。このエフェクトのリストには、死亡時にテレポートするプレイヤーに現在適用されているすべてのエフェクトが含まれています。次に、それぞれを見て、実行されて成功したかどうかを確認します(最初に成功した時点で停止します)。成功したので、ハンドラーを呼び出して処理します。
必要に応じて、相互作用を行うことができます。プレーヤーなどで特定のバフを探すためのコードを記述する必要があります。優れたパフォーマンスを備えているため(以下を参照)、それを行うのはかなり効率的です。より複雑なハンドラーなどが必要になるだけです。
そのため、最初のシステムのパフォーマンスは非常に高く、2番目のシステムと同様に多くの複雑さがあります(ASほどではありません)。少なくともJavaでは、MOSTの場合の最初のほとんどのパフォーマンスを得るためにいくつかのトリッキーなことを行うことができます(つまり、enumマップ(http://docs.oracle.com/javase/6/docs/api/javaを持つ) /util/EnumMap.htmlキーとして、ArrayListを値として、これにより、すぐに影響があるかどうかを確認できます(リストが0になるか、マップにenumがないため)理由なしにプレイヤーの影響リストを継続的に繰り返します。現時点で必要な場合、影響を繰り返し処理してもかまいません。問題が生じた場合は後で最適化します)。
現在、2005年に終了したMUDを再開しました(元のFastROMコードベースの代わりにJavaでゲームを書き換えています)。最近、バフシステムをどのように実装したいのでしょうか。以前の失敗したゲームでうまく機能したため、このシステムを使用します。
うまくいけば、どこかで誰かがこれらの洞察のいくつかを役に立つと思うでしょう。