Justement, je pense que la question, c'est comment ils font pour traiter X données supplémentaires et Y conditions sur ces données à chaque instant pour chaque joueur, X et Y pouvant potentiellement être énormes.
Qu'un jeu soit "déjà complexe", certes, mais c'est orthogonal à la question. Les hauts faits sont gérés sur le serveur pour les jeux multijoueurs (ou pour les jeux mono-joueur en ligne… *tousse* Diablo 3 *tousse*)
C'est plus un problème indépendant du moteur de jeu utilisé, et j’avoue m'être posé la même question assez récemment. (Je n'ai pas encore creusé car ça ne m'a pas semblé impossible d'y répondre, mais je vais le faire ici

)
Le but (enfin, ce qu'on recherche à priori), c'est de pouvoir gérer un maximum de conditions potentiellement complexes de la manière la moins coûteuse possible.
On veut surtout éviter de dégrader les performances du jeu *avec succès* par rapport à la version du jeu *sans succès*.
Et on veut idéalement pouvoir ajouter de nouveaux succès au jeu sans devoir recorder entièrement le moteur physique. (Bon j'exagère, mais disons qu'on ne veut pas y toucher, sauf nécessité absolue)
Les implémentations possibles sont à priori variées (côté client, côté serveur, scripté dans une base de données, scripté en dur, etc.), donc on mettra aussi ça de côté.
Il faut bien concevoir que traiter 500+ conditions à chaque itération du moteur physique, même si ça resterait concevable (ou pas !) en local sur une machine, c'est exclu.
Pour que les choses se produisent de la manière la plus passive possible, il faut retarder la vérification de la condition au plus tard possible. (Au dernier moment, quand on a plus le choix)
Le meilleur moyen pour cela est de procéder de manière évènementielle. (Avec des déclencheurs)
Prenons pour exemple, ce succès
Folco (./1) :
à TF2, il y a une classe Soldat qui obtient un succès si, après un saut auto-propulsé (ie. rocket jump), il tue un adversaire dans les 5 secondes.
Ici, ce qui va déclencher le haut fait (la condition finale, en quelque sorte), c'est tuer un adversaire. (Admettons que tu ne puisses pas tuer tes alliés, comme ça c'est plus simple)
Tant que tu ne tues personnes il ne se passe absolument rien [vis à vis de ce haut fait]. De fait ça ne coûte rien niveau performances. (NB: À priori, "tuer" c'est un truc qui arrive "souvent, mais pas trop quand même", donc c'est idéal comme déclencheur de succès)
Par contre dès que tu tues un méchant, on va effectuer toutes les taches associées à "mort d'un adversaire".
Par exemple, incrémenter ton compteur de victimes. Et aussi, vérifier les succès associés.
Donc pour le succès en question, la condition "générique" suivante est "est-ce que cela s'est produit dans les 5 secondes après X", X étant "atterrissage après un rocket jump".
Cette condition, tu peux la vérifier de manière simple : Quand le joueur atterrit d'un rocket jump, tu stockes le timestamp du dernier atterrissage dans une variable cachée. spécifique au joueur, et interne au jeu.
De là, tu sais si le haut fait est accompli ou non.
Tu peux également optimiser le jeu en activant et désactivant les conditions de haut fait automatiquement pour que cela ne soit effectué que quand cela est nécessaire. (Par exemple, une fois le succès effectué, ce n'est plus la peine de vérifier à chaque fois. Les succès qui ne concernent qu'une classe de personnages n'ont pas besoin d'êtres vérifiés pour les autres, etc.)
Il reste toutefois une question, qui est de savoir comment on détermine l’atterrissage après un rocket jump.
Et bien, cela va se passer de la même manière que pour le haut fait. Un aterrisage quelconque, déclenchera une série de tâches lié à "aterrissage".
Comme par exemple, "stocker le timestamp du dernier atterrissage" (si jamais tu en as besoin pour autre chose), ou "si le dernier atterrissage fait suite à un rocket jump, stocker le timestamp dans la variable cachée adéquate".
Pour savoir si un atterrissage est la conséquence d'un rocket jump, c'est simple, il suffit juste de savoir si le dernier "décollage" provient d'un rocket jump ou pas (saut normal, chute, …).
Bref, tu vas probablement devoir gérer un autre évènement qui est "joueur n'est plus en contact avec le sol", qui stockera probablement un timestamp (si tu veux connaitre la durée du saut, de la chute, etc.) et la raison de ce décollage (rocket jump !).
Au final, le mécanisme de succès revient à stocker tout un tas (ça peut devenir assez énorme) de statistiques sur le jeu dont tu n'avais pas nécessairement besoin avant de gérer le mécanisme de succès. Une partie du travail doit nécessairement être *directement* effectuée par le moteur physique (détecter les évènements, retenir certaines valeurs, …), et une autre partie va se contenter de répondre aux évènements et de réagir en fonction des valeurs retenues, et pourra être totalement scriptée.
Par exemple, pour un haut fait "sauter 10 000 fois", tu auras juste besoin d'une statistique "nombre de sauts effectué (total)", qui sera mise à jour par le moteur de jeu lors de l'évènement "saut effectué", qui, permettra aussi de vérifier la condition du haut fait. (Est-ce que le nombre de sauts total est maintenant [supérieur ou] égal à 10 000)
Gérer des succès te force parfois à retenir énormément de statistiques sur un joueur/personnage, que ce soit de manière statique (données sauvegardées même après la déconnexion) ou de manière dynamique (succès "pendant une seule partie" ou "après que x se soit produit"…)
Ça a nécessairement un coût associé (pas forcément négligeable), mais ça n’impacte pas non plus excessivement les performances de jeu outre mesure, si tu fais attention. (NB: Gérer les évènements a un coût non nul…)
Comme je suis pas sur que ce que j'ai dit ait été très clair, voilà un espèce de pseudo script de comment les choses peuvent se passer.
[Moteur physique] Déclenche évènement [Toto]
[Script] Gère évènement [Toto]
[Script] [Toto] [Action 1] -> Stockage de [Toto.Timestamp] dans [Stat.TotoLastTimestamp], et incrémentation de [Stat.NombreToto]
[Script] [Toto] [Action 2] -> Vérification de la condition [Succès 1] : Si vraie, [Succès 1] réussi, désactiver [Action 2], exécuter [Action Succès 1]; Si faux, ne rien faire.
[Succès 1] = [Stat.TotoLastTimestamp] > 5000
[Action Succès 1] = Activer [Succès 2] (Après validation du succès 1, on a retiré le succès 1 de la liste des conditions à vérifier, et comme action de complétion, on demande d'activer Succès 2, qui est probablement la suite de Succès 1)