Crunchez vos adresses URL
|
Rejoignez notre discord
|
Hébergez vos photos
Affichage des résultats 1 à 15 sur 15
  1. #1
    Hello !

    Je développe un petit roguelike en mode texte et je cherche un peu d'aide pour la résolution des combats. Le jeu se veut simple au niveau des caractéristiques des monstres et du joueur. En gros voici ce qui va définir les acteurs du combat :

    Le nombre de point de vie de base est de 40.

    Attaquant
    Force : puissance de l'attaque (ex. valeur de base : 15)
    Arme : puissance de l'arme (ex. dommage de base : 5)
    Dextérité : détermine si l'attaque touche (ex. valeur de base : 10)


    Attaqué
    Défense : somme des points d'armure et autres items défensifs (ex. CA 12 et Amulette CA 3)
    Dextérité : détermine si l'attaque est esquivé (ex. valeur de base : 8)

    N'étant pas une grosse star en math, je peine à trouver une formule qui me donnerait le nombre de point de vie enlevé à l'attaqué de façon simple.

    Je pensais à :
    Code:
    Dégât = (Force * Arme) / Défense //qui me donnerait 5 dans mon exemple, pourquoi pas
    Mais je ne sais pas comment ajouter la notion de dextérité. Une petite idée ?

  2. #2
    ça dépend de comment tu veux gérer ta dex. Est-ce que ça touche systématiquement si dexAttaquant > dexAttaqué, ou est-ce un random pondéré par la dex des 2 acteurs ?

  3. #3
    Je sais pas trop en fait. Peut-être plus avec un random pondéré comme tu dis pour que ça soit moins prévisible.

    Je testerai bien les deux en fait

  4. #4
    Un grand classique : la table de résolution.

    Soit un nombre aléatoire x entre 0 et 1. On ajoute (dex1 - dex2) * 0.05
    * si x < 0.1, alors raté.
    * si x < 0.3, alors éraflure (dégâts réduits de moitié).
    * si x < 0.9, alors coup normal.
    * sinon critique (dégâts doublés).


    Exemples :
    Si j'ai 2 points de dex de plus que l'adversaire je ne peux pas manquer, j'ai toujours 20% d'éraflures et j'ai 20% de critiques.
    Si j'ai 6 points de plus que lui je n'ai pas d'éraflures et 40% de critiques.



    PS : la défense en dénominateur pose problème : dégâts infinis si 0 défense, dégâts divisés par deux en passant de 1 à 2 de défense. A la rigueur divise par (10 + déf). Ou fait de la défense une valeur soustractive (10 points de dégâts - 5 de défense = 5 points de dégâts).

    PPS : si tout ça te brûle les méninges, crée d'abord des exemples sous Excel (un par ligne), puis ensuite rentre tes formules. Tu peux éventuellement tester un jet par colonne.

    PPPS : avant de penser à une formule, pense d'abord à un exemple et au comportement que tu veux pour celui-ci. Quel résultat et comment doit-il évoluer si on double la défense ou a dex ?

  5. #5
    Au lieu de "15", peut-être que quelque chose comme "5d4" est plus intéressant ?
    Je n'aime pas les "raté", je préfère toujours toucher, quitte à faire peu de dégâts parfois.

    La dextérité peut intervenir sur le nombre de dès à jeter.
    * Jeux1d100 ? Le blog Jeux1d100.net sur les jeux indécents et Linux, et la chaîne YouTube *

  6. #6
    Merci pour vos réponses ! J'ai quelques pistes maintenant, je vais pouvoir faire quelques tests et revenir avec plus de questions

  7. #7
    Citation Envoyé par ( Tchey ) Voir le message
    Au lieu de "15", peut-être que quelque chose comme "5d4" est plus intéressant ?
    Je n'aime pas les "raté", je préfère toujours toucher, quitte à faire peu de dégâts parfois.

    La dextérité peut intervenir sur le nombre de dès à jeter.
    Enfait tu mettrais plus des valeurs de dé qu'une valeur fixe pour la force et la CA ? Genre pour connaître la force, on lance 5 dé de 4 ?

  8. #8
    Plutôt le fait de lancer 5d4 pour une force de 5. C'est le système white wolf, sauf qu'ils utilisent des d6. Le problème c'est qu'avec peu de dés tu as une très (trop) grande variabilité alors qu'avec beaucoup de dés tu ne t'éloignes jamais beaucoup de la moyenne.

  9. #9
    J'ai commencé à suivre ton système Roscopolo :

    Code:
    //récupération d'un nombre aléatoire entre 0 et 1
    float randfloat = TCODRandom::getInstance()->getFloat(0.0f, 1.0f);
    
    //coef à appliquer à la force de l'attaquant
    randfloat = randfloat + (pattDexterity - pdefDexterity) * 0.05f;
    		
    //dommage
    float damage = pattStrength * randfloat;
    Maintenant le truc c'est que je ne sais pas trop ajouter la puissance de l'arme et la défense du l'attaqué. Pour la défense, probablement par soustraction, ta remarque était pertinente sur la division.

  10. #10
    Pour la table de résolution en fait il faut plutôt que tu ajoutes un if / else if / else if / else pour tester la valeur de "randFloat" (que tu devrais renommer en attackScore). Comme dans le post que j'avais écrit (si x < 0.1, si ... , si ... , sinon ...).

    Au cours de cette étape tu détermineras "damageMultiplier" (0, 0.5, 1.0 ou 2.0).


    Puis tu calcules par exemple baseDamage = rand(minWeaponDamage, maxWeaponDamage) - défense de l'opposant.

    Enfin tu multiplies baseDamage par damangeMultiplier pour obtenir les dégâts finaux.


    Ou alors pour la défense tu peux en faire un multiplicateur. Si par exemple tu veux converger lentement vers une réduction de 90% des dommages, alors tu fais :
    defenseMultiplier = 0.1 + 0.9 / (1 + defense / C). Qui vaut 1 pour une défense nulle et converge vers 0.1, plus ou moins vite selon C.

  11. #11
    D'accord, il est mieux de prendre une valeur ronde du coup pour le attackScore ? Je pensais me passer du if/else en utilisant directement la valeur random générée.

    Tu n'utilises pas la notion de force du coup ?

    Mon RL n'aura pas de système d'xp et de niveaux. Les valeurs de la force / dex sont défini au départ et seront normalement fixe jusqu'à la fin de la partie.

  12. #12
    Citation Envoyé par Patate Voir le message
    Je pensais me passer du if/else en utilisant directement la valeur random générée.
    Ok, je pensais que c'était un quiproquo comme tu avais dit avoir repris mon système.

    Cela dit, pourquoi pas ? En revanche le système est alors moins lisible par le joueur : tu te retrouves avec une grande variabilité (dégâts variant de 1 à 25 pour une même attaque par exemple), il n'y a pas de mentions critique/éraflure pour expliquer rapidement au joueur ce qui se passe, et tu perds le plaisir associé à un critique opportun.

    Mais ces défauts peuvent être compensés (par exemple en ajoutant un indicateur visuel pour des dégâts élevés) et tout dépend de l'usage que tu fais de ces mécaniques.


    D'accord, il est mieux de prendre une valeur ronde du coup pour le attackScore ?
    C'est sans doute mieux, oui.

    Tu n'utilises pas la notion de force du coup ?
    J'avais oublié la force. On pourrait l'ajouter aux dommages de base.

  13. #13
    Voici le bout de code qui calcul tout ça :

    Code:
    float randFloat = TCODRandom::getInstance()->getFloat(0.0f, 1.0f);
    
    float damageMultiplier = 0.0f;
    
    if (randFloat > 0.0f && randFloat < 0.5f)
    	damageMultiplier = 0.0f;
    else if (randFloat >= 0.5f && randFloat < 1.0f)
    	damageMultiplier = 1.0f;
    else if (randFloat >= 1.0f && randFloat < 2.0f)
    	damageMultiplier = 2.0f;
    
    int baseDamage = TCODRandom::getInstance()->getInt(pattWeaponMinDamage, pattWeaponMaxDamage) + pattStrength - pdefDefense;
    
    return baseDamage * damageMultiplier;
    A tester, mais je dois finir un système avant de pouvoir le faire. Merci pour votre aide !

  14. #14
    Tu n'as pas repris les valeurs d'exemple auxquelles comparer ton float random, là avec ce code tu as une chance sur deux de ne faire aucun dégât, et une chance sur deux de faire les dégâts normaux ^^' Tu génères ton float random entre 0 et 1, puis tu le testes de 0 à 2 (il ne sera jamais entre 1 et 2, sauf à 1 pile, ce qui paraît peu probable).
    Egalement, mini optim : tu initialises ton multiplier à 0, donc pas la peine de retester le cas qui va le (re)mettre à 0. Du coup ça donnerait :

    Code:
    float randFloat = TCODRandom::getInstance()->getFloat(0.0f, 1.0f);
    
    float damageMultiplier = 0.0f;
    
    if (randFloat >= 0.1f && randFloat < 0.9f)
    	damageMultiplier = 1.0f;
    else if (randFloat >= 0.9f)
    	damageMultiplier = 2.0f;
    
    int baseDamage = TCODRandom::getInstance()->getInt(pattWeaponMinDamage, pattWeaponMaxDamage) + pattStrength - pdefDefense;
    
    return baseDamage * damageMultiplier;
    Après il faudra aussi faire des checks pour ne pas faire des dégâts négatifs (et donc soigner) dans le cas où la défense est très élevée !
    Je pense qu'il doit y avoir des moyens plus élégants d'introduire la force et la défense, avec ce système là, lorsqu'il y aura de grandes différences entre force et défense ça va donner des résultats un peu abusés (genre 0 damage systématique si le défenseur a une très grande défense, mais c'est peut-être ce que tu veux, après tout).

  15. #15
    Citation Envoyé par Grhyll Voir le message
    là avec ce code tu as une chance sur deux de ne faire aucun dégât, et une chance sur deux de faire les dégâts normaux ^^' Tu génères ton float random entre 0 et 1, puis tu le testes de 0 à 2 (il ne sera jamais entre 1 et 2, sauf à 1 pile, ce qui paraît peu probable).
    Je pense que les 50% de ratés et 0% de critiques de base sont voulus mais il manque effectivement la prise en compte de la DEX.

    genre 0 damage systématique si le défenseur a une très grande défense, mais c'est peut-être ce que tu veux, après tout
    Ça correspondrait au cas où tu attaquerais un type en armure avec une plume d'oie.

    Mais il est vrai que les valeurs des armures et des armes doivent être choisis très précautionneusement avec ce système.

    Et par ailleurs avec une plume d'oie je peux toujours viser les yeux. Un critique pourrait peut-être ignorer l'armure au lieu de doubler les dégâts (ou seulement en faire 50% de plus) ?

Règles de messages

  • Vous ne pouvez pas créer de nouvelles discussions
  • Vous ne pouvez pas envoyer des réponses
  • Vous ne pouvez pas envoyer des pièces jointes
  • Vous ne pouvez pas modifier vos messages
  •