Don't like ads? PRO users don't see any ads ;-)
Guest

Untitled

By: a guest on Aug 20th, 2012  |  syntax: None  |  size: 13.43 KB  |  hits: 11  |  expires: Never
download  |  raw  |  embed  |  report abuse  |  print
Text below is selected. Please press Ctrl+C to copy to your clipboard. (⌘+C on Mac)
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Text;
  4. using System.Linq;
  5. using System.Threading;
  6.  
  7. using InfServer.Game;
  8. using InfServer.Protocol;
  9. using InfServer.Scripting;
  10. using InfServer.Bots;
  11.  
  12. using Assets;
  13. using Axiom.Math;
  14. using Bnoerj.AI.Steering;
  15.  
  16. namespace InfServer.Script.GameType_ZombieZone
  17. {
  18.     // ZombieBot Class
  19.     /// A simple zombie-type bot
  20.     ///////////////////////////////////////////////////////
  21.     public class ZombieBot : Bot
  22.     {   // Member variables
  23.         ///////////////////////////////////////////////////
  24.         public Team targetTeam;                                 //The team of which players we're targetting
  25.  
  26.         protected bool bOverriddenPoll;                 //Do we have custom actions for poll?
  27.  
  28.         protected Player victim;                                //The player we're currently stalking
  29.         protected SteeringController steering;  //System for controlling the bot's steering
  30.         protected Script_ZombieZone zz;                 //The zombiezone script
  31.  
  32.         protected List<Vector3> _path;                  //The path to our destination
  33.         protected int _pathTarget;                              //The next target node of the path
  34.         protected int _tickLastPath;                    //The time at which we last made a path to the player
  35.  
  36.         private float _seperation;
  37.         private Script_ZombieZone.ZombieDistraction distraction;
  38.  
  39.  
  40.         ///////////////////////////////////////////////////
  41.         // Member Functions
  42.         ///////////////////////////////////////////////////
  43.         /// <summary>
  44.         /// Generic constructor
  45.         /// </summary>
  46.         public ZombieBot(VehInfo.Car type, Helpers.ObjectState state, Arena arena, Script_ZombieZone _zz)
  47.             : base(type, state, arena,
  48.                     new SteeringController(type, state, arena))
  49.         {
  50.             Random rnd = new Random();
  51.  
  52.             _seperation = (float)rnd.NextDouble();
  53.             steering = _movement as SteeringController;
  54.  
  55.             if (type.InventoryItems[0] != 0)
  56.                 _weapon.equip(AssetManager.Manager.getItemByID(type.InventoryItems[0]));
  57.  
  58.             zz = _zz;
  59.         }
  60.  
  61.         /// <summary>
  62.         /// Looks after the bot's functionality
  63.         /// </summary>
  64.         public override bool poll()
  65.         {       //Overridden?
  66.             if (bOverriddenPoll)
  67.                 return base.poll();
  68.  
  69.             //Dead? Do nothing
  70.             if (IsDead)
  71.             {
  72.                 steering.steerDelegate = null;
  73.                 return base.poll();
  74.             }
  75.  
  76.             int now = Environment.TickCount;
  77.  
  78.             if (checkCircumstances())
  79.                 return base.poll();
  80.  
  81.             //Get the closest player
  82.             bool bClearPath = false;
  83.             victim = getTargetPlayer(ref bClearPath);
  84.  
  85.             if (victim != null)
  86.             {
  87.                 if (bClearPath)
  88.                 {       //Persue directly!
  89.                     steering.steerDelegate = steerForPersuePlayer;
  90.  
  91.                     //Can we shoot?
  92.                     if (_weapon.ableToFire())
  93.                     {
  94.                         int aimResult = _weapon.getAimAngle(victim._state);
  95.  
  96.                         if (_weapon.isAimed(aimResult))
  97.                         {       //Spot on! Fire?
  98.                             _itemUseID = _weapon.ItemID;
  99.                             _weapon.shotFired();
  100.                         }
  101.  
  102.                         steering.bSkipAim = true;
  103.                         steering.angle = aimResult;
  104.                     }
  105.                     else
  106.                         steering.bSkipAim = false;
  107.                 }
  108.                 else
  109.                 {       //Does our path need to be updated?
  110.                     if (now - _tickLastPath > Script_ZombieZone.c_zombiePathUpdateInterval)
  111.                     {   //Are we close enough to the team?
  112.                         if (!checkTeamDistance())
  113.                         {
  114.                             _path = null;
  115.                             destroy(true);
  116.                         }
  117.                         else
  118.                         {       //Update it!
  119.                             _tickLastPath = int.MaxValue;
  120.  
  121.                             _arena._pathfinder.queueRequest(
  122.                                 (short)(_state.positionX / 16), (short)(_state.positionY / 16),
  123.                                 (short)(victim._state.positionX / 16), (short)(victim._state.positionY / 16),
  124.                                 delegate(List<Vector3> path, int pathLength)
  125.                                 {
  126.                                     if (path != null)
  127.                                     {   //Is the path too long?
  128.                                         if (pathLength > Script_ZombieZone.c_zombieMaxPath)
  129.                                         {       //Destroy ourself and let another zombie take our place
  130.                                             _path = null;
  131.                                             destroy(true);
  132.                                         }
  133.                                         else
  134.                                         {
  135.                                             _path = path;
  136.                                             _pathTarget = 1;
  137.                                         }
  138.                                     }
  139.  
  140.                                     _tickLastPath = now;
  141.                                 }
  142.                             );
  143.                         }
  144.                     }
  145.  
  146.                     //Navigate to him
  147.                     if (_path == null)
  148.                         //If we can't find out way to him, just mindlessly walk in his direction for now
  149.                         steering.steerDelegate = steerForPersuePlayer;
  150.                     else
  151.                         steering.steerDelegate = steerAlongPath;
  152.                 }
  153.             }
  154.  
  155.             //Handle normal functionality
  156.             return base.poll();
  157.         }
  158.  
  159.         /// <summary>
  160.         /// Obtains a suitable target player
  161.         /// </summary>
  162.         protected Player getTargetPlayer(ref bool bInSight)
  163.         {       //Look at the players on the target team
  164.             if (targetTeam == null)
  165.                 return null;
  166.  
  167.             Player target = null;
  168.             double lastDist = double.MaxValue;
  169.             bInSight = false;
  170.  
  171.             foreach (Player p in targetTeam.ActivePlayers.ToList())
  172.             {   //Find the closest player
  173.                 if (p.IsDead)
  174.                     continue;
  175.  
  176.                 double dist = Helpers.distanceSquaredTo(_state, p._state);
  177.                 bool bClearPath = Helpers.calcBresenhemsPredicate(_arena,
  178.                     _state.positionX, _state.positionY, p._state.positionX, p._state.positionY,
  179.                     delegate(LvlInfo.Tile t)
  180.                     {
  181.                         return !t.Blocked;
  182.                     }
  183.                 );
  184.  
  185.                 if ((!bInSight || (bInSight && bClearPath)) && lastDist > dist)
  186.                 {
  187.                     bInSight = bClearPath;
  188.                     lastDist = dist;
  189.                     target = p;
  190.                 }
  191.             }
  192.  
  193.             return target;
  194.         }
  195.  
  196.         /// <summary>
  197.         /// Checks to see if we're too far from the team
  198.         /// </summary>
  199.         protected bool checkTeamDistance()
  200.         {
  201.             //sanity check
  202.             if (targetTeam.ActivePlayerCount == 0)
  203.                 return true;
  204.  
  205.             int minDist = int.MaxValue;
  206.  
  207.             //finds minimum distance from any one of the activeplayers
  208.             foreach (Player player in targetTeam.ActivePlayers)
  209.             {
  210.                 //uses the max{dx,dy} metric for distance estimate
  211.                 int dist = Math.Max(Math.Abs(_state.positionX - player._state.positionX), Math.Abs(_state.positionY - player._state.positionY));
  212.  
  213.                 if (dist < minDist)
  214.                     minDist = dist;
  215.             }
  216.  
  217.             return minDist < Script_ZombieZone.c_zombieMaxRespawnDist + Script_ZombieZone.c_zombieDistanceLeeway;
  218.         }
  219.  
  220.         /// <summary>
  221.         /// Checks for any special circumstances we should be handling
  222.         /// </summary>
  223.         protected bool checkCircumstances()
  224.         {       //Check for extraordinary circumstances
  225.             Script_ZombieZone.TeamState state = zz.getTeamState(targetTeam);
  226.             if (state != null)
  227.             {
  228.                 if (checkForDistractions(state))
  229.                     return true;
  230.  
  231.                 if (checkForCloak(state))
  232.                     return true;
  233.             }
  234.  
  235.             return false;
  236.         }
  237.  
  238.         /// <summary>
  239.         /// Checks for any distractions we should approach
  240.         /// </summary>
  241.         protected virtual bool checkForCloak(Script_ZombieZone.TeamState state)
  242.         {       //Is the team cloaked?
  243.             if (!state.bCloaked)
  244.                 return false;
  245.  
  246.             //Just wander about!
  247.             steering.steerDelegate = delegate(InfantryVehicle vehicle)
  248.             {
  249.                 return vehicle.SteerForWander(0.5f);
  250.             };
  251.  
  252.             return true;
  253.         }
  254.  
  255.         /// <summary>
  256.         /// Checks for any distractions we should approach
  257.         /// </summary>
  258.         protected virtual bool checkForDistractions(Script_ZombieZone.TeamState state)
  259.         {       //Do we already have a distraction?
  260.             if (distraction != null)
  261.             {
  262.                 if (distraction.bActive)
  263.                 {
  264.                     if (!headToDistraction(distraction))
  265.                     {
  266.                         distraction = null;
  267.                         return false;
  268.                     }
  269.                     else
  270.                         return true;
  271.                 }
  272.                 else
  273.                     distraction = null;
  274.             }
  275.  
  276.             //Are there any distractions we can see?
  277.             foreach (Script_ZombieZone.ZombieDistraction distract in state.distractions)
  278.             {   //At it's limit?
  279.                 if (distract.distractLimit <= 0)
  280.                     continue;
  281.  
  282.                 //If it works, use it
  283.                 if (headToDistraction(distract))
  284.                 {
  285.                     distraction = distract;
  286.                     distract.distractLimit--;
  287.                     return true;
  288.                 }
  289.             }
  290.  
  291.             return false;
  292.         }
  293.  
  294.         /// <summary>
  295.         /// Heads towards the current distraction
  296.         /// </summary>
  297.         private bool headToDistraction(Script_ZombieZone.ZombieDistraction distract)
  298.         {
  299.             bool bClearPath = Helpers.calcBresenhemsPredicate(_arena,
  300.                     _state.positionX, _state.positionY, distract.x, distract.y,
  301.                     delegate(LvlInfo.Tile t)
  302.                     {
  303.                         return !t.Blocked;
  304.                     }
  305.                 );
  306.             if (!bClearPath)
  307.                 return false;
  308.  
  309.             //It's clear, let's steer towards it
  310.             Vector3 distractpos = new Vector3(((float)distract.x) / 100.0, ((float)distract.y) / 100.0, 0);
  311.             steering.steerDelegate = delegate(InfantryVehicle vehicle)
  312.             {
  313.                 Vector3 wander = vehicle.SteerForWander(10.5f);
  314.                 Vector3 seek = vehicle.SteerForSeek(distractpos);
  315.                 return wander + (seek * 10.8f);
  316.             };
  317.  
  318.             if (distract.bStillHostile && _weapon.bEquipped && victim != null)
  319.             {   //Can we shoot?
  320.                 if (_weapon.ableToFire())
  321.                 {
  322.                     int aimResult = _weapon.getAimAngle(victim._state);
  323.  
  324.                     if (_weapon.isAimed(aimResult))
  325.                     {   //Spot on! Fire?
  326.                         _itemUseID = _weapon.ItemID;
  327.                         _weapon.shotFired();
  328.                     }
  329.  
  330.                     steering.bSkipAim = true;
  331.                     steering.angle = aimResult;
  332.                 }
  333.                 else
  334.                     steering.bSkipAim = false;
  335.             }
  336.  
  337.             return true;
  338.         }
  339.  
  340.         #region Steer Delegates
  341.         /// <summary>
  342.         /// Steers the zombie along the defined path
  343.         /// </summary>
  344.         public Vector3 steerAlongPath(InfantryVehicle vehicle)
  345.         {       //Are we at the end of the path?
  346.             if (_pathTarget >= _path.Count)
  347.             {   //Invalidate the path
  348.                 _path = null;
  349.                 _tickLastPath = 0;
  350.                 return Vector3.Zero;
  351.             }
  352.  
  353.             //Find the nearest path point
  354.             Vector3 point = _path[_pathTarget];
  355.  
  356.             //Are we close enough to go to the next?
  357.             if (_pathTarget < _path.Count && vehicle.Position.Distance(point) < 0.8f)
  358.                 point = _path[_pathTarget++];
  359.  
  360.             return vehicle.SteerForSeek(point);
  361.         }
  362.  
  363.         /// <summary>
  364.         /// Moves the zombie on a persuit course towards the player, while keeping seperated from other zombies
  365.         /// </summary>
  366.         public Vector3 steerForPersuePlayer(InfantryVehicle vehicle)
  367.         {
  368.             if (victim == null)
  369.                 return Vector3.Zero;
  370.  
  371.             List<Vehicle> zombies = _arena.getVehiclesInRange(vehicle.state.positionX, vehicle.state.positionY, 400,
  372.                                                                 delegate(Vehicle v)
  373.                                                                 { return (v is ZombieBot); });
  374.             IEnumerable<IVehicle> zombiebots = zombies.ConvertAll<IVehicle>(
  375.                 delegate(Vehicle v)
  376.                 {
  377.                     return (v as ZombieBot).Abstract;
  378.                 }
  379.             );
  380.  
  381.             Vector3 seperationSteer = vehicle.SteerForSeparation(_seperation, -0.707f, zombiebots);
  382.             Vector3 pursuitSteer = vehicle.SteerForPursuit(victim._baseVehicle.Abstract, 0.2f);
  383.  
  384.             return (seperationSteer * 0.6f) + pursuitSteer;
  385.         }
  386.         #endregion
  387.     }
  388. }