[Include] Cops
#1

COPS

current version (v1.0)

This include creates cop ai, they will kill anyone who is wanted, they can detect crimes like if player shoot, if player damage other player or a cop, if player killed someone, however for now they only follow wanted players otherwise they just stand, and they cant drive (will add later), no melee support yet.
How to include:

Code:
#define FILTERSCRIPT 
#include <a_samp>
#include <fcnpc>
#include <cops> //requires fcnpc 2.0.0
Crime types:

Code:
CRIME_KILL 0 //called only if you kill players, for cops use oncopdeath
CRIME_SHOOT 1 
CRIME_DAMAGE 2 //called only if you shoot players, for cops use oncoptakedamage
Functions:

Code:
native CreateCop(skinid, name[], Float:detection_area, Float:health, Float:x, Float:y, Float:z, Float:angle, weapon, Float:accuracy);
native IsCopDead(cop_id);
native IsCopInvulnerable(cop_id);
native IsCopMoving(cop_id);
native IsCopValid(cop_id);
native GetCopHealth(cop_id);
native GetCopTarget(cop_id);
native GetClosestPlayerToCop(cop_id);
native GetCopDetectionArea(cop_id);
native GetCopPos(cop_id, &Float:x, &Float:y, &Float:z);
native GetCopAngle(cop_id, &Float:angle);
native GetCopCreationPos(cop_id, &Float:x, &Float:y, &Float:z);
native GetCopCreationAngle(cop_id, &Float:angle);
native GetCopInterior(cop_id);
native GetCopVirtualWorld(cop_id);
native GetCopSkin(cop_id);
native GetCopCustomSkin(cop_id);
native GetCopWeapon(cop_id);
native SetCopWeapon(cop_id, weaponid);
native SetCopInvulnerable(cop_id, bool:invulnerable);
native SetCopSkin(cop_id, skinid);
native SetCopInterior(cop_id, interiorid);
native SetCopVirtualWorld(cop_id, worldid);
native SetCopHealth(cop_id, Float:health);
native RespawnCop(cop_id);
native DestroyCop(cop_id);
Callbacks:

Code:
OnCopDeath(cop_id, killerid, weaponid);
OnCopTakeDamage(cop_id, damagerid, weaponid, bodypart, Float:health_loss);
OnCopKillPlayer(cop_id, playerid);
OnCrimeHappenNearCop(playerid, crime);
Example:

PHP Code:
#define FILTERSCRIPT
#include <a_samp>
#include <fcnpc>
#include <cops>
#include <zcmd>
new cop;
CMD:cop(playerid)
{
    new 
Float:xFloat:yFloat:z;
    if(!
IsCopValid(cop)) //you could do without the check as well the include checks if cop allready exist
    
{
        
GetPlayerPos(playeridxyz);
        
cop CreateCop(284"Cop01"45.0100.0x+4yz, -1221.0);
    }
    return 
1;
}
CMD:dcop(playerid)
{
    if(
IsCopValid(cop)) //could do without the check as well
    
{
        
DestroyCop(cop);
    }
    return 
1;
}
public 
OnCrimeHappenNearCop(playeridcrime)
{
    switch(
crime)
    {
        case 
CRIME_KILL:
        {
            if(
GetPlayerWantedLevel(playerid) < 5)
            {
                
SetPlayerWantedLevel(playerid5);
            }
        }
        case 
CRIME_SHOOT:
        {
            if(
GetPlayerWantedLevel(playerid) < 2)
            {
                
SetPlayerWantedLevel(playerid2);
            }
        }
        case 
CRIME_DAMAGE:
        {
            if(
GetPlayerWantedLevel(playerid) < 3)
            {
                
SetPlayerWantedLevel(playerid3);
            }
        }
    }
    return 
1;
}
public 
OnCopKillPlayer(cop_idplayerid)
{
    if(
GetPlayerWantedLevel(playerid) > 1)
    {
        
SetPlayerWantedLevel(playerid0);
    }
    return 
1;

Video: Click here

Download: Click here

requires:

fcnpc 2.0.0


Bugs:

If you find any bugs please report them and i will fix them in the next update!


Credits:

SA-MP team - a_samp
ZIGGI - fcnpc
Lokii - cops
Pottus - colandreas & optimizing
Crayder - colandreas
Reply
#2

Dont have time to look it over but IsValidCop has no array bounds checking
Reply
#3

Quote:
Originally Posted by Pottus
View Post
Dont have time to look it over but IsValidCop has no array bounds checking
Updated.
Reply
#4

Nice idea.
Reply
#5

Quote:
Originally Posted by Hazon
View Post
Nice idea.
Thanks
Reply
#6

Good job!
Reply
#7

Quote:
Originally Posted by Lucky13
View Post
Good job!
Thx
Reply
#8

Good job i like this!
Reply
#9

Quote:
Originally Posted by N0FeaR
View Post
Good job i like this!
Thank you
Reply
#10

Okay here we go.

Should be static to maintain encapsulation. Shouldn't be able to be modified outside of include unless calling functions directly.
Code:
new e_cops[MAX_COPS][ee_cops];
IsCopValid() should return 1 if successful. There are other functions with this problem as well.
Code:
stock GetCopCreationPos(cop_id, &Float:x, &Float:y, &Float:z)
{
    if(IsCopValid(cop_id))
    {
        x = e_cops[cop_id][cop_pos_x];
        y = e_cops[cop_id][cop_pos_y];
        z = e_cops[cop_id][cop_pos_z];
    }
    return 0;
}
Why bother calling so many functions before checking if the NPC is actually valid? Check if the NPC is valid first then create.

Code:
CreateCop()[
......
	new id;
    for(new i = 0; i < MAX_COPS; i++)
    {
        if(IsCopValid(i)) continue;
        
        id = FCNPC_Create(name);
        
        if(FCNPC_IsValid(e_cops[i][copid]))
        {
	        e_cops[i][copid] = id;
	        FCNPC_Spawn(e_cops[i][copid], skinid, x, y, z);
	        FCNPC_SetHealth(e_cops[i][copid], health);
	        FCNPC_SetAngle(e_cops[i][copid], angle);
	        FCNPC_SetWeaponAccuracy(e_cops[i][copid], weapon, accuracy);
	        FCNPC_SetWeapon(e_cops[i][copid], weapon);
	        FCNPC_UseInfiniteAmmo(e_cops[i][copid], true);
	        e_cops[i][cop_pos_x] = x;
	        e_cops[i][cop_pos_y] = y;
	        e_cops[i][cop_pos_z] = z;
	        e_cops[i][cop_angle] = angle;
	        e_cops[i][cop_detection] = detection_area;
	        e_cops[i][cop_target] = 0xFFFF;
	        e_cops[i][cop_exist] = true;
			return i;
		}
    }
    return 0xFFFF;
Missing array bounds checking.
Code:
GetCopTarget(cop_id)
{
    return e_cops[cop_id][cop_target];
}
Why are you calling this function twice?
Code:
            if(GetPlayerDistanceFromPoint(i, x, y, z) >= last) continue;
            last = GetPlayerDistanceFromPoint(i, x, y, z);
Code:
new Float:tmp;
for(new i = 0, j = GetPlayerPoolSize(); i <= j; i++)
{
    if(!IsPlayerConnected(i) || IsPlayerNPC(i)) continue;
	tmp = GetPlayerDistanceFromPoint(i, x, y, z);
	if(tmp >= last) continue;
	last = tmp;
    id = i;
}
Major fuck-up here.
Code:
public FCNPC_OnUpdate(npcid)
{
    new Float:x, Float:y, Float:z;
    for(new k = 0; k < MAX_COPS; k++)
    {
I don't even see npcid used at all, you are basically using this callback like a timer! That means you are doing as many times more work as the number of cops that are spawned!

Why bother doing anything until you check if the killerid is an NPC?
Code:
public OnPlayerDeath(playerid, killerid, reason)
Reply
#11

Quote:
Originally Posted by Pottus
Посмотреть сообщение
fixed all of these except those:

Major fuck-up here.
Код:
public FCNPC_OnUpdate(npcid)
{
    new Float:x, Float:y, Float:z;
    for(new k = 0; k < MAX_COPS; k++)
    {
I don't even see npcid used at all, you are basically using this callback like a timer! That means you are doing as many times more work as the number of cops that are spawned!

Why bother doing anything until you check if the killerid is an NPC?
Код:
public OnPlayerDeath(playerid, killerid, reason)
1. e_cops[npcid][copid] could be invalid cop, or maybe i got you wrong
2. i check if killer is player then call crime_kill if cop npc killed player i call oncopkillplayer
Reply
#12

i think that you should use more includes in your include, that would make it more readable, for example y_hooks, y_iterate
function names could also be a little bit better
Reply
#13

Quote:
Originally Posted by codExpert
Посмотреть сообщение
i think that you should use more includes in your include, that would make it more readable, for example y_hooks, y_iterate
function names could also be a little bit better
for some reason y_hooks doesnt work on fcnpc callbacks, and sorry for function names english is not my native language.
Reply
#14

Yeah I see what you mean I guess I overlooked this line.
Код:
if(e_cops[k][copid] != npcid) continue;
Anyways that brings me to another point. You can eliminate most of your loops which find the correct NPC very easily.
All you need to do is create a reference array.

Код:
g_CopReferences[MAX_PLAYERS] = { -1, ... };
Then what you do is when creating an NPC simply set copid to the index of NPCID

Код:
e_cops[i][copid] = FCNPC_Create(name);
 g_CopReferences[e_cops[i][copid]] = i;
Now all those loops become this.

Old way
Код:
    for(new i = 0; i < MAX_COPS; i++)
    {
        if(!IsCopValid(i) || e_cops[i][copid] != npcid) continue;
        CallLocalFunction("OnCopDeath", "iii", i, killerid, reason);
    }


New way
Код:
// Yes this is a cop!
if(g_CopReferences[npcid] != -1)
      CallLocalFunction("OnCopDeath", "iii", g_CopReferences[npcid], killerid, reason);
Reply
#15

Quote:
Originally Posted by Pottus
Посмотреть сообщение
Yeah I see what you mean I guess I overlooked this line.
Код:
if(e_cops[k][copid] != npcid) continue;
Anyways that brings me to another point. You can eliminate most of your loops which find the correct NPC very easily.
All you need to do is create a reference array.

Код:
g_CopReferences[MAX_PLAYERS] = { -1, ... };
Then what you do is when creating an NPC simply set copid to the index of NPCID

Код:
e_cops[i][copid] = FCNPC_Create(name);
 g_CopReferences[e_cops[i][copid]] = i;
Now all those loops become this.

Old way
Код:
    for(new i = 0; i < MAX_COPS; i++)
    {
        if(!IsCopValid(i) || e_cops[i][copid] != npcid) continue;
        CallLocalFunction("OnCopDeath", "iii", i, killerid, reason);
    }


New way
Код:
// Yes this is a cop!
if(g_CopReferences[npcid] != -1)
      CallLocalFunction("OnCopDeath", "iii", g_CopReferences[npcid], killerid, reason);
Ok thank you will update once im on the pc
Reply
#16

Updated

Download: Click here
Reply


Forum Jump:


Users browsing this thread: 1 Guest(s)