User:Irgendwer/Damage calculator

From Guild Wars Wiki
Jump to navigationJump to search

Implementations of the Guild Wars damage calculation.

damage.c[edit]

/*  damage.c

    A calculator for Guild Wars skill and attack damage. Based on the
    information at http://wiki.guildwars.com/wiki/Damage_calculation.
    
    Syntax is as follows.
    
    To calculate skill damage:
        damage s dmg [-l level] [-a armor] [-p ap]
            dmg:    the damage inflicted by the skill at the caster's
                    level in the relevant attribute.
            level:  the caster's level. Defaults to 20.
            armor:  the target's armor. Defaults to 60.
            ap:     the amount of armor penetration affecting the
                    skill. Defaults to 0.
                
    To calculate base attack damage:
        damage a min max mastery [-a armor] [-m mod] [-p ap]
            min:    the weapon's minimum base damage.
            max:    the weapon's maximum base damage.
            mastery:    the wielder's level in the relevant attribute.
            armor:  the target's armor. Defaults to 60.
            mod:    the percentage to which the weapon's damage is
                    modified. Defaults to 1.38 (i.e. customization
                    and +15% modifier).
            ap:     the amount of armor penetration affecting the
                    skill. Defaults to 0.
                        
    Armor-ignoring damage does not use these calculations as neither
    caster level nor armor affects it.

    Guild Wars is a trademark of NCsoft Corporation.

    Coded by Irgendwer 6/10.
*/

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>

void showSyntax();
void calcSkill( int argc, char * argv[] );
void calcAttack( int argc, char * argv[] );

int main( int argc, char * argv[] )
{
    if ( argc < 3 )
        showSyntax();
    else
    {    
        if ( !strcmp( argv[ 1 ], "s" ) )
            calcSkill( argc, argv );
        else if ( !strcmp( argv[ 1 ], "a" ) )
            calcAttack( argc, argv );
        else
            showSyntax();
    }

    return 0;
}

void calcSkill( int argc, char * argv[] )
{
    double dmg = atoi( argv[ 2 ] );
    double level = 20;
    double armor = 60;
    double ap = 0;
    
    int fail = dmg == 0;
    int i;
    
    for ( i = 3; i < argc && !fail; i++ )
    {
        char * arg = argv[ i ];
    
        if ( !strcmp( arg, "-l" ) ||
             !strcmp( arg, "-a" ) ||
             !strcmp( arg, "-p" ) )
        {
            if ( argc < i + 1 )
            {
                printf( "missing value after %s\n", arg );
                fail = 1;
            }
            else
            {
                if ( !strcmp( arg, "-l" ) )
                    level = atof( argv[ i + 1 ] );
                else if ( !strcmp( arg, "-a" ) )
                    armor = atof( argv[ i + 1 ] );
                else if ( !strcmp( arg, "-p" ) )
                    ap = atof( argv[ i + 1 ] );
                    
                i++;
            }
        }
        else
        {
            printf( "invalid flag: %s\n", arg );
            fail = 1;
        }
    }
    
    if ( !fail )
    {
        double result = dmg * pow( 2, ( 3 * level - 60 ) / 40 ) *
            pow( 2, ( 60 - ( 1 - ap ) * armor ) / 40 );
        printf( "%.1f\n", result );
    }
    else
        showSyntax();
}

void calcAttack( int argc, char * argv[] )
{
    double min = atoi( argv[ 2 ] );
    double max;
    int mastery;
    double armor = 60;
    double ap = 0;
    double mod = 1.38;
    
    int fail = min == 0;
    int i;

    if ( argc < 5 )
        fail = 1;
    else
    {
        max = atof( argv[ 3 ] );
        fail *= max == 0;
        
        mastery = atoi( argv[ 4 ] );
        fail *= mastery == 0;
    }
    
    for ( i = 5; i < argc && !fail; i++ )
    {
        char * arg = argv[ i ];
    
        if ( !strcmp( arg, "-m" ) ||
             !strcmp( arg, "-a" ) ||
             !strcmp( arg, "-p" ) )
        {
            if ( argc < i + 1 )
            {
                printf( "missing value after %s\n", arg );
                fail = 1;
            }
            else
            {
                if ( !strcmp( arg, "-m" ) )
                    mod = atof( argv[ i + 1 ] );
                else if ( !strcmp( arg, "-a" ) )
                    armor = atof( argv[ i + 1 ] );
                else if ( !strcmp( arg, "-p" ) )
                    ap = atof( argv[ i + 1 ] );
                    
                i++;
            }
        }
        else
        {
            printf( "invalid flag: %s\n", arg );
            fail = 1;
        }
    }
    
    if ( !fail )
    {
        double attr;
        
        if ( mastery <= 12 )
            attr = mastery * 5;
        else
            attr = 60 + ( mastery - 12 ) * 2;
            
        double result = mod * pow( 2, ( attr - 60 ) / 40 ) *
            pow( 2, ( 60 - ( 1 - ap ) * armor ) / 40 );
        printf( "min:  %.1f\n", min * result );
        printf( "max:  %.1f\n", max * result );
        printf( "crit: %.1f\n", max * result * sqrt( 2 ) );
    }
    else
        showSyntax();
        
}

void showSyntax()
{
    printf( "usage: damage s dmg [-l level] [-a armor] [-p ap]\n" );
    printf( "       damage a min max mastery [-a armor] [-m mod] [-p ap]\n" );
}

damage.html[edit]

<html>
    <head>
        <style type="text/css">
            table
            {
                font-family:arial;
                font-size:14px;
            }
        </style>
        <title>Damage calculator</title>
    </head>
    <body>
        <form>
            <table>
                <tbody>
                    <tr>
                        <th colspan="2">Attack damage</th>
                        <td style="width: 10%;"></td>
                        <th colspan="2">Skill damage</th>
                    </tr>
                    <tr>
                        <td>Min. damage:</td>
                        <td><input tabindex="1" id="attMinDmg" size="5" onchange="calcAttack()"></td>
                        <td></td>
                        <td>Damage:</td>
                        <td><input tabindex="10" id="skillDmg" size="5" onchange="calcSkill()"></td>
                    </tr>
                    <tr>
                        <td>Max. damage:</td>
                        <td><input tabindex="2" id="attMaxDmg" size="5" onchange="calcAttack()"></td>
                        <td></td>
                        <td>Caster level:</td>
                        <td><input tabindex="11" id="skillLevel" size="5" onchange="calcSkill()"></td>
                    </tr>
                    <tr>
                        <td>Attribute level:</td>
                        <td><input tabindex="3" id="attAttr" size="5" onchange="calcAttack()"></td>
                        <td></td>
                        <td></td>
                        <td></td>
                    </tr>
                    <tr>
                        <td>Modifier:</td>
                        <td><input tabindex="4" id="attMod" size="5" onchange="calcAttack()"></td>
                        <td></td>
                        <td></td>
                        <td></td>
                    </tr>
                    <tr>
                        <td>Target armor:</td>
                        <td><input tabindex="5" id="attArmor" size="5" onchange="calcAttack()"></td>
                        <td></td>
                        <td>Target armor:</td>
                        <td><input tabindex="12" id="skillArmor" size="5" onchange="calcSkill()"></td>
                    </tr>
                    <tr>
                        <td>Armor penetration:</td>
                        <td><input tabindex="6" id="attAP" size="5" onchange="calcAttack()"></td>
                        <td></td>
                        <td>Armor penetration:</td>
                        <td><input tabindex="13" id="skillAP" size="5" onchange="calcSkill()"></td>
                    </tr>
                    <tr>
                        <td colspan="5"><hr /></td>
                    </tr>
                    <tr>
                        <td>Min. damage:</td>
                        <td><input tabindex="7" id="attResultMin" size="5" readonly="readonly" type="text"></td>
                        <td></td>
                        <td>Damage:</td>
                        <td><input tabindex="14" id="skillResult" size="5" readonly="readonly" type="text"></td>
                    </tr>
                    <tr>
                        <td>Max. damage:</td>
                        <td><input tabindex="8" id="attResultMax" size="5" readonly="readonly" type="text"></td>
                        <td></td>
                        <td></td>
                        <td></td>
                    </tr>
                    <tr>
                        <td>Critical damage:</td>
                        <td><input tabindex="9" id="attResultCrit" size="5" readonly="readonly" type="text"></td>
                        <td></td>
                        <td></td>
                        <td></td>
                    </tr>
                </tbody>
            </table>
        </form>
        <script type="text/javascript">
            function calcAttack()
            {
                var max=document.getElementById('attMaxDmg').value;
                var min=document.getElementById('attMinDmg').value;
                var attr=document.getElementById('attAttr').value;
                var mod=document.getElementById('attMod').value;
                var armor=document.getElementById('attArmor').value;
                var ap=document.getElementById('attAP').value;
                
                
                var attr1;
                if (attr<=12)
                {
                    attr1=attr*5;
                }
                else
                {
                    attr1=60+(attr-12)*2;
                }
                
                var min1=Math.round(100*min*mod*Math.pow(2,(attr1-60)/40)*Math.pow(2,(60-(1-ap)*armor)/40))/100;
                var max1=Math.round(100*max*mod*Math.pow(2,(attr1-60)/40)*Math.pow(2,(60-(1-ap)*armor)/40))/100;
                var crit=Math.round(100*max1*Math.sqrt(2))/100;
                
                document.getElementById('attResultMin').value=min1;
                document.getElementById('attResultMax').value=max1;
                document.getElementById('attResultCrit').value=crit;
            }
            
            function calcSkill()
            {
                var dmg=document.getElementById('skillDmg').value;
                var lvl=document.getElementById('skillLevel').value;
                var armor=document.getElementById('skillArmor').value;
                var ap=document.getElementById('skillAP').value;
                
                var dmg1=Math.round(100*dmg*Math.pow(2,(3*lvl-60)/40)*Math.pow(2,(60-(1-ap)*armor)/40))/100;
                
                document.getElementById('skillResult').value=dmg1;
            }
        </script>
    </body>
</html>