/* Guesses how damage a shot might do. * \param psObj object that might be hit * \param damage amount of damage to deal * \param weaponClass the class of the weapon that deals the damage * \param weaponSubClass the subclass of the weapon that deals the damage * \param angle angle of impact (from the damage dealing projectile in relation to this object) * \return guess at amount of damage */ unsigned int objGuessFutureDamage(WEAPON_STATS *psStats, unsigned int player, BASE_OBJECT *psTarget, HIT_SIDE i) { unsigned int damage; int impactSide; int actualDamage, armour = 0, level = 1; if (psTarget == NULL) return 0; // Hard to destroy the ground. The armour on the mud is very strong and blocks all damage. damage = calcDamage(weaponDamage(psStats, player), psStats->weaponEffect, psTarget); // EMP cannons do no damage, if we are one return now if (psStats->weaponSubClass == WSC_EMP) { return 0; } // apply game difficulty setting damage = modifyForDifficultyLevel(damage, psTarget->player != selectedPlayer); for (impactSide = 0; impactSide != NUM_HIT_SIDES; ++impactSide) armour = MAX(armour, psTarget->armour[impactSide][psStats->weaponClass]); //debug(LOG_ATTACK, "objGuessFutureDamage(%d): body %d armour %d damage: %d", psObj->id, psObj->body, armour, damage); if (psTarget->type == OBJ_DROID) { DROID *psDroid = (DROID *)psTarget; // Retrieve highest, applicable, experience level level = getDroidEffectiveLevel(psDroid); } // Reduce damage taken by EXP_REDUCE_DAMAGE % for each experience level actualDamage = (damage * (100 - EXP_REDUCE_DAMAGE * level)) / 100; // You always do at least a third of the experience modified damage actualDamage = MAX(actualDamage - armour, actualDamage / 3); // And at least MIN_WEAPON_DAMAGE points actualDamage = MAX(actualDamage, MIN_WEAPON_DAMAGE); //objTrace(psObj->id, "objGuessFutureDamage: Would penetrate %d", actualDamage); return actualDamage; }
/** print out weapon information * \param psStats the weapon to print the info for */ static void printWeaponInfo(const WEAPON_STATS* psStats) { const char *pWC, *pWSC, *pMM; switch (psStats->weaponClass) { case WC_KINETIC: //bullets etc pWC = "WC_KINETIC"; break; //case WC_EXPLOSIVE: //rockets etc // pWC = "WC_EXPLOSIVE"; // break; case WC_HEAT: //laser etc pWC = "WC_HEAT"; break; //case WC_MISC: //others we haven't thought of! // pWC = "WC_MISC"; // break; default: pWC = "UNKNOWN CLASS"; break; } switch (psStats->weaponSubClass) { case WSC_MGUN: pWSC = "WSC_MGUN"; break; case WSC_CANNON: pWSC = "WSC_CANNON"; break; /*case WSC_ARTILLARY: pWSC = "WSC_ARTILLARY"; break;*/ case WSC_MORTARS: pWSC = "WSC_MORTARS"; break; case WSC_MISSILE: pWSC = "WSC_MISSILE"; break; case WSC_ROCKET: pWSC = "WSC_ROCKET"; break; case WSC_ENERGY: pWSC = "WSC_ENERGY"; break; case WSC_GAUSS: pWSC = "WSC_GAUSS"; break; case WSC_FLAME: pWSC = "WSC_FLAME"; break; /*case WSC_CLOSECOMBAT: pWSC = "WSC_CLOSECOMBAT"; break;*/ case WSC_HOWITZERS: pWSC = "WSC_HOWITZERS"; break; case WSC_ELECTRONIC: pWSC = "WSC_ELECTRONIC"; break; case WSC_AAGUN: pWSC = "WSC_AAGUN"; break; case WSC_SLOWMISSILE: pWSC = "WSC_SLOWMISSILE"; break; case WSC_SLOWROCKET: pWSC = "WSC_SLOWROCKET"; break; case WSC_LAS_SAT: pWSC = "WSC_LAS_SAT"; break; case WSC_BOMB: pWSC = "WSC_BOMB"; break; case WSC_COMMAND: pWSC = "WSC_COMMAND"; break; case WSC_EMP: pWSC = "WSC_EMP"; break; default: pWSC = "UNKNOWN SUB CLASS"; break; } switch (psStats->movementModel) { case MM_DIRECT: pMM = "MM_DIRECT"; break; case MM_INDIRECT: pMM = "MM_INDIRECT"; break; case MM_HOMINGDIRECT: pMM = "MM_HOMINGDIRECT"; break; case MM_HOMINGINDIRECT: pMM = "MM_HOMINGINDIRECT"; break; case MM_ERRATICDIRECT: pMM = "MM_ERRATICDIRECT"; break; case MM_SWEEP: pMM = "MM_SWEEP"; break; default: pMM = "UNKNOWN MOVE MODEL"; break; } CONPRINTF(ConsoleString,(ConsoleString,"Weapon: ")); printComponentInfo((COMPONENT_STATS *)psStats); CONPRINTF(ConsoleString,(ConsoleString," sRng %d lRng %d mRng %d %s\n" " sHt %d lHt %d pause %d dam %d\n", psStats->shortRange, proj_GetLongRange(psStats), psStats->minRange, proj_Direct(psStats) ? "direct" : "indirect", //psStats->shortHit, psStats->longHit, psStats->firePause, psStats->damage)); weaponShortHit(psStats,(UBYTE)selectedPlayer), weaponLongHit(psStats, (UBYTE)selectedPlayer), weaponFirePause(psStats,(UBYTE)selectedPlayer), weaponDamage(psStats, (UBYTE)selectedPlayer))); CONPRINTF(ConsoleString,(ConsoleString," rad %d radHt %d radDam %d\n" " inTime %d inDam %d inRad %d\n", psStats->radius, psStats->radiusHit, psStats->radiusDamage, psStats->incenTime, psStats->incenDamage, psStats->incenRadius)); CONPRINTF(ConsoleString,(ConsoleString," flSpd %d %s\n", psStats->flightSpeed, psStats->fireOnMove ? "fireOnMove" : "not fireOnMove")); CONPRINTF(ConsoleString,(ConsoleString," %s %s %s\n", pWC, pWSC, pMM)); CONPRINTF(ConsoleString,(ConsoleString," %srotate recoil %d\n" " dLife %d radLife %d\n", psStats->rotate ? "" : "not ", psStats->recoilValue, psStats->directLife, psStats->radiusLife)); }
/** print out weapon information * \param psStats the weapon to print the info for */ static void printWeaponInfo(const WEAPON_STATS *psStats) { const char *pWC, *pWSC, *pMM; switch (psStats->weaponClass) { case WC_KINETIC: //bullets etc pWC = "WC_KINETIC"; break; case WC_HEAT: //laser etc pWC = "WC_HEAT"; break; default: pWC = "UNKNOWN CLASS"; break; } switch (psStats->weaponSubClass) { case WSC_MGUN: pWSC = "WSC_MGUN"; break; case WSC_CANNON: pWSC = "WSC_CANNON"; break; case WSC_MORTARS: pWSC = "WSC_MORTARS"; break; case WSC_MISSILE: pWSC = "WSC_MISSILE"; break; case WSC_ROCKET: pWSC = "WSC_ROCKET"; break; case WSC_ENERGY: pWSC = "WSC_ENERGY"; break; case WSC_GAUSS: pWSC = "WSC_GAUSS"; break; case WSC_FLAME: pWSC = "WSC_FLAME"; break; case WSC_HOWITZERS: pWSC = "WSC_HOWITZERS"; break; case WSC_ELECTRONIC: pWSC = "WSC_ELECTRONIC"; break; case WSC_AAGUN: pWSC = "WSC_AAGUN"; break; case WSC_SLOWMISSILE: pWSC = "WSC_SLOWMISSILE"; break; case WSC_SLOWROCKET: pWSC = "WSC_SLOWROCKET"; break; case WSC_LAS_SAT: pWSC = "WSC_LAS_SAT"; break; case WSC_BOMB: pWSC = "WSC_BOMB"; break; case WSC_COMMAND: pWSC = "WSC_COMMAND"; break; case WSC_EMP: pWSC = "WSC_EMP"; break; default: pWSC = "UNKNOWN SUB CLASS"; break; } switch (psStats->movementModel) { case MM_DIRECT: pMM = "MM_DIRECT"; break; case MM_INDIRECT: pMM = "MM_INDIRECT"; break; case MM_HOMINGDIRECT: pMM = "MM_HOMINGDIRECT"; break; case MM_HOMINGINDIRECT: pMM = "MM_HOMINGINDIRECT"; break; default: pMM = "UNKNOWN MOVE MODEL"; break; } CONPRINTF(ConsoleString, (ConsoleString, "Weapon: ")); printComponentInfo((COMPONENT_STATS *)psStats); CONPRINTF(ConsoleString, (ConsoleString, " lRng %d mRng %d %s\n" " lHt %d pause %d dam %d\n", proj_GetLongRange(psStats, selectedPlayer), psStats->upgrade[selectedPlayer].minRange, proj_Direct(psStats) ? "direct" : "indirect", weaponLongHit(psStats, selectedPlayer), weaponFirePause(psStats, selectedPlayer), weaponDamage(psStats, selectedPlayer))); CONPRINTF(ConsoleString, (ConsoleString, " rad %d radDam %d\n" " inTime %d inDam %d inRad %d\n", psStats->upgrade[selectedPlayer].radius, psStats->upgrade[selectedPlayer].radiusDamage, psStats->upgrade[selectedPlayer].periodicalDamageTime, psStats->upgrade[selectedPlayer].periodicalDamage, psStats->upgrade[selectedPlayer].periodicalDamageRadius)); CONPRINTF(ConsoleString, (ConsoleString, " flSpd %d %s\n", psStats->flightSpeed, psStats->fireOnMove ? "fireOnMove" : "not fireOnMove")); CONPRINTF(ConsoleString, (ConsoleString, " %s %s %s\n", pWC, pWSC, pMM)); CONPRINTF(ConsoleString, (ConsoleString, " %srotate recoil %d\n" " radLife %d\n", psStats->rotate ? "" : "not ", psStats->recoilValue, psStats->radiusLife)); }