home *** CD-ROM | disk | FTP | other *** search
/ Maximum CD 2007 September / maximum-cd-2007-09.iso / Assets / data / AssaultCube_v0.93.exe / source / src / bot / ac_bot_ai.cpp next >
Encoding:
C/C++ Source or Header  |  2006-12-06  |  10.0 KB  |  319 lines

  1. //
  2. // C++ Implementation: ac_bot_ai
  3. //
  4. // Description: The AI part of the bot for ac is here(navigation, shooting etc)
  5. //
  6. //
  7. // Author:  <rickhelmus@gmail.com>
  8. //
  9.  
  10.  
  11.  
  12. #include "bot.h"
  13.  
  14. #ifdef AC_CUBE
  15.  
  16. // UNDONE
  17. weaponinfo_s WeaponInfoTable[MAX_WEAPONS] =
  18. {
  19.      // KNIFE
  20.      { TYPE_MELEE, 0.0f, 2.0f, 0.0f, 3.5f, 1 },
  21.      // PISTOL
  22.      { TYPE_NORMAL, 0.0f, 20.0f, 0.0f, 50.0f, 6 },
  23.      // SHOTGUN
  24.      { TYPE_SHOTGUN, 0.0f, 15.0f, 0.0f, 40.0f, 3 },     
  25.      // SUBGUN
  26.      { TYPE_AUTO, 0.0f, 25.0f, 0.0f, 60.0f, 10 },     
  27.      // SNIPER
  28.      { TYPE_SNIPER, 30.0f, 50.0f, 20.0f, 200.0f, 3 },    
  29.      // ASSAULT
  30.      { TYPE_AUTO, 40.0f, 80.0f, 0.0f, 150.0f, 6 },
  31.      // GRENADE
  32.      { TYPE_GRENADE, 30.0f, 25.0f, 0.0f, 50.0f, 1 }
  33. };
  34.  
  35. // Code of CACBot - Start   
  36.  
  37. bool CACBot::ChoosePreferredWeapon()
  38. {
  39.     short bestWeapon = m_pMyEnt->gunselect;
  40.     short bestWeaponScore = 0;
  41.  
  42.      short sWeaponScore;
  43.      float flDist = GetDistance(m_pMyEnt->enemy->o);
  44.  
  45.      if (m_iChangeWeaponDelay < lastmillis && m_pMyEnt->mag[m_pMyEnt->gunselect])
  46.      {
  47.          if ((WeaponInfoTable[m_pMyEnt->gunselect].eWeaponType != TYPE_MELEE) || (flDist <= WeaponInfoTable[GUN_KNIFE].flMaxFireDistance))
  48.                return true;
  49.      };
  50.             
  51.      // Choose a weapon
  52.      for(int i=0;i<MAX_WEAPONS;i++)
  53.      {
  54.           // If no ammo for this weapon, skip it
  55.           if (!m_pMyEnt->mag[i] && !m_pMyEnt->ammo[i]) continue;
  56.           
  57.           sWeaponScore = 5; // Minimal score for a weapon
  58.  
  59.           // use the advantage of the melee weapon
  60.           if((flDist >= WeaponInfoTable[i].flMinDesiredDistance) &&
  61.               (flDist <= WeaponInfoTable[i].flMaxDesiredDistance))
  62.           {
  63.               if(WeaponInfoTable[i].eWeaponType == TYPE_MELEE) sWeaponScore += 5;
  64.           }
  65.           
  66.           if ((flDist > WeaponInfoTable[i].flMinFireDistance) && // inside the range, continue to evaluate
  67.                    (flDist < WeaponInfoTable[i].flMaxFireDistance))
  68.           {    
  69.             if(m_pMyEnt->mag[i]) sWeaponScore += 5;
  70.             if(i > 1) sWeaponScore += 4; // prefer primary guns
  71.           }
  72.  
  73.           if(sWeaponScore > bestWeaponScore)
  74.           {
  75.             bestWeaponScore = sWeaponScore;
  76.             bestWeapon = i;
  77.           }
  78.      }   
  79.      
  80.      {
  81.           m_iChangeWeaponDelay = lastmillis + 8000; //RandomLong(2000, 8000);
  82.           m_bShootAtFeet = false;
  83.           SelectGun(bestWeapon);
  84.           if(!m_pMyEnt->mag[bestWeapon]) 
  85.           {
  86.             reload(m_pMyEnt);
  87.             m_iShootDelay = lastmillis + reloadtime(bestWeapon) + 10;
  88.           }
  89.           return true;
  90.      }
  91. };
  92.      
  93. void CACBot::Reload(int Gun)
  94. {
  95.     
  96. };
  97.      
  98. entity *CACBot::SearchForEnts(bool bUseWPs, float flRange, float flMaxHeight)
  99. {
  100.      /* Entities are scored on the following things:
  101.           - Visibility
  102.           - For ammo: Need(ie has this bot much of this type or not)
  103.           - distance
  104.      */
  105.      
  106.      float flNearestDist = 9999, flDist;
  107.      entity *pNewTargetEnt = NULL;
  108.      waypoint_s *pWptNearBot = NULL, *pBestWpt = NULL;
  109.      short sScore, sHighestScore = 0;
  110.      
  111.      if ((WaypointClass.m_iWaypointCount >= 1) && bUseWPs)
  112.           pWptNearBot = GetNearestWaypoint(15.0f);
  113.  
  114. #ifdef WP_FLOOD                    
  115.      if (!pWptNearBot && bUseWPs)
  116.           pWptNearBot = GetNearestFloodWP(5.0f);
  117. #endif
  118.           
  119.      loopv(ents)
  120.      {
  121.           sScore = 0;
  122.           entity &e = ents[i];
  123.           vec o(e.x, e.y, S(e.x, e.y)->floor+player1->eyeheight);
  124.      
  125.           if (!ents[i].spawned) continue;
  126.           if (OUTBORD(e.x, e.y)) continue;
  127.           
  128.           bool bInteresting = false;
  129.           short sAmmo = 0, sMaxAmmo = 0;
  130.           
  131.           switch(e.type)
  132.           {
  133.           case I_CLIPS:
  134.                sMaxAmmo = itemstats[GUN_PISTOL].max;
  135.                bInteresting = (m_pMyEnt->ammo[GUN_PISTOL]<sMaxAmmo);
  136.                sAmmo = m_pMyEnt->ammo[GUN_PISTOL];
  137.                break;
  138.           case I_AMMO:
  139.                sMaxAmmo = itemstats[m_pMyEnt->primary].max;
  140.                bInteresting = (m_pMyEnt->ammo[m_pMyEnt->primary]<sMaxAmmo);
  141.                sAmmo = m_pMyEnt->ammo[m_pMyEnt->primary];
  142.                break;
  143.           case I_GRENADE:
  144.                sMaxAmmo = itemstats[GUN_GRENADE].max;
  145.                bInteresting = (m_pMyEnt->mag[GUN_GRENADE]<sMaxAmmo);
  146.                sAmmo = m_pMyEnt->mag[GUN_GRENADE];
  147.                break;
  148.           case I_HEALTH:
  149.                sMaxAmmo = itemstats[7].max; //FIXME
  150.                bInteresting = (m_pMyEnt->health < sMaxAmmo); 
  151.                sAmmo = m_pMyEnt->health;
  152.                break;
  153.           case I_ARMOUR:
  154.                sMaxAmmo = itemstats[8].max; // FIXME
  155.                bInteresting = (m_pMyEnt->armour < sMaxAmmo);
  156.                sAmmo = m_pMyEnt->armour;
  157.                break;
  158.           };
  159.           
  160.           if (!bInteresting)
  161.               continue; // Not an interesting item, skip
  162.           
  163.           // Score on ammo and need
  164.           if (sAmmo == -1)
  165.           {
  166.                // This entity doesn't have/need ammo
  167.                // Score on type instead
  168.                switch(e.type)
  169.                { // UNDONE
  170.                }
  171.           }
  172.           else
  173.           {
  174.                // Calculate current percentage of max ammo
  175.                float percent = ((float)sAmmo / (float)sMaxAmmo) * 100.0f;
  176.                if (percent > 100.0f) percent = 100.0f;
  177.                sScore += ((100 - short(percent))/2);
  178.           }
  179.                
  180.           flDist = GetDistance(o);
  181.           
  182.           if (flDist > flRange) continue;
  183.           
  184.           // Score on distance
  185.           float f = flDist;
  186.           if (f > 100.0f) f = 100.0f;
  187.           sScore += ((100 - short(f)) / 2);
  188.           
  189.           waypoint_s *pWptNearEnt = NULL;
  190.           // If this entity isn't visible check if there is a nearby waypoint
  191.           if (!IsReachable(o, flMaxHeight))//(!IsVisible(o))
  192.           {
  193.                if (!pWptNearBot) continue;
  194.                
  195. #ifdef WP_FLOOD               
  196.                if (pWptNearBot->pNode->iFlags & W_FL_FLOOD)
  197.                     pWptNearEnt = GetNearestFloodWP(o, 8.0f);
  198.                else
  199. #endif               
  200.                     pWptNearEnt = GetNearestWaypoint(o, 15.0f);
  201.                     
  202.                if (!pWptNearEnt) continue;                              
  203.           }
  204.                                     
  205.           // Score on visibility
  206.           if (pWptNearEnt == NULL) // Ent is visible
  207.                sScore += 30;
  208.           else
  209.                sScore += 15;
  210.                
  211.           if (sScore > sHighestScore)
  212.           {
  213.                // Found a valid wp near the bot and the ent,so...lets store it :)
  214.                if (pWptNearEnt)
  215.                     pBestWpt = pWptNearEnt;
  216.                else
  217.                     pBestWpt = NULL; // Best ent so far doesn't need any waypoints
  218.                
  219.                sHighestScore = sScore;
  220.                flNearestDist = flDist;
  221.                pNewTargetEnt = &ents[i];
  222.           }
  223.      }
  224.      
  225.      if (pNewTargetEnt)
  226.      {          
  227.           // Need waypoints to reach it?
  228.           if (pBestWpt)
  229.           {
  230.                ResetWaypointVars();
  231.                SetCurrentWaypoint(pWptNearBot);
  232.                SetCurrentGoalWaypoint(pBestWpt);
  233.           }
  234.                
  235.           m_vGoal.x = pNewTargetEnt->x;
  236.           m_vGoal.y = pNewTargetEnt->y;
  237.           m_vGoal.z = S(pNewTargetEnt->x, pNewTargetEnt->y)->floor+player1->eyeheight;
  238.      }
  239.           
  240.      return pNewTargetEnt;
  241. }
  242.  
  243. bool CACBot::HeadToTargetEnt()
  244. {     
  245.      if (m_pTargetEnt)
  246.      {
  247.           vec o(m_pTargetEnt->x, m_pTargetEnt->y,
  248.                     S(m_pTargetEnt->x, m_pTargetEnt->y)->floor+m_pMyEnt->eyeheight);
  249.           
  250.           if (m_pTargetEnt->spawned && (!UnderWater(m_pMyEnt->o) ||
  251.               !UnderWater(o)))
  252.           {
  253.                bool bIsVisible = false;
  254.                if (m_pCurrentGoalWaypoint)
  255.                {
  256.                     if ((GetDistance(o) <= 20.0f) && IsReachable(o, 1.0f))
  257.                          bIsVisible = true;
  258.                     else if (HeadToGoal())
  259.                     {
  260.                          //debugbeam(m_pMyEnt->o, m_pCurrentWaypoint->pNode->v_origin);
  261.                          //debugbeam(m_pMyEnt->o,
  262.                          //            m_pCurrentGoalWaypoint->pNode->v_origin);
  263.                          AddDebugText("Using WPs for ents");
  264.                          return true;
  265.                     }
  266.                }
  267.                else
  268.                     bIsVisible = IsVisible(o);
  269.                                    
  270.                if (bIsVisible)
  271.                {
  272.                     if (m_pCurrentWaypoint || m_pCurrentGoalWaypoint)
  273.                     {
  274.                          condebug("ent is now visible");
  275.                          ResetWaypointVars();
  276.                     }
  277.                     
  278.                     float flHeightDiff = o.z - m_pMyEnt->o.z;
  279.                     bool bToHigh = false;
  280.                     if (Get2DDistance(o) <= 2.0f)
  281.                     {
  282.                          if (flHeightDiff >= 1.5f)
  283.                          {
  284.                               if (flHeightDiff <= JUMP_HEIGHT)
  285.                               {
  286. #ifndef RELEASE_BUILD                    
  287.                                    char sz[64];
  288.                                    sprintf(sz, "Ent z diff: %f", o.z-m_pMyEnt->o.z);
  289.                                    condebug(sz);
  290. #endif                         
  291.                                    // Jump if close to ent and the ent is high
  292.                                    m_pMyEnt->jumpnext = true;
  293.                               }
  294.                               else
  295.                                    bToHigh = true;
  296.                          }
  297.                     }
  298.                     
  299.                     if (!bToHigh)
  300.                     {
  301.                          AimToVec(o);
  302.                          return true;                              
  303.                     }                                        
  304.                }
  305.           }
  306.      }
  307.      
  308.      return false;
  309. }
  310.           
  311. bool CACBot::DoSPStuff()
  312. {
  313.      return false;
  314. }
  315.     
  316. // Code of CACBot - End
  317.  
  318. #endif
  319.