Skip to main content
added 339 characters in body
Source Link
mgibsonbr
  • 363
  • 3
  • 10

A different class (or addressable function) for each buff is not overkill if the behavior of those buffs is different from one another. One thing would be having +10% or +20% buffs (that, of course, would be better represented as two objects of the same class), other would be implementing wildly different effects that would require custom code anyway. However, I believe it's better to have standard ways of customizing the game logic instead of letting each buff do whatever it pleases (and possibliy interfering with each other in unforeseen ways, disturbing game balance).

I'd suggest dividing each "attack cycle" into steps, where each step has a base value, an ordered list of modifications that can be applied to that value (maybe capped), and a final cap. Each modification has an identity transformation as default, and can be influenced by zero or more buffs/debuffs. The specifics of each modification would depend on the step applied. How the cycle is implemented is up to you (including the option of an event-driven architecture, as you've been discussing).

  • calculate player agility (base + mods);
  • calculate opponent evade (base + mods);
  • do the difference (and apply mods) and determine if there was a hit;
  • calculate player attack (base + mods);
  • calculate opponent defense (base + mods);
  • do the difference (and apply mods) and determine the base damage;
  • calculate any parry/armor effects (mods on base damage) and apply damage;
  • calculate any recoil effect (mods on base damage) and apply to the attacker.

The distinction between "Modifications" and "Buffs" I mentioned earlier has a purpose: if you want to have some buffs that are an upgraded version of another onedecisions about rules and balance can be implemented on the former, you'd normally not want bothso any changes on those don't need to be applied atreflect in changes to every class of the same timelatter. SoOTOH, if your Modification is something like "add X% to the stat Y"numbers and you have 3 activekinds of buffs where X = (10,20,30)are only limited by your imagination, the modification can pick the maxsince each of them instead of adding them. If the 3rd one expires but the other ones are still active, the next cycle will stillcan express their desired behavior without having to take the 2nd into account. That's a possibility, adding and capping are another one, any possible interaction between them and you could have the two strategies at the same timeothers - one Modification for cumulative effects, other for effects that pick(or even the maxexistence of others at all).

I'd suggest dividing each "attack cycle" into steps, where each step has a base value, an ordered list of modifications that can be applied to that value (maybe capped), and a final cap. Each modification has an identity transformation as default, and can be influenced by zero or more buffs/debuffs. The specifics of each modification would depend on the step applied.

  • calculate player agility (base + mods);
  • calculate opponent evade (base + mods);
  • do the difference (and apply mods) and determine if there was a hit;
  • calculate player attack (base + mods);
  • calculate opponent defense (base + mods);
  • do the difference (and apply mods) and determine the base damage;
  • calculate any parry/armor effects (mods on base damage) and apply damage;
  • calculate any recoil effect (mods on base damage) and apply to the attacker.

The distinction between "Modifications" and "Buffs" I mentioned earlier has a purpose: if you want to have some buffs that are an upgraded version of another one, you'd normally not want both to be applied at the same time. So, if your Modification is something like "add X% to the stat Y" and you have 3 active buffs where X = (10,20,30), the modification can pick the max of them instead of adding them. If the 3rd one expires but the other ones are still active, the next cycle will still take the 2nd into account. That's a possibility, adding and capping are another one, and you could have the two strategies at the same time - one Modification for cumulative effects, other for effects that pick the max.

A different class (or addressable function) for each buff is not overkill if the behavior of those buffs is different from one another. One thing would be having +10% or +20% buffs (that, of course, would be better represented as two objects of the same class), other would be implementing wildly different effects that would require custom code anyway. However, I believe it's better to have standard ways of customizing the game logic instead of letting each buff do whatever it pleases (and possibliy interfering with each other in unforeseen ways, disturbing game balance).

I'd suggest dividing each "attack cycle" into steps, where each step has a base value, an ordered list of modifications that can be applied to that value (maybe capped), and a final cap. Each modification has an identity transformation as default, and can be influenced by zero or more buffs/debuffs. The specifics of each modification would depend on the step applied. How the cycle is implemented is up to you (including the option of an event-driven architecture, as you've been discussing).

  • calculate player attack (base + mods);
  • calculate opponent defense (base + mods);
  • do the difference (and apply mods) and determine the base damage;
  • calculate any parry/armor effects (mods on base damage) and apply damage;
  • calculate any recoil effect (mods on base damage) and apply to the attacker.

The distinction between "Modifications" and "Buffs" I mentioned earlier has a purpose: decisions about rules and balance can be implemented on the former, so any changes on those don't need to reflect in changes to every class of the latter. OTOH, the numbers and kinds of buffs are only limited by your imagination, since each of them can express their desired behavior without having to take into account any possible interaction between them and the others (or even the existence of others at all).

Source Link
mgibsonbr
  • 363
  • 3
  • 10

I'd suggest dividing each "attack cycle" into steps, where each step has a base value, an ordered list of modifications that can be applied to that value (maybe capped), and a final cap. Each modification has an identity transformation as default, and can be influenced by zero or more buffs/debuffs. The specifics of each modification would depend on the step applied.

One example of attack cycle could be:

  • calculate player agility (base + mods);
  • calculate opponent evade (base + mods);
  • do the difference (and apply mods) and determine if there was a hit;
  • calculate player attack (base + mods);
  • calculate opponent defense (base + mods);
  • do the difference (and apply mods) and determine the base damage;
  • calculate any parry/armor effects (mods on base damage) and apply damage;
  • calculate any recoil effect (mods on base damage) and apply to the attacker.

The important thing to note is that the earlier in the cycle a buff is applied the more effect it will have in the outcome. So, if you want a more "tactical" combat (where the player skill is more important than the character level) create many buffs/debuffs on the basic stats. If you want a more "balanced" combat (where the level matters more - important in MMOGs to limit rate of progress) only use buffs/debuffs later in the cycle.

The distinction between "Modifications" and "Buffs" I mentioned earlier has a purpose: if you want to have some buffs that are an upgraded version of another one, you'd normally not want both to be applied at the same time. So, if your Modification is something like "add X% to the stat Y" and you have 3 active buffs where X = (10,20,30), the modification can pick the max of them instead of adding them. If the 3rd one expires but the other ones are still active, the next cycle will still take the 2nd into account. That's a possibility, adding and capping are another one, and you could have the two strategies at the same time - one Modification for cumulative effects, other for effects that pick the max.

So, answering the question: don't create a class for each Buff, but one for each (type of) Modification, and tie the Modification to the attack cycle, not to the character. The buffs can be simply a list of (Modification,key,value) tuples, and you can apply a buff to a character by simply adding/removing it to the character's set of buffs. This also reduces the window for error, since the character's stats don't need to be changed at all when the buffs are applied (so there's less risk to restore a stat to the wrong value after a buff expires).