Script:Files:script/misc/rules.script

From Mod Wiki
object rules {
    void            preinit();

    void            OnConnect( entity p );
    void            OnGameEnd();
    void            OnTimeLimitHit();

    entity            GetMaxXPInCategory( float category, boolean fromBase );
    entity            GetMinXPInCategory( float category, boolean fromBase );
    entity            GetBestStatEntry( handle statHandle );
    void            CalcAccuracy();
    void            CalcHighestLevel();

    void            WriteStats();

    void            PushStat( handle medalStat, entity p, float value );

    handle            medalHighXPStat;
    handle            medalLowXPStat;
    handle            medalSoldierStat;
    handle            medalMedicStat;
    handle            medalEngineerStat;
    handle            medalFieldOpsStat;
    handle            medalCovertOpsStat;
    handle            medalWeaponsStat;
    handle            medalBattleSenseStat;
    handle            medalVehicleStat;
    handle            medalHighAccuracyStat;
    handle            medalLowAccuracyStat;
    handle            medalRewardsStat;
    handle            medalKillsStat;
    handle            medalDamageStat;
    handle            medalTeamKillsStat;

    float            cachedResult;
}

void rules::preinit() {
    gameRules = self;

    medalHighXPStat            = sys.allocStatInt( "medal_high_xp" );
    medalLowXPStat            = sys.allocStatInt( "medal_low_xp" );
    medalSoldierStat        = sys.allocStatInt( "medal_soldier" );
    medalMedicStat            = sys.allocStatInt( "medal_medic" );
    medalEngineerStat        = sys.allocStatInt( "medal_engineer" );
    medalFieldOpsStat        = sys.allocStatInt( "medal_fieldops" );
    medalCovertOpsStat        = sys.allocStatInt( "medal_covertops" );
    medalWeaponsStat        = sys.allocStatInt( "medal_weapons" );
    medalBattleSenseStat    = sys.allocStatInt( "medal_battlesense" );
    medalVehicleStat        = sys.allocStatInt( "medal_vehicle" );
    medalHighAccuracyStat    = sys.allocStatInt( "medal_high_accuracy" );
    medalLowAccuracyStat    = sys.allocStatInt( "medal_low_accuracy" );
    medalRewardsStat        = sys.allocStatInt( "medal_rewards" );
    medalKillsStat            = sys.allocStatInt( "medal_kills" );
    medalDamageStat            = sys.allocStatInt( "medal_damage" );
    medalTeamKillsStat        = sys.allocStatInt( "medal_teamkills" );
}

void rules::OnConnect( entity p ) {
}

void rules::OnGameEnd() {
    WriteStats();
}

entity rules::GetBestStatEntry( handle statHandle ) {
    entity best;
    float bestValue = -1;

    float index;
    float maxClients = sys.getMaxClients();
    for ( index = 0; index < maxClients; index++ ) {
        entity p = sys.getClient( index );
        if ( p == $null_entity ) {
            continue;
        }

        float currentValue = sys.getStatValue( statHandle, index );
        if ( currentValue == 0.f ) {
            continue;
        }

        if ( currentValue > bestValue ) {
            bestValue = currentValue;
            best = p;
        }
    }

    cachedResult = bestValue;
    return best;
}

entity rules::GetMaxXPInCategory( float category, boolean fromBase ) {
    entity best;
    float bestValue = -1;

    float index;
    float maxClients = sys.getMaxClients();
    for ( index = 0; index < maxClients; index++ ) {
        entity p = sys.getClient( index );
        if ( p == $null_entity ) {
            continue;
        }

        float currentValue = p.getXP( category, fromBase );
        if ( currentValue == 0.f ) {
            continue;
        }

        if ( currentValue > bestValue ) {
            bestValue = currentValue;
            best = p;
        }
    }

    cachedResult = bestValue;
    return best;
}

entity rules::GetMinXPInCategory( float category, boolean fromBase ) {
    entity best;
    float bestValue = 999999999999.f;

    float index;
    float maxClients = sys.getMaxClients();
    for ( index = 0; index < maxClients; index++ ) {
        entity p = sys.getClient( index );
        if ( p == $null_entity ) {
            continue;
        }

        float currentValue = p.getXP( category, fromBase );
        if ( currentValue != 0.f && currentValue < bestValue ) {
            bestValue = currentValue;
            best = p;
        }
    }

    cachedResult = bestValue;
    return best;
}

void rules::CalcHighestLevel() {
    entity best;
    float bestValue = 0.f;

    float index;
    float maxClients = sys.getMaxClients();
    for ( index = 0; index < maxClients; index++ ) {
        entity p = sys.getClient( index );
        if ( p == $null_entity ) {
            continue;
        }

        float currentValue = 0.f;
        currentValue = currentValue + p.getProficiency( g_proficiencySoldier );
        currentValue = currentValue + p.getProficiency( g_proficiencyMedic );
        currentValue = currentValue + p.getProficiency( g_proficiencyEngineer );
        currentValue = currentValue + p.getProficiency( g_proficiencyFieldOps );
        currentValue = currentValue + p.getProficiency( g_proficiencyCovertOps );
        currentValue = currentValue + p.getProficiency( g_proficiencyLightWeapons );
        currentValue = currentValue + p.getProficiency( g_proficiencyBattleSense );
        currentValue = currentValue + p.getProficiency( g_proficiencyVehicle );

        if ( currentValue > bestValue ) {
            bestValue = currentValue;
            best = p;
        }
    }

    PushStat( medalRewardsStat, best, bestValue );
}

void rules::CalcAccuracy() {
    entity best;
    float bestValue = 0.f;

    entity worst;
    float worstValue = 999999999999.f;

    handle totalShotsFired = sys.allocStatInt( "total_shots_fired" );
    handle totalShotsHit = sys.allocStatInt( "total_shots_hit" );

    float index;
    float maxClients = sys.getMaxClients();
    for ( index = 0; index < maxClients; index++ ) {
        entity p = sys.getClient( index );
        if ( p == $null_entity ) {
            continue;
        }

        float shotsFired = sys.getStatValue( totalShotsFired, index );
        if ( shotsFired == 0.f ) {
            continue;
        }

        float accuracy = sys.getStatValue( totalShotsHit, index ) / shotsFired;
        if ( accuracy > bestValue ) {
            bestValue = accuracy;
            best = p;
        }

        if ( accuracy < worstValue ) {
            worstValue = accuracy;
            worst = p;
        }
    }    

    PushStat( medalHighAccuracyStat, best, bestValue * 100.f );
    PushStat( medalLowAccuracyStat, worst, worstValue * 100.f );
}

// these must be kept in the same order as the playerReward_e enum in sdNetManager.h
void rules::WriteStats() {
    PushStat( medalHighXPStat, GetMaxXPInCategory( -1, false ), cachedResult );
    PushStat( medalLowXPStat, GetMinXPInCategory( -1, false ), cachedResult );

    PushStat( medalSoldierStat, GetMaxXPInCategory( g_proficiencySoldier, true ), cachedResult );
    PushStat( medalMedicStat, GetMaxXPInCategory( g_proficiencyMedic, true ), cachedResult );
    PushStat( medalEngineerStat, GetMaxXPInCategory( g_proficiencyEngineer, true ), cachedResult );
    PushStat( medalFieldOpsStat, GetMaxXPInCategory( g_proficiencyFieldOps, true ), cachedResult );
    PushStat( medalCovertOpsStat, GetMaxXPInCategory( g_proficiencyCovertOps, true ), cachedResult );
    PushStat( medalWeaponsStat, GetMaxXPInCategory( g_proficiencyLightWeapons, true ), cachedResult );
    PushStat( medalBattleSenseStat, GetMaxXPInCategory( g_proficiencyBattleSense, true ), cachedResult );
    PushStat( medalVehicleStat, GetMaxXPInCategory( g_proficiencyVehicle, true ), cachedResult );

    CalcAccuracy();
    CalcHighestLevel();

    PushStat( medalKillsStat, GetBestStatEntry( sys.allocStatInt( "total_kills" ) ), cachedResult );
    PushStat( medalDamageStat, GetBestStatEntry( sys.allocStatInt( "total_damage" ) ), cachedResult );
    PushStat( medalTeamKillsStat, GetBestStatEntry( sys.allocStatInt( "total_team_kills" ) ), cachedResult );

    sys.sendEndGameStats();
}

void rules::OnTimeLimitHit() {
    objManager.OnTimeLimitHit();
}

void rules::PushStat( handle medalStat, entity p, float value ) {
    if ( p != $null_entity ) {
        sys.increaseStatInt( medalStat, p.getEntityNumber(), 1 );
    }
    sys.pushEndGameStat( p, value );
}