Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- Index: .project
- ===================================================================
- --- .project (revision 31069)
- +++ .project (working copy)
- @@ -6,6 +6,11 @@
- </projects>
- <buildSpec>
- <buildCommand>
- + <name>org.eclipse.cdt.managedbuilder.core.ScannerConfigBuilder</name>
- + <arguments>
- + </arguments>
- + </buildCommand>
- + <buildCommand>
- <name>org.eclipse.cdt.managedbuilder.core.genmakebuilder</name>
- <triggers>clean,full,incremental,</triggers>
- <arguments>
- @@ -63,11 +68,6 @@
- </dictionary>
- </arguments>
- </buildCommand>
- - <buildCommand>
- - <name>org.eclipse.cdt.managedbuilder.core.ScannerConfigBuilder</name>
- - <arguments>
- - </arguments>
- - </buildCommand>
- </buildSpec>
- <natures>
- <nature>org.eclipse.cdt.managedbuilder.core.ScannerConfigNature</nature>
- Index: src/game/g_local.h
- ===================================================================
- --- src/game/g_local.h (revision 31069)
- +++ src/game/g_local.h (working copy)
- @@ -44,6 +44,7 @@
- #define GAME_INCLUDE
- #include "game.h"
- +
- /** the "gameversion" client command will print this plus compile date */
- #define GAMEVERSION "baseufo"
- Index: src/game/g_combat.c
- ===================================================================
- --- src/game/g_combat.c (revision 31069)
- +++ src/game/g_combat.c (working copy)
- @@ -651,9 +651,11 @@
- VectorCopy(tr.endpos, newPos);
- /* calculate additional visibility */
- - for (i = 0; i < MAX_TEAMS; i++)
- - if (player->pers.team != level.activeTeam && G_TeamPointVis(i, newPos))
- - mask |= 1 << i;
- + if (!mock) {
- + for (i = 0; i < MAX_TEAMS; i++)
- + if (player->pers.team != level.activeTeam && G_TeamPointVis(i, newPos))
- + mask |= 1 << i;
- + }
- /* enough bouncing around or we have hit an actor */
- if (VectorLength(curV) < GRENADE_STOPSPEED || time > 4.0 || bounce > fd->bounce
- Index: src/game/g_ai.c
- ===================================================================
- --- src/game/g_ai.c (revision 31069)
- +++ src/game/g_ai.c (working copy)
- @@ -26,67 +26,185 @@
- #include "g_local.h"
- #include "g_ai.h"
- +
- +
- +
- +
- +#define LOOKUP_EPSILON 0.0001f
- +/* #define MOCK_ESTIMATION_ONLY uncomment for mock-shot ONLY dmg estimation (Warning: 5-min turns)*/
- +
- /**
- - * @brief Check whether friendly units are in the line of fire when shooting
- - * @param[in] ent AI that is trying to shoot
- - * @param[in] target Shoot to this location
- - * @param[in] spread
- + * @brief table for lookup_erf
- + * lookup[]= {erf(0), erf(0.1), ...}
- */
- -static qboolean AI_CheckFF (const edict_t * ent, const vec3_t target, float spread)
- -{
- - edict_t *check = NULL;
- - vec3_t dtarget, dcheck, back;
- - float cosSpread;
- +static const float lookup[30]= {
- + 0.0f, 0.1125f, 0.2227f, 0.3286f, 0.4284f, 0.5205f, 0.6039f,
- + 0.6778f, 0.7421f, 0.7969f, 0.8427f, 0.8802f, 0.9103f, 0.9340f,
- + 0.9523f, 0.9661f, 0.9763f, 0.9838f, 0.9891f, 0.9928f, 0.9953f,
- + 0.9970f, 0.9981f, 0.9989f, 0.9993f, 0.9996f, 0.9998f, 0.9999f,
- + 0.9999f, 1.0000f
- +};
- - /* spread data */
- - if (spread < 1.0)
- - spread = 1.0;
- - spread *= torad;
- - cosSpread = cos(spread);
- - VectorSubtract(target, ent->origin, dtarget);
- - VectorNormalize(dtarget);
- - VectorScale(dtarget, PLAYER_WIDTH / spread, back);
- +/**
- + * @brief table for lookup_erf
- + * lookup[]= {10*(erf(0.1)-erf(0.0)), 10*(erf(0.2)-erf(0.1)), ...}
- + */
- +static const float lookupdiff[30]= {
- + 1.1246f, 1.1024f, 1.0592f, 0.9977f, 0.9211f, 0.8336f, 0.7395f,
- + 0.6430f, 0.5481f, 0.4579f, 0.3750f, 0.3011f, 0.2369f, 0.1828f,
- + 0.1382f, 0.1024f, 0.0744f, 0.0530f, 0.0370f, 0.0253f, 0.0170f,
- + 0.0112f, 0.0072f, 0.0045f, 0.0028f, 0.0017f, 0.0010f, 0.0006f,
- + 0.0003f, 0.0002f
- +};
- - while ((check = G_EdictsGetNextLivingActorOfTeam(check, ent->team))) {
- - if (ent != check) {
- - /* found ally */
- - VectorSubtract(check->origin, ent->origin, dcheck);
- - if (DotProduct(dtarget, dcheck) > 0.0) {
- - /* ally in front of player */
- - VectorAdd(dcheck, back, dcheck);
- - VectorNormalize(dcheck);
- - if (DotProduct(dtarget, dcheck) > cosSpread)
- - return qtrue;
- - }
- - }
- - }
- +/**
- + * @brief calculate approximate erf, the error function
- + * http://en.wikipedia.org/wiki/Error_function
- + * uses lookup table and linear interpolation
- + * approximation good to around 0.001.
- + * easily good enough for the job.
- + * @param[in] z the number to calculate the erf of.
- + * @return for positive arg, returns approximate erf. for -ve arg returns 0.0f.
- + */
- +static float CL_LookupErrorFunction (float z)
- +{
- + float ifloat;
- + int iint;
- - /* no ally in danger */
- - return qfalse;
- + /* erf(-z)=-erf(z), but erf of -ve number should never be used here
- + * so return 0 here */
- + if (z < LOOKUP_EPSILON)
- + return 0.0f;
- + if (z > 2.8f)
- + return 1.0f;
- + ifloat = floor(z * 10.0f);
- + iint = (int)ifloat;
- + assert(iint < 30);
- + return lookup[iint] + (z - ifloat / 10.0f) * lookupdiff[iint];
- }
- /**
- - * @brief Check whether the fighter should perform the shoot
- - * @todo Check whether radius and power of fd are to to big for dist
- - * @todo Check whether the alien will die when shooting
- + * @brief Calculates chance to hit if the actor has a fire mode activated.
- + * @param[in] actor The local entity of the actor to calculate the hit probability for.
- + * @todo The hit probability should work somewhat differently for splash damage weapons.
- + * Since splash damage weapons can deal damage even when they don't directly hit an actor,
- + * the hit probability should be defined as the predicted percentage of the maximum splash
- + * damage of the firemode, assuming the projectile explodes at the desired location. This
- + * means that a percentage should be displayed for EVERY actor in the predicted blast
- + * radius. This will likely require specialized code.
- */
- -static qboolean AI_FighterCheckShoot (const edict_t* ent, const edict_t* check, const fireDef_t* fd, float *dist)
- +int AI_GetHitProbability (const edict_t * actor, const edict_t * check, const fireDef_t *fd, qboolean is_crouched)
- {
- - /* check range */
- - *dist = VectorDist(ent->origin, check->origin);
- - if (*dist > fd->range)
- - return qfalse;
- - /* don't shoot - we are to close */
- - else if (*dist < fd->splrad)
- - return qfalse;
- + vec3_t shooter, target;
- + float distance, pseudosin, width, height, acc, perpX, perpY, hitchance,
- + stdevupdown, stdevleftright, crouch, commonfactor;
- + int distx, disty, n;
- + //le_t *le;
- + const character_t *chr;
- + chr = &(actor->chr);
- + //pos3_t toPos;
- - /* check FF */
- - if (!G_IsInsane(ent) && AI_CheckFF(ent, check->origin, fd->spread[0]))
- - return qfalse;
- + //assert(actor);
- + //assert(actor->fd);
- - return qtrue;
- +
- + /** @todo use LE_FindRadius */
- + //le = LE_GetFromPos(toPos);
- + //if (!le)
- + // return 0;
- +
- + /* or suicide attempted */
- + //if (le->selected && !FIRESH_IsMedikit(le->fd))
- + // return 0;
- +
- +
- +
- + VectorCopy(actor->origin, shooter);
- + VectorCopy(check->origin, target);
- +
- + /* Calculate HitZone: */
- + distx = fabs(shooter[0] - target[0]);
- + disty = fabs(shooter[1] - target[1]);
- + distance = sqrt(distx * distx + disty * disty);
- + if (distx > disty)
- + pseudosin = distance / distx;
- + else
- + pseudosin = distance / disty;
- + width = 2 * PLAYER_WIDTH * pseudosin;
- + //height = LE_IsCrouched(le) ? PLAYER_CROUCHING_HEIGHT : PLAYER_STANDING_HEIGHT;
- + height = is_crouched ? PLAYER_CROUCHING_HEIGHT : PLAYER_STANDING_HEIGHT;
- +
- + //acc = GET_ACC(chr->score.skills[ABILITY_ACCURACY],
- + // actor->fd->weaponSkill ? chr->score.skills[actor->fd->weaponSkill] : 0);
- + acc = GET_ACC(chr->score.skills[ABILITY_ACCURACY],
- + fd->weaponSkill ? chr->score.skills[fd->weaponSkill] : 0);
- +
- + //crouch = (LE_IsCrouched(actor) && actor->fd->crouch) ? actor->fd->crouch : 1;
- + crouch = (is_crouched && fd->crouch) ? fd->crouch : 1;
- +
- + commonfactor = crouch * torad * distance * GET_INJURY_MULT(chr->score.skills[ABILITY_MIND], chr->HP, chr->maxHP);
- + stdevupdown = (fd->spread[0] * (WEAPON_BALANCE + SKILL_BALANCE * acc)) * commonfactor;
- + stdevleftright = (fd->spread[1] * (WEAPON_BALANCE + SKILL_BALANCE * acc)) * commonfactor;
- + hitchance = (stdevupdown > LOOKUP_EPSILON ? CL_LookupErrorFunction(height * 0.3536f / stdevupdown) : 1.0f)
- + * (stdevleftright > LOOKUP_EPSILON ? CL_LookupErrorFunction(width * 0.3536f / stdevleftright) : 1.0f);
- + /* 0.3536=sqrt(2)/4 */
- +
- + /* Calculate cover: */
- + n = 0;
- + height = height / 18;
- + width = width / 18;
- + target[2] -= UNIT_HEIGHT / 2;
- + target[2] += height * 9;
- + perpX = disty / distance * width;
- + perpY = 0 - distx / distance * width;
- +
- + target[0] += perpX;
- + perpX *= 2;
- + target[1] += perpY;
- + perpY *= 2;
- + target[2] += 6 * height;
- + if (!TR_TestLine(shooter, target, TL_FLAG_NONE))
- + n++;
- + target[0] += perpX;
- + target[1] += perpY;
- + target[2] -= 6 * height;
- + if (!TR_TestLine(shooter, target, TL_FLAG_NONE))
- + n++;
- + target[0] += perpX;
- + target[1] += perpY;
- + target[2] += 4 * height;
- + if (!TR_TestLine(shooter, target, TL_FLAG_NONE))
- + n++;
- + target[2] += 4 * height;
- + if (!TR_TestLine(shooter, target, TL_FLAG_NONE))
- + n++;
- + target[0] -= perpX * 3;
- + target[1] -= perpY * 3;
- + target[2] -= 12 * height;
- + if (!TR_TestLine(shooter, target, TL_FLAG_NONE))
- + n++;
- + target[0] -= perpX;
- + target[1] -= perpY;
- + target[2] += 6 * height;
- + if (!TR_TestLine(shooter, target, TL_FLAG_NONE))
- + n++;
- + target[0] -= perpX;
- + target[1] -= perpY;
- + target[2] -= 4 * height;
- + if (!TR_TestLine(shooter, target, TL_FLAG_NONE))
- + n++;
- + target[0] -= perpX;
- + target[1] -= perpY;
- + target[2] += 10 * height;
- + if (!TR_TestLine(shooter, target, TL_FLAG_NONE))
- + n++;
- +
- + return 100 * (hitchance * (0.125) * n);
- }
- +
- +
- +
- /**
- * @brief Checks whether the AI controlled actor wants to use a door
- * @param[in] ent The AI controlled actor
- @@ -179,6 +297,243 @@
- }
- /**
- + * @brief Estimate the damage of a shot (given firedef and shoottype) by making mock shots with G_ClientShoot. This function properly calculates for
- + * gravity & splash-based weapons while being the most accurate. This comes at a heavy processor cost though and should only be used where really needed
- + * @sa G_ClientShoot
- + * @param[in] ent_player the player who's actor will try to shoot
- + * @param[in] ent AI actor that is trying to shoot
- + * @param[in] The target we're shooting at
- + * @param[in] The shooting type we're using
- + * @param[in] The firedefinition index we're using
- + * @param[in] The firedef we're using. Redundant because of fdIdx and used only for minimizing sampled shots.
- + * @param[out] the damage expected from the shot
- + */
- +static int AI_CalculateDamageMock(const player_t * ent_player, edict_t * ent, const edict_t * check, shoot_types_t shootType, fireDefIndex_t fdIdx, const fireDef_t *fd) {
- + int mockShotDmg = 0;
- + int j;
- + const int samples = 10; /** Try to make only this many G_ShootSingle shots in order to keep CPU usage to a minimum */
- +
- + /* Sample 5 mock shots through the proper G_ClientShoot to see what kind of damage we can deal with our current settings */
- + /** @todo OPTIMIZE, we're really having a HUGE bite into the cpu over here */
- + /** @todo: is the z-align value of 0 correct? */
- + /** @todo: allow mock.allowSelf=1? */
- +
- + /** If the firedef is already shooting many times, divide by fd->shots so we get about 10 samples only */
- + const int iterations = ((int)(samples/fd->shots))?samples/fd->shots:1;
- +
- + /** Only aliens are pleased in damaging civilians */
- + const int shootCivilians = (ent->team == TEAM_ALIEN);
- + float civilianPenalty = 1.0f;
- +
- + for (j = 0; j < iterations; j++) {
- + shot_mock_t mock;
- + memset(&mock, 0, sizeof(mock));
- + if (G_ClientShoot(ent_player, ent, check->pos, shootType, fdIdx, &mock, qfalse, 0)) {
- + /* Add the total damage expected */
- + mockShotDmg += mock.damage;
- + /* Remove the fraction of the damage that is done to us/our team and civilians (if we're not aliens)*/
- + mockShotDmg -= ((mock.friendCount + mock.self) / (mock.enemyCount ? mock.enemyCount : 1)) * mock.damage;
- + civilianPenalty = shootCivilians? 1 : mock.civilian/(mock.enemyCount? mock.enemyCount : 1.0f);
- + mockShotDmg *= civilianPenalty;
- + }
- + }
- + mockShotDmg /= iterations;
- +
- + return mockShotDmg;
- +}
- +
- +/**
- + * @brief Estimate the damage of a series of shots (given a firedef) by estimating the hitchance and multiplying it with the expected avg damage (and shots)
- + * Since the tracings involved in the AI_GetHitProbability are minimal, the performance should be much superior to AI_CalculateDamageMock. The downsides are
- + * that it is very bad for calculating splash-damage&gravity based weapons while inheriting AI_GetHitProbability's hitchance calculation issues
- + * TODO: profiling to find out how fast this function is compared to AI_CalculateDamageMock
- + * TODO: take the shots out of this function
- + * @param[in] ent The actor that is trying to shoot
- + * @param[in] The target we're shooting at
- + * @param[in] The firedefinition we're using
- + * @param[in] The amount of shots we will take
- + * @param[out] the damage expected from the shot
- + */
- +int AI_CalculateDamageMath(edict_t * ent, const edict_t * check, const fireDef_t *fd, const int shots) {
- + const objDef_t *ad;
- +
- + int hitChance = AI_GetHitProbability(ent, check, fd, qfalse);
- + int hitdmg = (fd->damage[0] + fd->damage[1] / 2 + fd->spldmg[0]) * fd->shots * shots;
- +
- + if (CONTAINER(check, gi.csi->idArmour)) {
- + ad = CONTAINER(check, gi.csi->idArmour)->item.t;
- + hitdmg *= 1.0 - ad->protection[ad->dmgtype] * 0.01;
- + }
- +
- + return (hitdmg * hitChance / 100);
- +}
- +
- +/**
- + * @brief Check whether friendly units are in the line of fire when shooting
- + * @param[in] ent AI that is trying to shoot
- + * @param[in] target Shoot to this location
- + * @param[in] spread
- + */
- +static qboolean AI_CheckFF(const edict_t * ent, const vec3_t target, float spread) {
- + edict_t *check = NULL;
- + vec3_t dtarget, dcheck, back;
- + float cosSpread;
- +
- + /* spread data */
- + if (spread < 1.0)
- + spread = 1.0;
- + spread *= torad;
- + cosSpread = cos(spread);
- + VectorSubtract(target, ent->origin, dtarget);
- + VectorNormalize(dtarget);
- + VectorScale(dtarget, PLAYER_WIDTH / spread, back);
- +
- + while ((check = G_EdictsGetNextLivingActorOfTeam(check, ent->team))) {
- + if (ent != check) {
- + /* found ally */
- + VectorSubtract(check->origin, ent->origin, dcheck);
- + if (DotProduct(dtarget, dcheck) > 0.0) {
- + /* ally in front of player */
- + VectorAdd(dcheck, back, dcheck);
- + VectorNormalize(dcheck);
- + if (DotProduct(dtarget, dcheck) > cosSpread)
- + return qtrue;
- + }
- + }
- + }
- +
- + /* no ally in danger */
- + return qfalse;
- +}
- +
- +
- +/**
- + * @brief Basic checks whether the fighter should perform the shoot. Performance Cutoff for the heavier estimation functions
- + * @param[in] The edict of the actor taking the shot
- + * @param[in] The edict of the actor getting shot
- + * @param[in] The fireDefinition to check against
- + * @param[out] The distance between the actors' edicts. Kept for legacy support
- + * @param[out] Whether it's logical to consider shooting the target or not.
- + */
- +static qboolean AI_FighterCheckShoot(const edict_t* ent, const edict_t* check, const fireDef_t* fd, float *dist) {
- + /* check range */
- + *dist = VectorDist(ent->origin, check->origin);
- + if (*dist > fd->range)
- + return qfalse;
- + /* don't shoot - we are to close */
- + else if (*dist < fd->splrad)
- + return qfalse;
- +
- + /* check FF */
- + //@todo: I'm not convinced with the usage of AI_CheckFF. When the math-based calcs are in we can do better weighting of FF
- + if (!G_IsInsane(ent) && AI_CheckFF(ent, check->origin, fd->spread[0]))
- + return qfalse;
- +
- + return qtrue;
- +}
- +
- +/**
- + * @brief Find and estimate the best shot/hit we can deal to a target
- + * @sa G_ClientShoot
- + * @param[in] ent AI actor that is trying to shoot
- + * @param[in] the TU's the shooting actor can spend shooting
- + * @param[in] The target we're shooting at
- + * @param[out] aia used for returning the optimal shooting information. Overwries all relevant data
- + * @param[out] the damage expected from the optimal shot
- + */
- +float AI_GetDamagePotential (edict_t * ent, int tu, const edict_t * check, aiAction_t * aia)
- +{
- + shoot_types_t shootType;
- + float maxDmg = 0.0f;
- +
- + /* For each shootType */
- + for (shootType = ST_RIGHT; shootType < ST_NUM_SHOOT_TYPES; shootType++) {
- + fireDefIndex_t fdIdx;
- + const fireDef_t *fdArray;
- + const item_t *item = AI_GetItemForShootType(shootType, ent);
- + /* If we're checking for damage coming from another team */
- + const player_t * ent_player = (level.activeTeam != (G_PLAYER_FROM_ENT(ent))->pers.team) ? NULL : G_PLAYER_FROM_ENT(ent);
- +
- + /* Reaction fire and @todo grenade/knife-tossing from inventory return NULL */
- + if (!item)
- + continue;
- +
- + /** @todo: we never consider switching ammo type. We (probably) can't do this with mockshooting dmg estimation */
- + fdArray = FIRESH_FiredefForWeapon(item);
- + if (fdArray == NULL)
- + continue;
- +
- + /** @todo timed firedefs that bounce around should not be thrown/shoot about the whole distance */
- + /* foreach firedef */
- + for (fdIdx = 0; fdIdx < item->m->numFiredefs[fdArray->weapFdsIdx]; fdIdx++) {
- + const fireDef_t *fd = &fdArray[fdIdx];
- + /* how many shoots can this actor do */
- + const int shots = tu / fd->time;
- +
- + /* quickly check if the shot is worth considering */
- + float uselessFloat = 0.0f;
- + if (!AI_FighterCheckShoot(ent, check, fd, &uselessFloat)) {
- + continue;
- + }
- +
- + /* See if we can shoot & how much damage we're expected to deal */
- + if (shots) {
- + int mockTotalDamage = 0;
- +
- +#ifndef MOCK_ESTIMATION_ONLY
- + /* If we're using grav-affected or splash-dmg weapons, calculate expected dmg via mockshots, otherwise via maths */
- + /* mockshot-based is always better but really slow, so we use it only when required */
- + int testTotalDamage =0;
- +
- + if (fd->splrad > 0 || fd->gravity) {
- + mockTotalDamage += AI_CalculateDamageMock(ent_player, ent, check, shootType, fdIdx, fd) * shots;
- + //testTotalDamage = AI_CalculateDamageMath(ent, check, fd, shots);
- + } else {
- + mockTotalDamage = AI_CalculateDamageMath(ent, check, fd, shots);
- + //testTotalDamage = AI_CalculateDamageMock(ent_player, ent, check, shootType, fdIdx, allowCivilians) * shots;
- + }
- +#else
- + mockTotalDamage = AI_CalculateDamageMock(ent_player, ent, check, shootType, fdIdx, fd) * shots;
- +#endif
- + /** Do not take low-damage shots */
- + /** @todo bear in mind that the dmg is actually dmg*hitchance. This might affect weapons differently according to the firedef*/
- + /** @todo how about we also get the chance and use that aswell? dmg=10*100% is better than dmg1000*1%. That's how 2.3 AI thinks */
- + /** Also, the selection of dmg calculations (be it mock or math) may yield different results (if math only returns dmg to one target)*/
- + if (mockTotalDamage < 10){mockTotalDamage=0;}
- +
- + if (mockTotalDamage > maxDmg) {
- + maxDmg = mockTotalDamage;
- + if (aia != NULL) {
- + aia->shootType = shootType;
- + aia->shots = shots;
- + aia->target = G_EdictsGetByNum(check->number);
- + aia->fd = fd;
- + }
- + }
- + //}
- + /* START EXPERIMENTING WITH HIT PROBABILITIES */
- + //CL_GetHitProbability (edict_t actor, edict_t check, const fireDef_t *fd, qboolean is_crouched)
- + /*
- + int hitChance = AI_GetHitProbability(ent, check, fd, qfalse);
- + //int sampledHitChance = hits/shots_taken; //@TODO: this is debug-only
- + int hitdmg = (fd->damage[0] + fd->damage[1]/2 + fd->spldmg[0]) * fd->shots * shots;
- + if (CONTAINER(check, gi.csi->idArmour)) {
- + ad = CONTAINER(check, gi.csi->idArmour)->item.t;
- + hitdmg *= 1.0 - ad->protection[ad->dmgtype] * 0.01;
- + }
- + */
- + //int hitdmgscore = AI_CalculateDamageMath(ent, check, fd, shots);
- + //AI_GetHitProbability(ent, check, fd, qfalse); //FOR BREAKPOINT GOODNESS
- + /* START EXPERIMENTING WITH HIT PROBABILITIES */
- +
- + }
- + }
- + }
- +
- + return maxDmg;
- +}
- +
- +/**
- * @brief Checks whether the given alien should try to hide because there are enemies close
- * enough to shoot the alien.
- * @param[in] ent The alien edict that should (maybe) hide
- @@ -189,35 +544,38 @@
- /* only brave aliens are trying to stay on the field if no dangerous actor is visible */
- if (ent->morale > mor_brave->integer) {
- edict_t *from = NULL;
- + float hpExectedToLoose;
- + hpExectedToLoose = 0.0;
- /* test if check is visible */
- while ((from = G_EdictsGetNextLivingActor(from))) {
- + const invList_t *invlist;
- + const fireDef_t *fd;
- +
- if (from->team == ent->team)
- continue;
- if (G_IsCivilian(from))
- continue;
- - if (G_IsVisibleForTeam(from, ent->team)) {
- - const invList_t *invlist = RIGHT(from);
- - const fireDef_t *fd = NULL;
- - if (invlist && invlist->item.t) {
- + invlist = RIGHT(from);
- + fd = NULL;
- + if (invlist && invlist->item.t) {
- + fd = FIRESH_FiredefForWeapon(&invlist->item);
- + } else {
- + invlist = LEFT(from);
- + if (invlist && invlist->item.t)
- fd = FIRESH_FiredefForWeapon(&invlist->item);
- - } else {
- - invlist = LEFT(from);
- - if (invlist && invlist->item.t)
- - fd = FIRESH_FiredefForWeapon(&invlist->item);
- - }
- - /* search the (visible) inventory (by just checking the weapon in the hands of the enemy */
- - if (fd != NULL && fd->range * fd->range >= VectorDistSqr(ent->origin, from->origin)) {
- - const int damage = max(0, fd->damage[0] + (fd->damage[1] * crand()));
- - if (damage >= ent->HP / 3) {
- - const int hidingTeam = AI_GetHidingTeam(ent);
- - /* now check whether this enemy is visible for this alien */
- - if (G_Vis(hidingTeam, ent, from, VT_NOFRUSTUM))
- - return qtrue;
- - }
- - }
- }
- + /* search the (visible) inventory (by just checking the weapon in the hands of the enemy */
- + if (fd != NULL && fd->range * fd->range >= VectorDistSqr(ent->origin, from->origin)) {
- + /** @todo: we still need to consider the enemy getting in range if that's not the case */
- + const int damage = AI_GetDamagePotential(from, 30, ent, NULL);
- +
- + /* Add the damage he can dish out to our expected HP loss and check to see if we can take it */
- + hpExectedToLoose += damage;
- + if (hpExectedToLoose > (ent->HP * GUETE_DAMAGE_AVOID_FACTOR))
- + return qtrue;
- + }
- }
- return qfalse;
- }
- @@ -402,15 +760,16 @@
- return qfalse;
- }
- +#if 0
- /**
- - * @todo This feature causes the 'aliens shoot at walls'-bug.
- + * @todo This feature (partially) causes the 'aliens shoot at walls'-bug.
- * I considered adding a visibility check, but that wouldn't prevent aliens
- * from shooting at the breakable parts of their own ship.
- * So I disabled it for now. Duke, 23.10.09
- */
- static edict_t *AI_SearchDestroyableObject (const edict_t *ent, const fireDef_t *fd)
- {
- -#if 0
- +
- /* search best none human target */
- edict_t *check = NULL;
- float dist;
- @@ -431,7 +790,7 @@
- return check;
- }
- }
- -#endif
- +
- return NULL;
- }
- @@ -523,6 +882,7 @@
- }
- }
- }
- +#endif
- /**
- * @sa AI_ActorThink
- @@ -534,14 +894,14 @@
- edict_t *check = NULL;
- int tu;
- pos_t move;
- - shoot_types_t shootType;
- - float minDist;
- - float bestActionPoints, maxDmg;
- - int bestTime = -1;
- + float dist, minDist;
- + float bestActionPoints, maxDmg, bestTime = -1;
- move = gi.MoveLength(&level.pathingMap, to,
- G_IsCrouched(ent) ? 1 : 0, qtrue);
- - tu = ent->TU - move;
- + //tu = ent->TU - move;
- + //@todo: who's setting ent->chr.reservedTus.reaction to > 0? It's also not setting the firemode etc
- + tu = G_ActorUsableTUs(ent) - move;
- /* test for time */
- if (tu < 0 || move == ROUTING_NOT_REACHABLE)
- @@ -559,39 +919,49 @@
- /* search best target */
- while ((check = G_EdictsGetNextLivingActor(check))) {
- if (ent != check && (check->team != ent->team || G_IsInsane(ent))) {
- - /* don't shoot civilians in mp */
- + aiAction_t dmgAia;
- + float dmg = 0.0;
- +
- + /* don't shoot sane civilians in mp */
- if (G_IsCivilian(check) && sv_maxclients->integer > 1 && !G_IsInsane(ent))
- continue;
- - /* shooting */
- - maxDmg = 0.0;
- - for (shootType = ST_RIGHT; shootType < ST_NUM_SHOOT_TYPES; shootType++) {
- - const item_t *item;
- - const fireDef_t *fdArray;
- + dmg = AI_GetDamagePotential(ent, tu, check, &dmgAia);
- + /** Since dmg is chance*dmg, upper limit for dmg scoring is 2x check->HP. We use 2x as much so we're killing the target */
- + dmg = min(dmg,(check->HP)/2);
- - item = AI_GetItemForShootType(shootType, ent);
- - if (!item)
- - continue;
- + /* civilian malus */
- + if (G_IsCivilian(check) && !G_IsInsane(ent))
- + dmg *= GUETE_CIV_FACTOR;
- - fdArray = FIRESH_FiredefForWeapon(item);
- - if (fdArray == NULL)
- - continue;
- -
- - AI_SearchBestTarget(aia, ent, check, item, shootType, tu, &maxDmg, &bestTime, fdArray);
- + /* check if most damage can be done here */
- + if (dmg > maxDmg) {
- + maxDmg = dmg;
- + bestTime = dmgAia.fd->time * dmgAia.shots;
- + aia->shootType = dmgAia.shootType;
- + aia->shots = dmgAia.shots;
- + aia->target = check;
- + aia->fd = dmgAia.fd;
- }
- - } /* firedefs */
- + }
- }
- /* add damage to bestActionPoints */
- if (aia->target) {
- + assert(maxDmg > 0);
- bestActionPoints += maxDmg;
- assert(bestTime > 0);
- tu -= bestTime;
- + if (tu<0){
- + Com_DPrintf(DEBUG_GAME,"AI: AI_FighterCalcBestAction actor %s is trying to use more TU's than he has. After shooting he has %d tu's", (ent->chr).name, tu);
- + }
- }
- if (!G_IsRaged(ent)) {
- const int hidingTeam = AI_GetHidingTeam(ent);
- /* hide */
- - if (!AI_HideNeeded(ent) || !(G_TestVis(hidingTeam, ent, VT_PERISH | VT_NOFRUSTUM) & VIS_YES)) {
- + /** @todo: don't hide from the unit we're about to kill */
- + //if (!AI_HideNeeded(ent) || !(G_TestVis(hidingTeam, ent, VT_PERISH | VT_NOFRUSTUM) & VIS_YES)) {
- + if (!(G_TestVis(hidingTeam, ent, VT_PERISH | VT_NOFRUSTUM) & VIS_YES) && !AI_HideNeeded(ent)) {
- /* is a hiding spot */
- bestActionPoints += GUETE_HIDE + (aia->target ? GUETE_CLOSE_IN : 0);
- } else if (aia->target && tu >= TU_MOVE_STRAIGHT) {
- @@ -623,8 +993,9 @@
- check = NULL;
- while ((check = G_EdictsGetNextLivingActor(check))) {
- if (check->team != ent->team) {
- - const float dist = VectorDist(ent->origin, check->origin);
- - minDist = min(dist, minDist);
- + dist = VectorDist(ent->origin, check->origin);
- + if (dist < minDist)
- + minDist = dist;
- }
- }
- bestActionPoints += GUETE_CLOSE_IN * (1.0 - minDist / CLOSE_IN_DIST);
- @@ -659,7 +1030,9 @@
- G_EdictSetOrigin(ent, to);
- move = gi.MoveLength(&level.pathingMap, to, crouchingState, qtrue);
- - tu = ent->TU - move;
- + //tu = ent->TU - move;
- + //@todo: who's setting ent->chr.reservedTus.reaction to > 0? It's also not setting the firemode etc
- + tu = G_ActorUsableTUs(ent) - move;
- /* test for time */
- if (tu < 0 || move == ROUTING_NOT_REACHABLE)
- @@ -835,12 +1208,12 @@
- const byte crouchingState = G_IsCrouched(ent) ? 1 : 0;
- /* calculate move table */
- - G_MoveCalc(0, ent, ent->pos, crouchingState, ent->TU);
- + G_MoveCalc(0, ent, ent->pos, crouchingState,G_ActorUsableTUs(ent));
- Com_DPrintf(DEBUG_ENGINE, "AI_PrepBestAction: Called MoveMark.\n");
- gi.MoveStore(&level.pathingMap);
- /* set borders */
- - dist = (ent->TU + 1) / 2;
- + dist = (G_ActorUsableTUs(ent) + 1) / 2;
- xl = max((int) ent->pos[0] - dist, 0);
- yl = max((int) ent->pos[1] - dist, 0);
- xh = min((int) ent->pos[0] + dist, PATHFINDING_WIDTH);
- @@ -857,7 +1230,7 @@
- for (to[1] = yl; to[1] < yh; to[1]++)
- for (to[0] = xl; to[0] < xh; to[0]++) {
- const pos_t move = gi.MoveLength(&level.pathingMap, to, crouchingState, qtrue);
- - if (move != ROUTING_NOT_REACHABLE && move <= ent->TU) {
- + if (move != ROUTING_NOT_REACHABLE && move <= G_ActorUsableTUs(ent)) {
- if (G_IsCivilian(ent) || G_IsPaniced(ent))
- bestActionPoints = AI_CivilianCalcBestAction(ent, to, &aia);
- else
- @@ -873,6 +1246,11 @@
- VectorCopy(oldPos, ent->pos);
- VectorCopy(oldOrigin, ent->origin);
- + Com_DPrintf(DEBUG_COMMANDS,"%s decides to move to %d-%d and shoot at %s then move to %d-%d", (ent->chr).name, bestAia.to[0],bestAia.to[1], (bestAia.target)?((bestAia.target)->chr).name:"none\0", bestAia.stop[0],bestAia.stop[1]);
- + if (G_ActorUsableTUs(ent) < bestActionPoints){
- + Com_DPrintf(DEBUG_COMMANDS,"Actor %s will try to use %f AP's while he has only %d",(ent->chr).name, bestActionPoints, G_ActorUsableTUs(ent));
- + }
- +
- bestActionPoints = AI_CheckForMissionTargets(player, ent, &aia);
- if (bestActionPoints > best) {
- bestAia = aia;
- @@ -929,7 +1307,8 @@
- int dv;
- const byte crouchingState = G_IsCrouched(ent) ? 1 : 0;
- - G_MoveCalc(ent->team, ent, pos, crouchingState, ent->TU);
- + //G_MoveCalc(ent->team, ent, pos, crouchingState, ent->TU);
- + G_MoveCalc(ent->team, ent, pos, crouchingState, G_ActorUsableTUs(ent));
- dv = gi.MoveNext(&level.pathingMap, pos, crouchingState);
- if (dv != ROUTING_UNREACHABLE) {
- @@ -980,6 +1359,7 @@
- bestAia = AI_PrepBestAction(player, ent);
- +
- /* shoot and hide */
- if (bestAia.target) {
- const fireDefIndex_t fdIdx = bestAia.fd ? bestAia.fd->fdIdx : 0;
- @@ -994,6 +1374,7 @@
- if (G_IsDead(bestAia.target)) {
- /* search another target now */
- bestAia = AI_PrepBestAction(player, ent);
- + Com_DPrintf(DEBUG_GAME,"%s overshot and now decides to move to %d-%d and shoot at %s and move to %d-%d", (ent->chr).name, bestAia.to[0],bestAia.to[1], (bestAia.target->chr).name, bestAia.stop[0],bestAia.stop[1]);
- /* no other target found - so no need to hide */
- if (!bestAia.target)
- return;
- @@ -1044,7 +1425,8 @@
- edict_t *ent = player->pers.last;
- while ((ent = G_EdictsGetNextLivingActorOfTeam(ent, player->pers.team))) {
- - if (ent->TU) {
- + //if (ent->TU) {
- + if (G_ActorUsableTUs(ent)) {
- if (g_ailua->integer)
- AIL_ActorThink(player, ent);
- else
- Index: src/game/g_ai.h
- ===================================================================
- --- src/game/g_ai.h (revision 31069)
- +++ src/game/g_ai.h (working copy)
- @@ -36,13 +36,14 @@
- int z_align; /**< the z-align for every shoot */
- } aiAction_t;
- -#define GUETE_HIDE 60
- +#define GUETE_HIDE 30
- #define GUETE_CLOSE_IN 20
- #define GUETE_KILL 30
- #define GUETE_RANDOM 10
- #define GUETE_REACTION_ERADICATION 30
- #define GUETE_REACTION_FEAR_FACTOR 20
- -#define GUETE_CIV_FACTOR 0.25
- +#define GUETE_CIV_FACTOR 0.2
- +#define GUETE_DAMAGE_AVOID_FACTOR 0.4
- #define GUETE_CIV_RANDOM 10
- #define GUETE_RUN_AWAY 50
- Index: build/projects/ufo.launch
- ===================================================================
- --- build/projects/ufo.launch (revision 31069)
- +++ build/projects/ufo.launch (working copy)
- @@ -6,9 +6,12 @@
- <stringAttribute key="org.eclipse.cdt.debug.mi.core.GDB_INIT" value=".gdbinit"/>
- <listAttribute key="org.eclipse.cdt.debug.mi.core.SOLIB_PATH"/>
- <booleanAttribute key="org.eclipse.cdt.debug.mi.core.STOP_ON_SOLIB_EVENTS" value="false"/>
- +<booleanAttribute key="org.eclipse.cdt.debug.mi.core.breakpointsFullPath" value="false"/>
- +<stringAttribute key="org.eclipse.cdt.debug.mi.core.commandFactory" value="org.eclipse.cdt.debug.mi.core.standardLinuxCommandFactory"/>
- <stringAttribute key="org.eclipse.cdt.debug.mi.core.protocol" value="mi"/>
- +<booleanAttribute key="org.eclipse.cdt.debug.mi.core.verboseMode" value="false"/>
- <stringAttribute key="org.eclipse.cdt.launch.COREFILE_PATH" value=""/>
- -<stringAttribute key="org.eclipse.cdt.launch.DEBUGGER_ID" value="org.eclipse.cdt.debug.mi.core.CDebugger"/>
- +<stringAttribute key="org.eclipse.cdt.launch.DEBUGGER_ID" value="org.eclipse.cdt.debug.mi.core.CDebuggerNew"/>
- <stringAttribute key="org.eclipse.cdt.launch.DEBUGGER_REGISTER_GROUPS" value=""/>
- <stringAttribute key="org.eclipse.cdt.launch.DEBUGGER_START_MODE" value="run"/>
- <booleanAttribute key="org.eclipse.cdt.launch.DEBUGGER_STOP_AT_MAIN" value="false"/>
- @@ -18,10 +21,9 @@
- <stringAttribute key="org.eclipse.cdt.launch.FORMAT" value="<?xml version="1.0" encoding="UTF-8" standalone="no"?><contentList><content id="color-MAP_GetCultureTypeByPos-(cast)" val="unsigned char[4]"/><content id="color-MAP_GetTerrainTypeByPos-(cast)" val="unsigned char[4]"/></contentList>"/>
- <stringAttribute key="org.eclipse.cdt.launch.GLOBAL_VARIABLES" value="<?xml version="1.0" encoding="UTF-8" standalone="no"?> <globalVariableList> <globalVariable name="g_edicts" path=""/> <globalVariable name="selActor" path=""/> <globalVariable name="r_state" path=""/> </globalVariableList> "/>
- <stringAttribute key="org.eclipse.cdt.launch.MEMORY_BLOCKS" value="<?xml version="1.0" encoding="UTF-8" standalone="no"?> <memoryBlockExpressionList/> "/>
- -<stringAttribute key="org.eclipse.cdt.launch.PROGRAM_ARGUMENTS" value="+set developer 1 +set cvar 0"/>
- <stringAttribute key="org.eclipse.cdt.launch.PROGRAM_NAME" value="ufo"/>
- <stringAttribute key="org.eclipse.cdt.launch.PROJECT_ATTR" value="ufoai-trunk"/>
- -<stringAttribute key="org.eclipse.cdt.launch.PROJECT_BUILD_CONFIG_ID_ATTR" value="preference.org.eclipse.cdt.managedbuilder.core.configurationDataProvider.406131790"/>
- +<stringAttribute key="org.eclipse.cdt.launch.PROJECT_BUILD_CONFIG_ID_ATTR" value=""/>
- <booleanAttribute key="org.eclipse.cdt.launch.use_terminal" value="true"/>
- <listAttribute key="org.eclipse.debug.core.MAPPED_RESOURCE_PATHS">
- <listEntry value="/ufoai-trunk"/>
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement