Advertisement
Mauzen

RNPC Police AI include

Jul 11th, 2012
4,219
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Pawn 7.46 KB | None | 0 0
  1. /**
  2.  * RNPC Police include
  3.  * Simple AI and tutorial script
  4.  * Mauzen, 10.7.2012, V1.0
  5.  */
  6. #include <RNPC>
  7.  
  8. #define RPOL_MAX_WAYPOINTS          (12)    // Maximum number of waypoints for a policeman
  9. #define RPOL_VISIONRANGE            (25.0)  // Attacking players in that range will be chased
  10. #define RPOL_ATTACKRANGE            (15.0)  // Policeman starts firing when in this range to the player
  11. #define MAX_RNPC_POLICE             (8)     // Max number of police officers
  12. #define RPOL_UPDATE                 (200)   // Interval in ms to update movements, attacks, etc
  13.  
  14. // The enum containing all data for a single policeman
  15. enum RPol_enum {
  16.             RPOL_NPCID,
  17.             RPOL_TIMER,
  18.     Float:  RPOL_WAYPOINTS_X[RPOL_MAX_WAYPOINTS],
  19.     Float:  RPOL_WAYPOINTS_Y[RPOL_MAX_WAYPOINTS],
  20.     Float:  RPOL_WAYPOINTS_Z[RPOL_MAX_WAYPOINTS],
  21.             RPOL_WPINDEX,
  22.             RPOL_NEXTWP,
  23.             RPOL_CURTARGET,
  24.             RPOL_SKIN
  25. };
  26.  
  27. // Initial data
  28. new rpol[MAX_RNPC_POLICE][RPol_enum] = {{-1, -1, 0.0, 0.0, 0.0, 0, 0, -1}, {-1, -1, 0.0, 0.0, 0.0, 0, 0, -1},
  29.     {-1, -1, 0.0, 0.0, 0.0, 0, 0, -1}, {-1, -1, 0.0, 0.0, 0.0, 0, 0, -1}, {-1, -1, 0.0, 0.0, 0.0, 0, 0, -1},
  30.     {-1, -1, 0.0, 0.0, 0.0, 0, 0, -1}, {-1, -1, 0.0, 0.0, 0.0, 0, 0, -1}, {-1, -1, 0.0, 0.0, 0.0, 0, 0, -1} };
  31.  
  32. // Creates a new policeman
  33. stock CreateRNPCPolice(name[], skin)
  34. {
  35.     // Find a free spot in the rpol array
  36.     new slot = -1;
  37.     for (new i = 0; i < MAX_RNPC_POLICE; i++) {
  38.         if (rpol[i][RPOL_NPCID] == -1) {
  39.             slot = i;
  40.             break;
  41.         }
  42.     }
  43.     if (slot == -1) return -1;
  44.    
  45.     // Connect the NPC
  46.     rpol[slot][RPOL_NPCID] = ConnectRNPC(name);
  47.     rpol[slot][RPOL_SKIN] = skin;
  48.     return slot;
  49. }
  50.  
  51. // Adds a waypoint to the Policeman's path
  52. stock AddRPOLWaypoint(rpolid, Float:x, Float:y, Float:z) {
  53.     if (rpol[rpolid][RPOL_NPCID] == -1) return false;
  54.     if (rpol[rpolid][RPOL_WPINDEX] >= RPOL_MAX_WAYPOINTS) return false;
  55.     // Store the waypoint coordinates at the last free position
  56.     new slot = rpol[rpolid][RPOL_WPINDEX]
  57.     rpol[rpolid][RPOL_WAYPOINTS_X][slot] = x;
  58.     rpol[rpolid][RPOL_WAYPOINTS_Y][slot] = y;
  59.     rpol[rpolid][RPOL_WAYPOINTS_Z][slot] = z;
  60.    
  61.     rpol[rpolid][RPOL_WPINDEX]++;
  62.     return true;
  63. }
  64.  
  65. stock StartRPOLRoute(rpolid)
  66. {
  67.     // If valid and not already walking
  68.     if (rpol[rpolid][RPOL_TIMER] == -1 && rpol[rpolid][RPOL_NPCID] != -1) {
  69.         rpol[rpolid][RPOL_TIMER] = SetTimerEx("WatchTimer", RPOL_UPDATE, 1, "i", rpolid);
  70.         // Move to the first waypoint
  71.         MoveRNPC(rpol[rpolid][RPOL_NPCID], rpol[rpolid][RPOL_WAYPOINTS_X][0], rpol[rpolid][RPOL_WAYPOINTS_Y][0],
  72.                 rpol[rpolid][RPOL_WAYPOINTS_Z][0], RNPC_SPEED_RUN);
  73.         return true;
  74.     }
  75.     return 0;
  76. }
  77.  
  78. stock RemoveRNPCPolice(rpolid)
  79. {
  80.     if (rpol[rpolid][RPOL_TIMER] > -1) {
  81.         // Stop timer
  82.         KillTimer(rpol[slot][RPOL_TIMER]);
  83.     }
  84.     // Kick the NPC
  85.     Kick(rpol[rpolid][RPOL_NPCID];
  86.     // Reset data
  87.     rpol[rpolid] = {-1, -1, 0.0, 0.0, 0.0, 0, 0, -1};
  88. }
  89.  
  90. // This is the timer that actually controls the policeman
  91. // and so the actually interesting "KI" for the RNPC
  92. forward WatchTimer(id);
  93. public WatchTimer(id) {
  94.     if (rpol[id][RPOL_CURTARGET] > -1) {
  95.         new Float:x, Float:y, Float:z;
  96.         GetPlayerPos(rpol[id][RPOL_CURTARGET], x, y ,z);
  97.         if (!IsPlayerInRangeOfPoint(rpol[id][RPOL_NPCID], RPOL_VISIONRANGE * 2.0, x, y, z)
  98.             || GetPlayerState(rpol[id][RPOL_CURTARGET]) != PLAYER_STATE_ONFOOT) {
  99.             // Target escaped or died
  100.             // Stop shooting
  101.             RNPC_SetKeys(0);
  102.             // Continue route
  103.             MoveRNPC(rpol[id][RPOL_NPCID], rpol[id][RPOL_WAYPOINTS_X][rpol[id][RPOL_NEXTWP]],
  104.                 rpol[id][RPOL_WAYPOINTS_Y][rpol[id][RPOL_NEXTWP]], rpol[id][RPOL_WAYPOINTS_Z][rpol[id][RPOL_NEXTWP]],
  105.                 RNPC_SPEED_RUN);
  106.             rpol[id][RPOL_CURTARGET] = -1;
  107.             return;
  108.         } else
  109.         if (IsPlayerInRangeOfPoint(rpol[id][RPOL_NPCID], RPOL_ATTACKRANGE, x, y, z)) {
  110.             // Target is in attackrange
  111.             // Stop running and start shhoting
  112.             new Float:ox, Float:oy, Float:oz;
  113.             GetPlayerPos(rpol[id][RPOL_NPCID], ox, oy, oz);
  114.             // Angle to the target
  115.             new Float:angle = atan2(ox - x, oy - y) + 180.0;
  116.             // Stop and build, alternate slot for security
  117.             RNPC_StopPlayback(rpol[id][RPOL_NPCID]);
  118.             RNPC_CreateBuild(rpol[id][RPOL_NPCID], PLAYER_RECORDING_TYPE_ONFOOT, 1);
  119.             // Set weapon
  120.             RNPC_SetWeaponID(22);
  121.             // Set facing angle to the target
  122.             RNPC_SetAngleQuats(0.0, angle, 0.0);
  123.             // Start firing
  124.             RNPC_SetKeys(KEY_FIRE);
  125.             // Move towards the target from the current position
  126.             RNPC_ConcatMovement(x, y, z, RNPC_SPEED_RUN);
  127.             // Finish build
  128.             RNPC_FinishBuild();
  129.            
  130.             // Start playback
  131.             RNPC_StartBuildPlayback(id, 1);
  132.            
  133.         } else {
  134.             // Stop shooting
  135.             RNPC_SetKeys(0);
  136.             // Move towards the targets
  137.             MoveRNPC(rpol[id][RPOL_NPCID], x, y, z, RNPC_SPEED_RUN);
  138.         }
  139.     }
  140. }
  141.  
  142. // Hook OnNPCPlaybackFinished to determine when a NPC reached his current waypoint
  143. public OnRNPCPlaybackFinished(npcid)
  144. {
  145.     // Find the array index of the npc
  146.     new slot = -1;
  147.     for (new i = 0; i < MAX_RNPC_POLICE; i++) {
  148.         if (rpol[i][RPOL_NPCID] == npcid) {
  149.             slot = i;
  150.             break;
  151.         }
  152.     }
  153.     if (slot > -1) {
  154.         // NPC is a RNPC policeman
  155.         if (rpol[slot][RPOL_CURTARGET] == -1) {
  156.             // Increase current waypoint index, and set it to 0 when the last one is reached
  157.             rpol[slot][RPOL_NEXTWP] = (rpol[slot][RPOL_NEXTWP] + 1) % rpol[slot][RPOL_WPINDEX];
  158.             // Make him walk to the next waypoint
  159.             MoveRNPC(rpol[slot][RPOL_NPCID], rpol[slot][RPOL_WAYPOINTS_X][rpol[slot][RPOL_NEXTWP]],
  160.                 rpol[slot][RPOL_WAYPOINTS_Y][rpol[slot][RPOL_NEXTWP]], rpol[slot][RPOL_WAYPOINTS_Z][rpol[slot][RPOL_NEXTWP]],
  161.                 RNPC_SPEED_WALK);
  162.         }
  163.     }
  164.     CallLocalFunction("RNPC_OnRNPCPlaybackFinished", "i", npcid);
  165. }
  166. #if defined _ALS_OnRNPCPlaybackFinished
  167.     #undef OnRNPCPlaybackFinished
  168. #else
  169.     #define _ALS_OnRNPCPlaybackFinished
  170. #endif
  171. #define OnRNPCPlaybackFinished RNPC_OnRNPCPlaybackFinished
  172. forward RNPC_OnRNPCPlaybackFinished(npcid);
  173.  
  174. // Hook OnPlayerKeyStateChange to detect firing players
  175. public OnPlayerKeyStateChange(playerid, newkeys, oldkeys)
  176. {
  177.     // Check if player started firing
  178.     if (!(oldkeys & KEY_FIRE) && (newkeys & KEY_FIRE)) {
  179.         // Check if player holds a gun
  180.         if (GetPlayerWeapon(playerid) > 16 && GetPlayerWeapon(playerid) < 40) {
  181.             new Float:px, Float:py, Float:pz;
  182.             for (new i = 0; i < MAX_RNPC_POLICE; i++) {
  183.                 // Skip invalid and already following npcs
  184.                 if (rpol[i][RPOL_NPCID] == -1 || rpol[i][RPOL_CURTARGET] > -1) continue;
  185.                 GetPlayerPos(rpol[i][RPOL_NPCID], px, py, pz);
  186.                 // If police in in range make him chase the attacking player
  187.                 if (IsPlayerInRangeOfPoint(playerid, RPOL_VISIONRANGE, px, py, pz)) {
  188.                     rpol[i][RPOL_CURTARGET] = playerid;
  189.                 }
  190.             }
  191.         }
  192.     }
  193.     CallLocalFunction("RNPC_OnPlayerKeyStateChange", "iii", playerid, newkeys, oldkeys);
  194. }
  195. #if defined _ALS_OnPlayerKeyStateChange
  196.     #undef OnPlayerKeyStateChange
  197. #else
  198.     #define _ALS_OnPlayerKeyStateChange
  199. #endif
  200. #define OnPlayerKeyStateChange RNPC_OnPlayerKeyStateChange
  201. forward RNPC_OnPlayerKeyStateChange(playerid, newkeys, oldkeys);
  202.  
  203. // Hook OnPlayerSpawn to set the NPCs skin
  204. public OnPlayerSpawn(playerid)
  205. {
  206.     if (IsPlayerNPC(playerid)) {   
  207.         // Find the array index of the npc
  208.         new slot = -1;
  209.         for (new i = 0; i < MAX_RNPC_POLICE; i++) {
  210.             if (rpol[i][RPOL_NPCID] == playerid) {
  211.                 slot = i;
  212.                 break;
  213.             }
  214.         }
  215.         // If playerid is a policeman
  216.         if (slot > -1) {
  217.             SetPlayerSkin(playerid, rpol[slot][RPOL_SKIN]);
  218.         }
  219.     }
  220.     CallLocalFunction("RNPC_OnPlayerSpawn", "i", playerid);
  221. }
  222. #if defined _ALS_OnPlayerSpawn
  223.     #undef OnPlayerSpawn
  224. #else
  225.     #define _ALS_OnPlayerSpawn
  226. #endif
  227. #define OnPlayerSpawn RNPC_OnPlayerSpawn
  228. forward RNPC_OnPlayerSpawn(playerid);
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement