Je ne sais pas si vous lisez encore cela, mais cela fait longtemps que je lutte avec ce type de problème.
J'ai conçu de nombreux types de systèmes affectifs. Je vais les passer brièvement en revue maintenant. Tout est basé sur mon expérience. Je ne prétends pas connaître toutes les réponses.
Modificateurs statiques
Ce type de système repose principalement sur des entiers simples pour déterminer les modifications éventuelles. Par exemple, +100 à Max HP, +10 à attaquer et ainsi de suite. Ce système pourrait également gérer des pourcentages. Vous devez juste vous assurer que l'empilement ne devient pas incontrôlable.
Je n'ai jamais vraiment mis en cache les valeurs générées pour ce type de système. Par exemple, si je voulais afficher le maximum de santé de quelque chose, je générerais la valeur sur place. Cela a empêché les choses d'être sujettes aux erreurs et tout simplement plus faciles à comprendre pour toutes les personnes impliquées.
(Je travaille en Java, donc ce qui suit est basé sur Java, mais il devrait fonctionner avec quelques modifications pour d’autres langages). Ce système peut facilement être installé en utilisant des énumérations pour les types de modification, puis des entiers. Le résultat final peut être placé dans une sorte de collection qui a des paires clé / valeur ordonnées. Ce sera une recherche rapide et des calculs, donc la performance est très bonne.
Globalement, cela fonctionne très bien avec des modificateurs statiques à plat. Toutefois, le code doit exister aux emplacements appropriés pour que les modificateurs soient utilisés: getAttack, getMaxHP, getMeleeDamage, etc., etc.
Lorsque cette méthode échoue (pour moi), il existe une interaction très complexe entre les buffs. Il n’ya pas de moyen facile d’interagir autrement qu’en ghettant un peu. Il y a quelques possibilités d'interaction simples. Pour ce faire, vous devez modifier la façon dont vous stockez les modificateurs statiques. Au lieu d'utiliser une énumération comme clé, vous utilisez une chaîne. Cette chaîne serait le nom Enum + variable supplémentaire. 9 fois sur 10, la variable supplémentaire n'est pas utilisée, vous conservez donc le nom enum comme clé.
Prenons un exemple rapide: si vous voulez pouvoir modifier les dégâts infligés aux créatures morts-vivants, vous pourriez avoir une paire ordonnée comme ceci: (DAMAGE_Undead, 10) Le DAMAGE est l’énum et le Mort-vivant est la variable supplémentaire. Donc, pendant votre combat, vous pouvez faire quelque chose comme:
dam += attacker.getMod(Mod.DAMAGE + npc.getRaceFamily()); //in this case the race family would be undead
Quoi qu'il en soit, cela fonctionne assez bien et est rapide. Mais cela échoue aux interactions complexes et à un code «spécial» partout. Par exemple, considérons la situation de «25% de chances de se téléporter à la mort». Ceci est un "assez" complexe. Le système ci-dessus peut le gérer, mais pas facilement, car vous avez besoin des éléments suivants:
- Déterminez si le joueur a ce mod.
- Quelque part, avoir un code pour exécuter la téléportation, si elle réussit. L'emplacement de ce code est une discussion en soi!
- Obtenez les bonnes données de la carte Mod. Que signifie la valeur? Est-ce la pièce où ils se téléportent aussi? Que faire si un joueur a deux mods de téléportation sur eux ?? Les montants ne seront-ils pas cumulés ?????? ÉCHEC!
Donc cela m'amène à mon prochain:
Le système ultime de buff complexe
Une fois, j'ai essayé d'écrire moi-même un MMORPG 2D. C'était une terrible erreur mais j'ai beaucoup appris!
J'ai réécrit le système affect 3 fois. Le premier utilisait une variante moins puissante de ce qui précède. Le second était ce que je vais parler.
Ce système avait une série de classes pour chaque modification. Des choses comme: ChangeHP, ChangeMaxHP, ChangeHPByPercent, ChangeMaxByPercent. J'ai eu un million de ces gars - même des choses comme TeleportOnDeath.
Mes cours avaient des choses qui feraient ce qui suit:
- applyAffect
- removeAffect
- checkForInteraction <--- important
Appliquer et supprimer expliquer eux-mêmes (bien que pour des pourcentages tels que, par exemple, l’effet garderait une trace de son augmentation de HP pour assurer que lorsque l’effet disparaîtrait, il ne supprime que le montant ajouté. Il m'a fallu beaucoup de temps pour m'assurer que tout allait bien. Je n'ai toujours pas eu un bon pressentiment à ce sujet.).
La méthode checkForInteraction était un morceau de code incroyablement complexe. Dans chacune des classes d’effets (c.-à-d. ChangeHP), il y aurait un code pour déterminer s’il doit être modifié par l’effet d’entrée. Donc, par exemple, si vous aviez quelque chose comme ...
- Buff 1: Inflige 10 points de dégâts de Feu en attaque.
- Buff 2: Augmente tous les dégâts de feu de 25%.
- Buff 3: Augmente tous les dégâts de feu de 15.
La méthode checkForInteraction traiterait tous ces effets. Pour ce faire, chacun des effets sur TOUS les joueurs à proximité devait être vérifié! En effet, le type d’effets que j’avais eu avec plusieurs joueurs sur une zone donnée. Cela signifie que le code N'A JAMAIS eu de déclaration spéciale comme ci-dessus - "si nous venons de mourir, nous devrions vérifier le téléport au décès". Ce système le traiterait automatiquement correctement au bon moment.
Essayer d'écrire ce système m'a pris environ deux mois et m'a fait exploser à plusieurs reprises. CEPENDANT, il était VRAIMENT puissant et pouvait faire une quantité incroyable de choses - en particulier si vous tenez compte des deux faits suivants pour les capacités de mon jeu: 1. Ils avaient des domaines cibles (c.-à-d. Unique, seul, groupe uniquement, PB AE). , Cible PB AE, AE ciblée, etc.). 2. Les capacités pourraient avoir plus d'un effet sur elles.
Comme je l'ai mentionné ci-dessus, il s'agissait du deuxième système de troisième affect pour ce jeu. Pourquoi je me suis éloigné de ça?
Ce système a eu la pire performance que j'ai jamais vue! C'était terriblement lent, car il devait faire beaucoup de vérifications pour chaque chose qui se passait. J'ai essayé de l'améliorer, mais j'ai considéré que c'était un échec.
Nous arrivons donc à ma troisième version (et à un autre type de système de buff):
Classe d'affect complexe avec gestionnaires
Il s’agit donc en fait d’une combinaison des deux premières: nous pouvons avoir des variables statiques dans une classe Affect contenant de nombreuses fonctionnalités et des données supplémentaires. Ensuite, il suffit d'appeler des gestionnaires (pour moi, des méthodes utilitaires statiques plutôt que des sous-classes pour des actions spécifiques. Mais je suis sûr que vous pouvez utiliser des sous-classes pour des actions si vous le souhaitez également) lorsque nous voulons faire quelque chose.
La classe Affect aurait toutes les bonnes choses juteuses, comme les types de cibles, la durée, le nombre d'utilisations, les chances d'exécution et ainsi de suite.
Il faudrait encore ajouter des codes spéciaux pour gérer les situations, par exemple, le téléport à la mort. Nous devrions toujours vérifier cela dans le code de combat manuellement, et si cela existait, nous aurions une liste des affects. Cette liste d’effets contient tous les effets actuellement appliqués sur le joueur qui s’est déjà téléporté à sa mort. Ensuite, nous examinerions chacun d’entre eux et vérifierions s’il s’exécutait et réussissait (nous nous arrêterions au premier essai réussi). Si cela réussissait, nous appelions simplement le gestionnaire pour s’occuper de cela.
L'interaction peut être faite, si vous voulez aussi. Il suffirait d’écrire le code pour rechercher des améliorations spécifiques sur les lecteurs / etc. Parce qu'il a de bonnes performances (voir ci-dessous), il devrait être assez efficace pour le faire. Il aurait simplement besoin de gestionnaires plus complexes, etc.
Donc, il a beaucoup de performances du premier système et toujours beaucoup de complexité comme le second (mais pas autant). Au moins en Java, vous pouvez faire certaines choses difficiles pour obtenir les performances de presque la première dans la plupart des cas (par exemple, avoir une carte enum ( http://docs.oracle.com/javase/6/docs/api/java). /util/EnumMap.html ) avec Enums comme clés et ArrayList des affects en tant que valeurs, ce qui vous permet de voir si vous avez rapidement des affects [puisque la liste serait 0 ou que la carte n'aurait pas l'énum] et ne pas avoir parcourir sans cesse les listes d’effets des joueurs sans aucune raison (cela ne me dérange pas d’itérer plus d’affect si nous en avons besoin à ce moment-là. J'optimiserai plus tard si cela devient un problème).
Je suis actuellement en train de ré-ouvrir (réécrire le jeu en Java au lieu du code de base FastROM dans lequel il se trouvait à l'origine) mon MUD qui s'est terminé en 2005 et j'ai récemment compris comment je veux implémenter mon système de buff. Je vais utiliser ce système car il a bien fonctionné dans mon jeu précédent échoué.
Espérons que quelqu'un, quelque part, trouvera certaines de ces idées utiles.