Advertisement
Guest User

Untitled

a guest
Aug 1st, 2010
350
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C 33.47 KB | None | 0 0
  1. Index: .project
  2. ===================================================================
  3. --- .project    (revision 31069)
  4. +++ .project    (working copy)
  5. @@ -6,6 +6,11 @@
  6.     </projects>
  7.     <buildSpec>
  8.         <buildCommand>
  9. +           <name>org.eclipse.cdt.managedbuilder.core.ScannerConfigBuilder</name>
  10. +           <arguments>
  11. +           </arguments>
  12. +       </buildCommand>
  13. +       <buildCommand>
  14.             <name>org.eclipse.cdt.managedbuilder.core.genmakebuilder</name>
  15.             <triggers>clean,full,incremental,</triggers>
  16.             <arguments>
  17. @@ -63,11 +68,6 @@
  18.                 </dictionary>
  19.             </arguments>
  20.         </buildCommand>
  21. -       <buildCommand>
  22. -           <name>org.eclipse.cdt.managedbuilder.core.ScannerConfigBuilder</name>
  23. -           <arguments>
  24. -           </arguments>
  25. -       </buildCommand>
  26.     </buildSpec>
  27.     <natures>
  28.         <nature>org.eclipse.cdt.managedbuilder.core.ScannerConfigNature</nature>
  29. Index: src/game/g_local.h
  30. ===================================================================
  31. --- src/game/g_local.h  (revision 31069)
  32. +++ src/game/g_local.h  (working copy)
  33. @@ -44,6 +44,7 @@
  34.  #define    GAME_INCLUDE
  35.  #include "game.h"
  36.  
  37. +
  38.  /** the "gameversion" client command will print this plus compile date */
  39.  #define    GAMEVERSION "baseufo"
  40.  
  41. Index: src/game/g_combat.c
  42. ===================================================================
  43. --- src/game/g_combat.c (revision 31069)
  44. +++ src/game/g_combat.c (working copy)
  45. @@ -651,9 +651,11 @@
  46.                 VectorCopy(tr.endpos, newPos);
  47.  
  48.             /* calculate additional visibility */
  49. -           for (i = 0; i < MAX_TEAMS; i++)
  50. -               if (player->pers.team != level.activeTeam && G_TeamPointVis(i, newPos))
  51. -                   mask |= 1 << i;
  52. +           if (!mock) {
  53. +               for (i = 0; i < MAX_TEAMS; i++)
  54. +                   if (player->pers.team != level.activeTeam && G_TeamPointVis(i, newPos))
  55. +                       mask |= 1 << i;
  56. +           }
  57.  
  58.             /* enough bouncing around or we have hit an actor */
  59.             if (VectorLength(curV) < GRENADE_STOPSPEED || time > 4.0 || bounce > fd->bounce
  60. Index: src/game/g_ai.c
  61. ===================================================================
  62. --- src/game/g_ai.c (revision 31069)
  63. +++ src/game/g_ai.c (working copy)
  64. @@ -26,67 +26,185 @@
  65.  #include "g_local.h"
  66.  #include "g_ai.h"
  67.  
  68. +
  69. +
  70. +
  71. +
  72. +#define LOOKUP_EPSILON 0.0001f
  73. +/* #define MOCK_ESTIMATION_ONLY uncomment for mock-shot ONLY dmg estimation (Warning: 5-min turns)*/
  74. +
  75.  /**
  76. - * @brief Check whether friendly units are in the line of fire when shooting
  77. - * @param[in] ent AI that is trying to shoot
  78. - * @param[in] target Shoot to this location
  79. - * @param[in] spread
  80. + * @brief table for lookup_erf
  81. + * lookup[]= {erf(0), erf(0.1), ...}
  82.   */
  83. -static qboolean AI_CheckFF (const edict_t * ent, const vec3_t target, float spread)
  84. -{
  85. -   edict_t *check = NULL;
  86. -   vec3_t dtarget, dcheck, back;
  87. -   float cosSpread;
  88. +static const float lookup[30]= {
  89. +   0.0f,    0.1125f, 0.2227f, 0.3286f, 0.4284f, 0.5205f, 0.6039f,
  90. +   0.6778f, 0.7421f, 0.7969f, 0.8427f, 0.8802f, 0.9103f, 0.9340f,
  91. +   0.9523f, 0.9661f, 0.9763f, 0.9838f, 0.9891f, 0.9928f, 0.9953f,
  92. +   0.9970f, 0.9981f, 0.9989f, 0.9993f, 0.9996f, 0.9998f, 0.9999f,
  93. +   0.9999f, 1.0000f
  94. +};
  95.  
  96. -   /* spread data */
  97. -   if (spread < 1.0)
  98. -       spread = 1.0;
  99. -   spread *= torad;
  100. -   cosSpread = cos(spread);
  101. -   VectorSubtract(target, ent->origin, dtarget);
  102. -   VectorNormalize(dtarget);
  103. -   VectorScale(dtarget, PLAYER_WIDTH / spread, back);
  104. +/**
  105. + * @brief table for lookup_erf
  106. + * lookup[]= {10*(erf(0.1)-erf(0.0)), 10*(erf(0.2)-erf(0.1)), ...}
  107. + */
  108. +static const float lookupdiff[30]= {
  109. +   1.1246f, 1.1024f, 1.0592f, 0.9977f, 0.9211f, 0.8336f, 0.7395f,
  110. +   0.6430f, 0.5481f, 0.4579f, 0.3750f, 0.3011f, 0.2369f, 0.1828f,
  111. +   0.1382f, 0.1024f, 0.0744f, 0.0530f, 0.0370f, 0.0253f, 0.0170f,
  112. +   0.0112f, 0.0072f, 0.0045f, 0.0028f, 0.0017f, 0.0010f, 0.0006f,
  113. +   0.0003f, 0.0002f
  114. +};
  115.  
  116. -   while ((check = G_EdictsGetNextLivingActorOfTeam(check, ent->team))) {
  117. -       if (ent != check) {
  118. -           /* found ally */
  119. -           VectorSubtract(check->origin, ent->origin, dcheck);
  120. -           if (DotProduct(dtarget, dcheck) > 0.0) {
  121. -               /* ally in front of player */
  122. -               VectorAdd(dcheck, back, dcheck);
  123. -               VectorNormalize(dcheck);
  124. -               if (DotProduct(dtarget, dcheck) > cosSpread)
  125. -                   return qtrue;
  126. -           }
  127. -       }
  128. -   }
  129. +/**
  130. + * @brief calculate approximate erf, the error function
  131. + * http://en.wikipedia.org/wiki/Error_function
  132. + * uses lookup table and linear interpolation
  133. + * approximation good to around 0.001.
  134. + * easily good enough for the job.
  135. + * @param[in] z the number to calculate the erf of.
  136. + * @return for positive arg, returns approximate erf. for -ve arg returns 0.0f.
  137. + */
  138. +static float CL_LookupErrorFunction (float z)
  139. +{
  140. +   float ifloat;
  141. +   int iint;
  142.  
  143. -   /* no ally in danger */
  144. -   return qfalse;
  145. +   /* erf(-z)=-erf(z), but erf of -ve number should never be used here
  146. +    * so return 0 here */
  147. +   if (z < LOOKUP_EPSILON)
  148. +       return 0.0f;
  149. +   if (z > 2.8f)
  150. +       return 1.0f;
  151. +   ifloat = floor(z * 10.0f);
  152. +   iint = (int)ifloat;
  153. +   assert(iint < 30);
  154. +   return lookup[iint] + (z - ifloat / 10.0f) * lookupdiff[iint];
  155.  }
  156.  
  157.  /**
  158. - * @brief Check whether the fighter should perform the shoot
  159. - * @todo Check whether radius and power of fd are to to big for dist
  160. - * @todo Check whether the alien will die when shooting
  161. + * @brief Calculates chance to hit if the actor has a fire mode activated.
  162. + * @param[in] actor The local entity of the actor to calculate the hit probability for.
  163. + * @todo The hit probability should work somewhat differently for splash damage weapons.
  164. + * Since splash damage weapons can deal damage even when they don't directly hit an actor,
  165. + * the hit probability should be defined as the predicted percentage of the maximum splash
  166. + * damage of the firemode, assuming the projectile explodes at the desired location. This
  167. + * means that a percentage should be displayed for EVERY actor in the predicted blast
  168. + * radius. This will likely require specialized code.
  169.   */
  170. -static qboolean AI_FighterCheckShoot (const edict_t* ent, const edict_t* check, const fireDef_t* fd, float *dist)
  171. +int AI_GetHitProbability (const edict_t * actor, const edict_t * check, const fireDef_t *fd, qboolean is_crouched)
  172.  {
  173. -   /* check range */
  174. -   *dist = VectorDist(ent->origin, check->origin);
  175. -   if (*dist > fd->range)
  176. -       return qfalse;
  177. -   /* don't shoot - we are to close */
  178. -   else if (*dist < fd->splrad)
  179. -       return qfalse;
  180. +   vec3_t shooter, target;
  181. +   float distance, pseudosin, width, height, acc, perpX, perpY, hitchance,
  182. +       stdevupdown, stdevleftright, crouch, commonfactor;
  183. +   int distx, disty, n;
  184. +   //le_t *le;
  185. +   const character_t *chr;
  186. +   chr = &(actor->chr);
  187. +   //pos3_t toPos;
  188.  
  189. -   /* check FF */
  190. -   if (!G_IsInsane(ent) && AI_CheckFF(ent, check->origin, fd->spread[0]))
  191. -       return qfalse;
  192. +   //assert(actor);
  193. +   //assert(actor->fd);
  194.  
  195. -   return qtrue;
  196. +
  197. +   /** @todo use LE_FindRadius */
  198. +   //le = LE_GetFromPos(toPos);
  199. +   //if (!le)
  200. +   //  return 0;
  201. +
  202. +   /* or suicide attempted */
  203. +   //if (le->selected && !FIRESH_IsMedikit(le->fd))
  204. +   //  return 0;
  205. +
  206. +
  207. +
  208. +   VectorCopy(actor->origin, shooter);
  209. +   VectorCopy(check->origin, target);
  210. +
  211. +   /* Calculate HitZone: */
  212. +   distx = fabs(shooter[0] - target[0]);
  213. +   disty = fabs(shooter[1] - target[1]);
  214. +   distance = sqrt(distx * distx + disty * disty);
  215. +   if (distx > disty)
  216. +       pseudosin = distance / distx;
  217. +   else
  218. +       pseudosin = distance / disty;
  219. +   width = 2 * PLAYER_WIDTH * pseudosin;
  220. +   //height = LE_IsCrouched(le) ? PLAYER_CROUCHING_HEIGHT : PLAYER_STANDING_HEIGHT;
  221. +   height = is_crouched ? PLAYER_CROUCHING_HEIGHT : PLAYER_STANDING_HEIGHT;
  222. +
  223. +   //acc = GET_ACC(chr->score.skills[ABILITY_ACCURACY],
  224. +   //      actor->fd->weaponSkill ? chr->score.skills[actor->fd->weaponSkill] : 0);
  225. +   acc = GET_ACC(chr->score.skills[ABILITY_ACCURACY],
  226. +               fd->weaponSkill ? chr->score.skills[fd->weaponSkill] : 0);
  227. +
  228. +   //crouch = (LE_IsCrouched(actor) && actor->fd->crouch) ? actor->fd->crouch : 1;
  229. +   crouch = (is_crouched && fd->crouch) ? fd->crouch : 1;
  230. +
  231. +   commonfactor = crouch * torad * distance * GET_INJURY_MULT(chr->score.skills[ABILITY_MIND], chr->HP, chr->maxHP);
  232. +   stdevupdown = (fd->spread[0] * (WEAPON_BALANCE + SKILL_BALANCE * acc)) * commonfactor;
  233. +   stdevleftright = (fd->spread[1] * (WEAPON_BALANCE + SKILL_BALANCE * acc)) * commonfactor;
  234. +   hitchance = (stdevupdown > LOOKUP_EPSILON ? CL_LookupErrorFunction(height * 0.3536f / stdevupdown) : 1.0f)
  235. +             * (stdevleftright > LOOKUP_EPSILON ? CL_LookupErrorFunction(width * 0.3536f / stdevleftright) : 1.0f);
  236. +   /* 0.3536=sqrt(2)/4 */
  237. +
  238. +   /* Calculate cover: */
  239. +   n = 0;
  240. +   height = height / 18;
  241. +   width = width / 18;
  242. +   target[2] -= UNIT_HEIGHT / 2;
  243. +   target[2] += height * 9;
  244. +   perpX = disty / distance * width;
  245. +   perpY = 0 - distx / distance * width;
  246. +
  247. +   target[0] += perpX;
  248. +   perpX *= 2;
  249. +   target[1] += perpY;
  250. +   perpY *= 2;
  251. +   target[2] += 6 * height;
  252. +   if (!TR_TestLine(shooter, target, TL_FLAG_NONE))
  253. +       n++;
  254. +   target[0] += perpX;
  255. +   target[1] += perpY;
  256. +   target[2] -= 6 * height;
  257. +   if (!TR_TestLine(shooter, target, TL_FLAG_NONE))
  258. +       n++;
  259. +   target[0] += perpX;
  260. +   target[1] += perpY;
  261. +   target[2] += 4 * height;
  262. +   if (!TR_TestLine(shooter, target, TL_FLAG_NONE))
  263. +       n++;
  264. +   target[2] += 4 * height;
  265. +   if (!TR_TestLine(shooter, target, TL_FLAG_NONE))
  266. +       n++;
  267. +   target[0] -= perpX * 3;
  268. +   target[1] -= perpY * 3;
  269. +   target[2] -= 12 * height;
  270. +   if (!TR_TestLine(shooter, target, TL_FLAG_NONE))
  271. +       n++;
  272. +   target[0] -= perpX;
  273. +   target[1] -= perpY;
  274. +   target[2] += 6 * height;
  275. +   if (!TR_TestLine(shooter, target, TL_FLAG_NONE))
  276. +       n++;
  277. +   target[0] -= perpX;
  278. +   target[1] -= perpY;
  279. +   target[2] -= 4 * height;
  280. +   if (!TR_TestLine(shooter, target, TL_FLAG_NONE))
  281. +       n++;
  282. +   target[0] -= perpX;
  283. +   target[1] -= perpY;
  284. +   target[2] += 10 * height;
  285. +   if (!TR_TestLine(shooter, target, TL_FLAG_NONE))
  286. +       n++;
  287. +
  288. +   return 100 * (hitchance * (0.125) * n);
  289.  }
  290.  
  291. +
  292. +
  293. +
  294.  /**
  295.   * @brief Checks whether the AI controlled actor wants to use a door
  296.   * @param[in] ent The AI controlled actor
  297. @@ -179,6 +297,243 @@
  298.  }
  299.  
  300.  /**
  301. + * @brief Estimate the damage of a shot (given firedef and shoottype) by making mock shots with G_ClientShoot. This function properly calculates for
  302. + * 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
  303. + * @sa G_ClientShoot
  304. + * @param[in] ent_player the player who's actor will try to shoot
  305. + * @param[in] ent AI actor that is trying to shoot
  306. + * @param[in] The target we're shooting at
  307. + * @param[in] The shooting type we're using
  308. + * @param[in] The firedefinition index we're using
  309. + * @param[in] The firedef we're using. Redundant because of fdIdx and used only for minimizing sampled shots.
  310. + * @param[out] the damage expected from the shot
  311. + */
  312. +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) {
  313. +   int mockShotDmg = 0;
  314. +   int j;
  315. +   const int samples = 10; /** Try to make only this many G_ShootSingle shots in order to keep CPU usage to a minimum */
  316. +
  317. +   /* Sample 5 mock shots through the proper G_ClientShoot to see what kind of damage we can deal with our current settings */
  318. +   /** @todo OPTIMIZE, we're really having a HUGE bite into the cpu over here */
  319. +   /** @todo: is the z-align value of 0 correct? */
  320. +   /** @todo: allow mock.allowSelf=1? */
  321. +
  322. +   /** If the firedef is already shooting many times, divide by fd->shots so we get about 10 samples only */
  323. +   const int iterations = ((int)(samples/fd->shots))?samples/fd->shots:1;
  324. +
  325. +   /** Only aliens are pleased in damaging civilians */
  326. +   const int shootCivilians = (ent->team == TEAM_ALIEN);
  327. +   float civilianPenalty = 1.0f;
  328. +
  329. +   for (j = 0; j < iterations; j++) {
  330. +       shot_mock_t mock;
  331. +       memset(&mock, 0, sizeof(mock));
  332. +       if (G_ClientShoot(ent_player, ent, check->pos, shootType, fdIdx, &mock, qfalse, 0)) {
  333. +           /* Add the total damage expected */
  334. +           mockShotDmg += mock.damage;
  335. +           /* Remove the fraction of the damage that is done to us/our team and civilians (if we're not aliens)*/
  336. +           mockShotDmg -= ((mock.friendCount + mock.self) / (mock.enemyCount ? mock.enemyCount : 1)) * mock.damage;
  337. +           civilianPenalty = shootCivilians? 1 : mock.civilian/(mock.enemyCount? mock.enemyCount : 1.0f);
  338. +           mockShotDmg *= civilianPenalty;
  339. +       }
  340. +   }
  341. +   mockShotDmg /= iterations;
  342. +
  343. +   return mockShotDmg;
  344. +}
  345. +
  346. +/**
  347. + * @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)
  348. + * Since the tracings involved in the AI_GetHitProbability are minimal, the performance should be much superior to AI_CalculateDamageMock. The downsides are
  349. + * that it is very bad for calculating splash-damage&gravity based weapons while inheriting AI_GetHitProbability's hitchance calculation issues
  350. + * TODO: profiling to find out how fast this function is compared to AI_CalculateDamageMock
  351. + * TODO: take the shots out of this function
  352. + * @param[in] ent The actor that is trying to shoot
  353. + * @param[in] The target we're shooting at
  354. + * @param[in] The firedefinition we're using
  355. + * @param[in] The amount of shots we will take
  356. + * @param[out] the damage expected from the shot
  357. + */
  358. +int AI_CalculateDamageMath(edict_t * ent, const edict_t * check, const fireDef_t *fd, const int shots) {
  359. +   const objDef_t *ad;
  360. +
  361. +   int hitChance = AI_GetHitProbability(ent, check, fd, qfalse);
  362. +   int hitdmg = (fd->damage[0] + fd->damage[1] / 2 + fd->spldmg[0]) * fd->shots * shots;
  363. +
  364. +   if (CONTAINER(check, gi.csi->idArmour)) {
  365. +       ad = CONTAINER(check, gi.csi->idArmour)->item.t;
  366. +       hitdmg *= 1.0 - ad->protection[ad->dmgtype] * 0.01;
  367. +   }
  368. +
  369. +   return (hitdmg * hitChance / 100);
  370. +}
  371. +
  372. +/**
  373. + * @brief Check whether friendly units are in the line of fire when shooting
  374. + * @param[in] ent AI that is trying to shoot
  375. + * @param[in] target Shoot to this location
  376. + * @param[in] spread
  377. + */
  378. +static qboolean AI_CheckFF(const edict_t * ent, const vec3_t target, float spread) {
  379. +   edict_t *check = NULL;
  380. +   vec3_t dtarget, dcheck, back;
  381. +   float cosSpread;
  382. +
  383. +   /* spread data */
  384. +   if (spread < 1.0)
  385. +       spread = 1.0;
  386. +   spread *= torad;
  387. +   cosSpread = cos(spread);
  388. +   VectorSubtract(target, ent->origin, dtarget);
  389. +   VectorNormalize(dtarget);
  390. +   VectorScale(dtarget, PLAYER_WIDTH / spread, back);
  391. +
  392. +   while ((check = G_EdictsGetNextLivingActorOfTeam(check, ent->team))) {
  393. +       if (ent != check) {
  394. +           /* found ally */
  395. +           VectorSubtract(check->origin, ent->origin, dcheck);
  396. +           if (DotProduct(dtarget, dcheck) > 0.0) {
  397. +               /* ally in front of player */
  398. +               VectorAdd(dcheck, back, dcheck);
  399. +               VectorNormalize(dcheck);
  400. +               if (DotProduct(dtarget, dcheck) > cosSpread)
  401. +                   return qtrue;
  402. +           }
  403. +       }
  404. +   }
  405. +
  406. +   /* no ally in danger */
  407. +   return qfalse;
  408. +}
  409. +
  410. +
  411. +/**
  412. + * @brief Basic checks whether the fighter should perform the shoot. Performance Cutoff for the heavier estimation functions
  413. + * @param[in] The edict of the actor taking the shot
  414. + * @param[in] The edict of the actor getting shot
  415. + * @param[in] The fireDefinition to check against
  416. + * @param[out] The distance between the actors' edicts. Kept for legacy support
  417. + * @param[out] Whether it's logical to consider shooting the target or not.
  418. + */
  419. +static qboolean AI_FighterCheckShoot(const edict_t* ent, const edict_t* check, const fireDef_t* fd, float *dist) {
  420. +   /* check range */
  421. +   *dist = VectorDist(ent->origin, check->origin);
  422. +   if (*dist > fd->range)
  423. +       return qfalse;
  424. +   /* don't shoot - we are to close */
  425. +   else if (*dist < fd->splrad)
  426. +       return qfalse;
  427. +
  428. +   /* check FF */
  429. +   //@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
  430. +   if (!G_IsInsane(ent) && AI_CheckFF(ent, check->origin, fd->spread[0]))
  431. +       return qfalse;
  432. +
  433. +   return qtrue;
  434. +}
  435. +
  436. +/**
  437. + * @brief Find and estimate the best shot/hit we can deal to a target
  438. + * @sa G_ClientShoot
  439. + * @param[in] ent AI actor that is trying to shoot
  440. + * @param[in] the TU's the shooting actor can spend shooting
  441. + * @param[in] The target we're shooting at
  442. + * @param[out] aia used for returning the optimal shooting information. Overwries all relevant data
  443. + * @param[out] the damage expected from the optimal shot
  444. + */
  445. +float AI_GetDamagePotential (edict_t * ent, int tu, const edict_t * check, aiAction_t * aia)
  446. +{
  447. +   shoot_types_t shootType;
  448. +   float maxDmg = 0.0f;
  449. +
  450. +   /* For each shootType */
  451. +   for (shootType = ST_RIGHT; shootType < ST_NUM_SHOOT_TYPES; shootType++) {
  452. +       fireDefIndex_t fdIdx;
  453. +       const fireDef_t *fdArray;
  454. +       const item_t *item = AI_GetItemForShootType(shootType, ent);
  455. +       /* If we're checking for damage coming from another team */
  456. +       const player_t * ent_player = (level.activeTeam != (G_PLAYER_FROM_ENT(ent))->pers.team) ? NULL : G_PLAYER_FROM_ENT(ent);
  457. +
  458. +       /* Reaction fire and @todo grenade/knife-tossing from inventory return NULL */
  459. +       if (!item)
  460. +           continue;
  461. +
  462. +       /** @todo: we never consider switching ammo type. We (probably) can't do this with mockshooting dmg estimation */
  463. +       fdArray = FIRESH_FiredefForWeapon(item);
  464. +       if (fdArray == NULL)
  465. +           continue;
  466. +
  467. +       /** @todo timed firedefs that bounce around should not be thrown/shoot about the whole distance */
  468. +       /* foreach firedef */
  469. +       for (fdIdx = 0; fdIdx < item->m->numFiredefs[fdArray->weapFdsIdx]; fdIdx++) {
  470. +           const fireDef_t *fd = &fdArray[fdIdx];
  471. +           /* how many shoots can this actor do */
  472. +           const int shots = tu / fd->time;
  473. +
  474. +           /* quickly check if the shot is worth considering */
  475. +           float uselessFloat = 0.0f;
  476. +           if (!AI_FighterCheckShoot(ent, check, fd, &uselessFloat)) {
  477. +               continue;
  478. +           }
  479. +
  480. +           /* See if we can shoot & how much damage we're expected to deal */
  481. +           if (shots) {
  482. +               int mockTotalDamage = 0;
  483. +
  484. +#ifndef MOCK_ESTIMATION_ONLY
  485. +               /* If we're using grav-affected or splash-dmg weapons, calculate expected dmg via mockshots, otherwise via maths */
  486. +               /* mockshot-based is always better but really slow, so we use it only when required */
  487. +               int testTotalDamage =0;
  488. +
  489. +               if (fd->splrad > 0 || fd->gravity) {
  490. +                   mockTotalDamage += AI_CalculateDamageMock(ent_player, ent, check, shootType, fdIdx, fd) * shots;
  491. +                   //testTotalDamage = AI_CalculateDamageMath(ent, check, fd, shots);
  492. +               } else {
  493. +                   mockTotalDamage = AI_CalculateDamageMath(ent, check, fd, shots);
  494. +                   //testTotalDamage = AI_CalculateDamageMock(ent_player, ent, check, shootType, fdIdx, allowCivilians) * shots;
  495. +               }
  496. +#else
  497. +               mockTotalDamage = AI_CalculateDamageMock(ent_player, ent, check, shootType, fdIdx, fd) * shots;
  498. +#endif
  499. +               /** Do not take low-damage shots */
  500. +               /** @todo bear in mind that the dmg is actually dmg*hitchance. This might affect weapons differently according to the firedef*/
  501. +               /** @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 */
  502. +               /** Also, the selection of dmg calculations (be it mock or math) may yield different results (if math only returns dmg to one target)*/
  503. +               if (mockTotalDamage < 10){mockTotalDamage=0;}
  504. +
  505. +               if (mockTotalDamage > maxDmg) {
  506. +                   maxDmg = mockTotalDamage;
  507. +                   if (aia != NULL) {
  508. +                       aia->shootType = shootType;
  509. +                       aia->shots = shots;
  510. +                       aia->target = G_EdictsGetByNum(check->number);
  511. +                       aia->fd = fd;
  512. +                   }
  513. +               }
  514. +               //}
  515. +               /* START EXPERIMENTING WITH HIT PROBABILITIES */
  516. +               //CL_GetHitProbability (edict_t actor, edict_t check, const fireDef_t *fd, qboolean is_crouched)
  517. +               /*
  518. +                int hitChance = AI_GetHitProbability(ent, check, fd, qfalse);
  519. +                //int sampledHitChance = hits/shots_taken; //@TODO: this is debug-only
  520. +                int hitdmg = (fd->damage[0] + fd->damage[1]/2 + fd->spldmg[0]) * fd->shots * shots;
  521. +                if (CONTAINER(check, gi.csi->idArmour)) {
  522. +                ad = CONTAINER(check, gi.csi->idArmour)->item.t;
  523. +                hitdmg *= 1.0 - ad->protection[ad->dmgtype] * 0.01;
  524. +                }
  525. +                */
  526. +               //int hitdmgscore = AI_CalculateDamageMath(ent, check, fd, shots);
  527. +               //AI_GetHitProbability(ent, check, fd, qfalse); //FOR BREAKPOINT GOODNESS
  528. +               /* START EXPERIMENTING WITH HIT PROBABILITIES */
  529. +
  530. +           }
  531. +       }
  532. +   }
  533. +
  534. +   return maxDmg;
  535. +}
  536. +
  537. +/**
  538.   * @brief Checks whether the given alien should try to hide because there are enemies close
  539.   * enough to shoot the alien.
  540.   * @param[in] ent The alien edict that should (maybe) hide
  541. @@ -189,35 +544,38 @@
  542.     /* only brave aliens are trying to stay on the field if no dangerous actor is visible */
  543.     if (ent->morale > mor_brave->integer) {
  544.         edict_t *from = NULL;
  545. +       float hpExectedToLoose;
  546. +       hpExectedToLoose = 0.0;
  547.         /* test if check is visible */
  548.         while ((from = G_EdictsGetNextLivingActor(from))) {
  549. +           const invList_t *invlist;
  550. +           const fireDef_t *fd;
  551. +
  552.             if (from->team == ent->team)
  553.                 continue;
  554.  
  555.             if (G_IsCivilian(from))
  556.                 continue;
  557.  
  558. -           if (G_IsVisibleForTeam(from, ent->team)) {
  559. -               const invList_t *invlist = RIGHT(from);
  560. -               const fireDef_t *fd = NULL;
  561. -               if (invlist && invlist->item.t) {
  562. +           invlist = RIGHT(from);
  563. +           fd = NULL;
  564. +           if (invlist && invlist->item.t) {
  565. +               fd = FIRESH_FiredefForWeapon(&invlist->item);
  566. +           } else {
  567. +               invlist = LEFT(from);
  568. +               if (invlist && invlist->item.t)
  569.                     fd = FIRESH_FiredefForWeapon(&invlist->item);
  570. -               } else {
  571. -                   invlist = LEFT(from);
  572. -                   if (invlist && invlist->item.t)
  573. -                       fd = FIRESH_FiredefForWeapon(&invlist->item);
  574. -               }
  575. -               /* search the (visible) inventory (by just checking the weapon in the hands of the enemy */
  576. -               if (fd != NULL && fd->range * fd->range >= VectorDistSqr(ent->origin, from->origin)) {
  577. -                   const int damage = max(0, fd->damage[0] + (fd->damage[1] * crand()));
  578. -                   if (damage >= ent->HP / 3) {
  579. -                       const int hidingTeam = AI_GetHidingTeam(ent);
  580. -                       /* now check whether this enemy is visible for this alien */
  581. -                       if (G_Vis(hidingTeam, ent, from, VT_NOFRUSTUM))
  582. -                           return qtrue;
  583. -                   }
  584. -               }
  585.             }
  586. +           /* search the (visible) inventory (by just checking the weapon in the hands of the enemy */
  587. +           if (fd != NULL && fd->range * fd->range >= VectorDistSqr(ent->origin, from->origin)) {
  588. +               /** @todo: we still need to consider the enemy getting in range if that's not the case */
  589. +               const int damage = AI_GetDamagePotential(from, 30, ent, NULL);
  590. +
  591. +               /* Add the damage he can dish out to our expected HP loss and check to see if we can take it */
  592. +               hpExectedToLoose += damage;
  593. +               if (hpExectedToLoose > (ent->HP * GUETE_DAMAGE_AVOID_FACTOR))
  594. +                   return qtrue;
  595. +           }
  596.         }
  597.         return qfalse;
  598.     }
  599. @@ -402,15 +760,16 @@
  600.     return qfalse;
  601.  }
  602.  
  603. +#if 0
  604.  /**
  605. - * @todo This feature causes the 'aliens shoot at walls'-bug.
  606. + * @todo This feature (partially) causes the 'aliens shoot at walls'-bug.
  607.   * I considered adding a visibility check, but that wouldn't prevent aliens
  608.   * from shooting at the breakable parts of their own ship.
  609.   * So I disabled it for now. Duke, 23.10.09
  610.   */
  611.  static edict_t *AI_SearchDestroyableObject (const edict_t *ent, const fireDef_t *fd)
  612.  {
  613. -#if 0
  614. +
  615.     /* search best none human target */
  616.     edict_t *check = NULL;
  617.     float dist;
  618. @@ -431,7 +790,7 @@
  619.             return check;
  620.         }
  621.     }
  622. -#endif
  623. +
  624.     return NULL;
  625.  }
  626.  
  627. @@ -523,6 +882,7 @@
  628.         }
  629.     }
  630.  }
  631. +#endif
  632.  
  633.  /**
  634.   * @sa AI_ActorThink
  635. @@ -534,14 +894,14 @@
  636.     edict_t *check = NULL;
  637.     int tu;
  638.     pos_t move;
  639. -   shoot_types_t shootType;
  640. -   float minDist;
  641. -   float bestActionPoints, maxDmg;
  642. -   int bestTime = -1;
  643. +   float dist, minDist;
  644. +   float bestActionPoints, maxDmg, bestTime = -1;
  645.  
  646.     move = gi.MoveLength(&level.pathingMap, to,
  647.             G_IsCrouched(ent) ? 1 : 0, qtrue);
  648. -   tu = ent->TU - move;
  649. +   //tu = ent->TU - move;
  650. +   //@todo: who's setting ent->chr.reservedTus.reaction to > 0? It's also not setting the firemode etc
  651. +   tu = G_ActorUsableTUs(ent) - move;
  652.  
  653.     /* test for time */
  654.     if (tu < 0 || move == ROUTING_NOT_REACHABLE)
  655. @@ -559,39 +919,49 @@
  656.     /* search best target */
  657.     while ((check = G_EdictsGetNextLivingActor(check))) {
  658.         if (ent != check && (check->team != ent->team || G_IsInsane(ent))) {
  659. -           /* don't shoot civilians in mp */
  660. +           aiAction_t dmgAia;
  661. +           float dmg = 0.0;
  662. +
  663. +           /* don't shoot sane civilians in mp */
  664.             if (G_IsCivilian(check) && sv_maxclients->integer > 1 && !G_IsInsane(ent))
  665.                 continue;
  666.  
  667. -           /* shooting */
  668. -           maxDmg = 0.0;
  669. -           for (shootType = ST_RIGHT; shootType < ST_NUM_SHOOT_TYPES; shootType++) {
  670. -               const item_t *item;
  671. -               const fireDef_t *fdArray;
  672. +           dmg = AI_GetDamagePotential(ent, tu, check, &dmgAia);
  673. +           /** 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 */
  674. +           dmg = min(dmg,(check->HP)/2);
  675.  
  676. -               item = AI_GetItemForShootType(shootType, ent);
  677. -               if (!item)
  678. -                   continue;
  679. +           /* civilian malus */
  680. +           if (G_IsCivilian(check) && !G_IsInsane(ent))
  681. +               dmg *= GUETE_CIV_FACTOR;
  682.  
  683. -               fdArray = FIRESH_FiredefForWeapon(item);
  684. -               if (fdArray == NULL)
  685. -                   continue;
  686. -
  687. -               AI_SearchBestTarget(aia, ent, check, item, shootType, tu, &maxDmg, &bestTime, fdArray);
  688. +           /* check if most damage can be done here */
  689. +           if (dmg > maxDmg) {
  690. +               maxDmg = dmg;
  691. +               bestTime = dmgAia.fd->time * dmgAia.shots;
  692. +               aia->shootType = dmgAia.shootType;
  693. +               aia->shots = dmgAia.shots;
  694. +               aia->target = check;
  695. +               aia->fd = dmgAia.fd;
  696.             }
  697. -       } /* firedefs */
  698. +       }
  699.     }
  700.     /* add damage to bestActionPoints */
  701.     if (aia->target) {
  702. +       assert(maxDmg > 0);
  703.         bestActionPoints += maxDmg;
  704.         assert(bestTime > 0);
  705.         tu -= bestTime;
  706. +       if (tu<0){
  707. +           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);
  708. +       }
  709.     }
  710.  
  711.     if (!G_IsRaged(ent)) {
  712.         const int hidingTeam = AI_GetHidingTeam(ent);
  713.         /* hide */
  714. -       if (!AI_HideNeeded(ent) || !(G_TestVis(hidingTeam, ent, VT_PERISH | VT_NOFRUSTUM) & VIS_YES)) {
  715. +       /** @todo: don't hide from the unit we're about to kill */
  716. +       //if (!AI_HideNeeded(ent) || !(G_TestVis(hidingTeam, ent, VT_PERISH | VT_NOFRUSTUM) & VIS_YES)) {
  717. +       if (!(G_TestVis(hidingTeam, ent, VT_PERISH | VT_NOFRUSTUM) & VIS_YES) && !AI_HideNeeded(ent)) {
  718.             /* is a hiding spot */
  719.             bestActionPoints += GUETE_HIDE + (aia->target ? GUETE_CLOSE_IN : 0);
  720.         } else if (aia->target && tu >= TU_MOVE_STRAIGHT) {
  721. @@ -623,8 +993,9 @@
  722.     check = NULL;
  723.     while ((check = G_EdictsGetNextLivingActor(check))) {
  724.         if (check->team != ent->team) {
  725. -           const float dist = VectorDist(ent->origin, check->origin);
  726. -           minDist = min(dist, minDist);
  727. +           dist = VectorDist(ent->origin, check->origin);
  728. +           if (dist < minDist)
  729. +               minDist = dist;
  730.         }
  731.     }
  732.     bestActionPoints += GUETE_CLOSE_IN * (1.0 - minDist / CLOSE_IN_DIST);
  733. @@ -659,7 +1030,9 @@
  734.     G_EdictSetOrigin(ent, to);
  735.  
  736.     move = gi.MoveLength(&level.pathingMap, to, crouchingState, qtrue);
  737. -   tu = ent->TU - move;
  738. +   //tu = ent->TU - move;
  739. +   //@todo: who's setting ent->chr.reservedTus.reaction to > 0? It's also not setting the firemode etc
  740. +   tu = G_ActorUsableTUs(ent) - move;
  741.  
  742.     /* test for time */
  743.     if (tu < 0 || move == ROUTING_NOT_REACHABLE)
  744. @@ -835,12 +1208,12 @@
  745.     const byte crouchingState = G_IsCrouched(ent) ? 1 : 0;
  746.  
  747.     /* calculate move table */
  748. -   G_MoveCalc(0, ent, ent->pos, crouchingState, ent->TU);
  749. +   G_MoveCalc(0, ent, ent->pos, crouchingState,G_ActorUsableTUs(ent));
  750.     Com_DPrintf(DEBUG_ENGINE, "AI_PrepBestAction: Called MoveMark.\n");
  751.     gi.MoveStore(&level.pathingMap);
  752.  
  753.     /* set borders */
  754. -   dist = (ent->TU + 1) / 2;
  755. +   dist = (G_ActorUsableTUs(ent) + 1) / 2;
  756.     xl = max((int) ent->pos[0] - dist, 0);
  757.     yl = max((int) ent->pos[1] - dist, 0);
  758.     xh = min((int) ent->pos[0] + dist, PATHFINDING_WIDTH);
  759. @@ -857,7 +1230,7 @@
  760.         for (to[1] = yl; to[1] < yh; to[1]++)
  761.             for (to[0] = xl; to[0] < xh; to[0]++) {
  762.                 const pos_t move = gi.MoveLength(&level.pathingMap, to, crouchingState, qtrue);
  763. -               if (move != ROUTING_NOT_REACHABLE && move <= ent->TU) {
  764. +               if (move != ROUTING_NOT_REACHABLE && move <= G_ActorUsableTUs(ent)) {
  765.                     if (G_IsCivilian(ent) || G_IsPaniced(ent))
  766.                         bestActionPoints = AI_CivilianCalcBestAction(ent, to, &aia);
  767.                     else
  768. @@ -873,6 +1246,11 @@
  769.     VectorCopy(oldPos, ent->pos);
  770.     VectorCopy(oldOrigin, ent->origin);
  771.  
  772. +   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]);
  773. +   if (G_ActorUsableTUs(ent) < bestActionPoints){
  774. +       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));
  775. +   }
  776. +
  777.     bestActionPoints = AI_CheckForMissionTargets(player, ent, &aia);
  778.     if (bestActionPoints > best) {
  779.         bestAia = aia;
  780. @@ -929,7 +1307,8 @@
  781.     int dv;
  782.     const byte crouchingState = G_IsCrouched(ent) ? 1 : 0;
  783.  
  784. -   G_MoveCalc(ent->team, ent, pos, crouchingState, ent->TU);
  785. +   //G_MoveCalc(ent->team, ent, pos, crouchingState, ent->TU);
  786. +   G_MoveCalc(ent->team, ent, pos, crouchingState, G_ActorUsableTUs(ent));
  787.  
  788.     dv = gi.MoveNext(&level.pathingMap, pos, crouchingState);
  789.     if (dv != ROUTING_UNREACHABLE) {
  790. @@ -980,6 +1359,7 @@
  791.  
  792.     bestAia = AI_PrepBestAction(player, ent);
  793.  
  794. +
  795.     /* shoot and hide */
  796.     if (bestAia.target) {
  797.         const fireDefIndex_t fdIdx = bestAia.fd ? bestAia.fd->fdIdx : 0;
  798. @@ -994,6 +1374,7 @@
  799.             if (G_IsDead(bestAia.target)) {
  800.                 /* search another target now */
  801.                 bestAia = AI_PrepBestAction(player, ent);
  802. +               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]);
  803.                 /* no other target found - so no need to hide */
  804.                 if (!bestAia.target)
  805.                     return;
  806. @@ -1044,7 +1425,8 @@
  807.             edict_t *ent = player->pers.last;
  808.  
  809.             while ((ent = G_EdictsGetNextLivingActorOfTeam(ent, player->pers.team))) {
  810. -               if (ent->TU) {
  811. +               //if (ent->TU) {
  812. +               if (G_ActorUsableTUs(ent)) {
  813.                     if (g_ailua->integer)
  814.                         AIL_ActorThink(player, ent);
  815.                     else
  816. Index: src/game/g_ai.h
  817. ===================================================================
  818. --- src/game/g_ai.h (revision 31069)
  819. +++ src/game/g_ai.h (working copy)
  820. @@ -36,13 +36,14 @@
  821.     int z_align;        /**< the z-align for every shoot */
  822.  } aiAction_t;
  823.  
  824. -#define GUETE_HIDE         60
  825. +#define GUETE_HIDE         30
  826.  #define GUETE_CLOSE_IN     20
  827.  #define GUETE_KILL         30
  828.  #define GUETE_RANDOM       10
  829.  #define GUETE_REACTION_ERADICATION 30
  830.  #define GUETE_REACTION_FEAR_FACTOR 20
  831. -#define GUETE_CIV_FACTOR   0.25
  832. +#define GUETE_CIV_FACTOR   0.2
  833. +#define GUETE_DAMAGE_AVOID_FACTOR  0.4
  834.  
  835.  #define GUETE_CIV_RANDOM   10
  836.  #define GUETE_RUN_AWAY     50
  837. Index: build/projects/ufo.launch
  838. ===================================================================
  839. --- build/projects/ufo.launch   (revision 31069)
  840. +++ build/projects/ufo.launch   (working copy)
  841. @@ -6,9 +6,12 @@
  842.  <stringAttribute key="org.eclipse.cdt.debug.mi.core.GDB_INIT" value=".gdbinit"/>
  843.  <listAttribute key="org.eclipse.cdt.debug.mi.core.SOLIB_PATH"/>
  844.  <booleanAttribute key="org.eclipse.cdt.debug.mi.core.STOP_ON_SOLIB_EVENTS" value="false"/>
  845. +<booleanAttribute key="org.eclipse.cdt.debug.mi.core.breakpointsFullPath" value="false"/>
  846. +<stringAttribute key="org.eclipse.cdt.debug.mi.core.commandFactory" value="org.eclipse.cdt.debug.mi.core.standardLinuxCommandFactory"/>
  847.  <stringAttribute key="org.eclipse.cdt.debug.mi.core.protocol" value="mi"/>
  848. +<booleanAttribute key="org.eclipse.cdt.debug.mi.core.verboseMode" value="false"/>
  849.  <stringAttribute key="org.eclipse.cdt.launch.COREFILE_PATH" value=""/>
  850. -<stringAttribute key="org.eclipse.cdt.launch.DEBUGGER_ID" value="org.eclipse.cdt.debug.mi.core.CDebugger"/>
  851. +<stringAttribute key="org.eclipse.cdt.launch.DEBUGGER_ID" value="org.eclipse.cdt.debug.mi.core.CDebuggerNew"/>
  852.  <stringAttribute key="org.eclipse.cdt.launch.DEBUGGER_REGISTER_GROUPS" value=""/>
  853.  <stringAttribute key="org.eclipse.cdt.launch.DEBUGGER_START_MODE" value="run"/>
  854.  <booleanAttribute key="org.eclipse.cdt.launch.DEBUGGER_STOP_AT_MAIN" value="false"/>
  855. @@ -18,10 +21,9 @@
  856.  <stringAttribute key="org.eclipse.cdt.launch.FORMAT" value="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&lt;contentList&gt;&lt;content id=&quot;color-MAP_GetCultureTypeByPos-(cast)&quot; val=&quot;unsigned char[4]&quot;/&gt;&lt;content id=&quot;color-MAP_GetTerrainTypeByPos-(cast)&quot; val=&quot;unsigned char[4]&quot;/&gt;&lt;/contentList&gt;"/>
  857.  <stringAttribute key="org.eclipse.cdt.launch.GLOBAL_VARIABLES" value="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#10;&lt;globalVariableList&gt;&#10;&lt;globalVariable name=&quot;g_edicts&quot; path=&quot;&quot;/&gt;&#10;&lt;globalVariable name=&quot;selActor&quot; path=&quot;&quot;/&gt;&#10;&lt;globalVariable name=&quot;r_state&quot; path=&quot;&quot;/&gt;&#10;&lt;/globalVariableList&gt;&#10;"/>
  858.  <stringAttribute key="org.eclipse.cdt.launch.MEMORY_BLOCKS" value="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#10;&lt;memoryBlockExpressionList/&gt;&#10;"/>
  859. -<stringAttribute key="org.eclipse.cdt.launch.PROGRAM_ARGUMENTS" value="+set developer 1 +set cvar 0"/>
  860.  <stringAttribute key="org.eclipse.cdt.launch.PROGRAM_NAME" value="ufo"/>
  861.  <stringAttribute key="org.eclipse.cdt.launch.PROJECT_ATTR" value="ufoai-trunk"/>
  862. -<stringAttribute key="org.eclipse.cdt.launch.PROJECT_BUILD_CONFIG_ID_ATTR" value="preference.org.eclipse.cdt.managedbuilder.core.configurationDataProvider.406131790"/>
  863. +<stringAttribute key="org.eclipse.cdt.launch.PROJECT_BUILD_CONFIG_ID_ATTR" value=""/>
  864.  <booleanAttribute key="org.eclipse.cdt.launch.use_terminal" value="true"/>
  865.  <listAttribute key="org.eclipse.debug.core.MAPPED_RESOURCE_PATHS">
  866.  <listEntry value="/ufoai-trunk"/>
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement