U3Games

Games | Desarrollo & Soporte => SAMP | Desarrollo de Servidores => San Andreas Multi Player => SAMP | Filter Scripts => Mensaje iniciado por: Kanis en Jul 30, 2025, 09:38 AM

Título: Plug'N'Play Zombie System by Weponz (2018)
Publicado por: Kanis en Jul 30, 2025, 09:38 AM
FUENTE: https://github.com/Pac0M/Plug-N-Play-Zombie-System

zombies.pwn

/*
Plug'N'Play Zombie System by Weponz (2018)
*/
#define FILTERSCRIPT
#include <a_samp>//Credits: SA-MP
#include <rnpc>//Credits: Mauzen

#define HOLDING(%0) ((newkeys & (%0)) == (%0))
#define PRESSED(%0) (((newkeys & (%0)) == (%0)) && ((oldkeys & (%0)) != (%0)))

//Configuration (YOU MAY EDIT THIS SECTION)
#define MAX_ZOMBIES 25//Maximum amount of zombies to spawn. (Default: 25)

#define ZOMBIE_SKIN 162//Zombie skin id. (Default: 162)
#define ZOMBIE_COLOUR 0xFF0000FF//Zombie colour. (Default: Red)
#define ZOMBIE_DAMAGE 20//Zombie damage. (Default: 20)
#define ZOMBIE_DETECT 25//Zombie detection range. (Default: 25)

//DO NOT EDIT BELOW THIS LINE!!!
#define MAX_MOVEMENT 6
#define MAX_ROAM 10

#define RUNNER_ZOMBIE 0
#define SPRINTER_ZOMBIE 1

forward OnZombieCreate();
forward OnZombieUpdate();

forward ResetDetectRange(playerid);
forward ResetZombieKill(playerid);

forward RemoveZombieBody(npcid);

enum server_data
{
server_zombies,
server_zombietimer
};
new ServerData[server_data];

enum zombie_data
{
zombie_species,
zombie_victim,
zombie_roam,
zombie_movement
};
new ZombieData[MAX_ZOMBIES][zombie_data];

enum victim_data
{
victim_detect,
victim_timer,
victim_status,
victim_kill
};
new VictimData[MAX_PLAYERS][victim_data];

stock GetZombieVictim(npcid)
{
for(new i = 0; i < MAX_PLAYERS; i++)
{
    if(IsPlayerConnected(i) && !IsPlayerNPC(i) && IsPlayerSpawned(i))
    {
        new Float:pos[3], Float:pos2[3];
GetPlayerPos(npcid, pos[0], pos[1], pos[2]);
GetPlayerPos(i, pos2[0], pos2[1], pos2[2]);
if(IsPlayerInRangeOfPoint(i, VictimData[i][victim_detect], pos[0], pos[1], pos[2]) && GetPlayerState(i) == PLAYER_STATE_ONFOOT)
{
    return GetClosestVictim(npcid);
}
    }
}
return INVALID_PLAYER_ID;
}

stock GetClosestVictim(npcid)
{
    new Float:dist = 1000.0, target = INVALID_PLAYER_ID, Float:pos[3], Float:pos2[3], Float:tmpdis;
    GetPlayerPos(npcid, pos[0], pos[1], pos[2]);
    for(new i = 0; i < MAX_PLAYERS; i++)
    {
        if(!IsPlayerConnected(i) || IsPlayerNPC(i) || i == npcid || !IsPlayerSpawned(i)) continue;
        GetPlayerPos(i, pos2[0], pos2[1], pos2[2]);
        tmpdis = floatsqroot(floatpower(floatabs(floatsub(pos2[0], pos[0])), 2) + floatpower(floatabs(floatsub(pos2[1], pos[1])), 2) + floatpower(floatabs(floatsub(pos2[2], pos[2])), 2));
        if(tmpdis < dist && GetPlayerState(i) == PLAYER_STATE_ONFOOT)
        {
            dist = tmpdis;
            target = i;
        }
    }
    return target;
}

stock GetRandomPlayer()
{
    new players[MAX_PLAYERS], online = 0;
    for(new i = 0; i < MAX_PLAYERS; i++)
    {
    if(!IsPlayerNPC(i) && IsPlayerConnected(i))
        {
players[online] = i;
          online++;
        }
    }

    if(online > 0)
    {
        return players[random(online)];
    }
    return INVALID_PLAYER_ID;
}

stock GetOnlinePlayers()
{
new count = 0;
for(new i = 0; i < MAX_PLAYERS; i++)
{
  if(IsPlayerConnected(i) && !IsPlayerNPC(i))
  {
count++;
}
}
return count;
}

stock bool:IsZombieStranded(npcid)
{
new Float:pos[3];
GetPlayerPos(npcid, pos[0], pos[1], pos[2]);

for(new i = 0; i < MAX_PLAYERS; i++)
{
    if(!IsPlayerConnected(i) || IsPlayerNPC(i)) continue;
    if(IsPlayerInRangeOfPoint(i, 300.0, pos[0], pos[1], pos[2]))
    {
    return false;
    }
}
return true;
}

stock IsHoldingFirearm(playerid)
{
if(GetPlayerWeapon(playerid) == 30) { return 1; }
else if(GetPlayerWeapon(playerid) == 31) { return 1; }
else if(GetPlayerWeapon(playerid) == 32) { return 1; }
else if(GetPlayerWeapon(playerid) == 22) { return 1; }
else if(GetPlayerWeapon(playerid) == 23) { return 1; }
else if(GetPlayerWeapon(playerid) == 24) { return 1; }
else if(GetPlayerWeapon(playerid) == 33) { return 1; }
else if(GetPlayerWeapon(playerid) == 34) { return 1; }
else if(GetPlayerWeapon(playerid) == 25) { return 1; }
else if(GetPlayerWeapon(playerid) == 27) { return 1; }
else if(GetPlayerWeapon(playerid) == 26) { return 1; }
else if(GetPlayerWeapon(playerid) == 28) { return 1; }
else if(GetPlayerWeapon(playerid) == 29) { return 1; }
return 0;
}

stock IsPlayerSpawned(playerid)
{
new pState = GetPlayerState(playerid);
return 0 <= playerid <= MAX_PLAYERS && pState != PLAYER_STATE_NONE && pState != PLAYER_STATE_WASTED && pState != PLAYER_STATE_SPECTATING;
}

public OnFilterScriptInit()
{
    for(new i = 0; i < MAX_ZOMBIES; i++)
{
    ZombieData[i][zombie_species] = RUNNER_ZOMBIE;
    ZombieData[i][zombie_victim] = INVALID_PLAYER_ID;
    ZombieData[i][zombie_movement] = 0;
}

ServerData[server_zombies] = 0;
ServerData[server_zombietimer] = SetTimer("OnZombieCreate", 80, true);//Just incase, as some servers require you to do this.

SetTimer("OnZombieUpdate", 1000, true);
return 1;
}

public OnPlayerSpawn(playerid)
{
if(IsPlayerNPC(playerid))
{
    new players = GetOnlinePlayers(), targetid = GetRandomPlayer(), position = random(10), Float:pos[3], health = random(25) + 15;
if(players > 0 && targetid != INVALID_PLAYER_ID)
{
GetPlayerPos(targetid, pos[0], pos[1], pos[2]);

ClearAnimations(playerid);

SetPlayerPos(playerid, pos[0], pos[1], pos[2] + 500.0);
SetPlayerInterior(playerid, 0);
SetPlayerVirtualWorld(playerid, 0);

if(position == 0) { SetPlayerPos(playerid, pos[0] + 100.0, pos[1], pos[2] + 500.00); }
else if(position == 1) { SetPlayerPos(playerid, pos[0], pos[1] + 100.0, pos[2] + 500.00); }
else if(position == 2) { SetPlayerPos(playerid, pos[0] - 100.0, pos[1], pos[2] + 500.00); }
else if(position == 3) { SetPlayerPos(playerid, pos[0], pos[1] - 100.0, pos[2] + 500.00); }
else if(position == 4) { SetPlayerPos(playerid, pos[0] + 150.0, pos[1], pos[2] + 500.00); }
else if(position == 5) { SetPlayerPos(playerid, pos[0], pos[1] + 150.0, pos[2] + 500.00); }
else if(position == 6) { SetPlayerPos(playerid, pos[0] - 150.0, pos[1], pos[2] + 500.00); }
else { SetPlayerPos(playerid, pos[0], pos[1] - 150.0, pos[2] + 500.00); }
}
else
{
ClearAnimations(playerid);

SetPlayerPos(playerid, 0.0, 0.0, 0.0 + 500.00);
SetPlayerInterior(playerid, 0);
SetPlayerVirtualWorld(playerid, 0);

if(position == 0) { SetPlayerPos(playerid, 0.0 + 100.0, 0.0, 0.0 + 500.00); }
else if(position == 1) { SetPlayerPos(playerid, 0.0, 0.0 + 100.0, 0.0 + 500.00); }
else if(position == 2) { SetPlayerPos(playerid, 0.0 - 100.0, 0.0, 0.0 + 500.00); }
else if(position == 3) { SetPlayerPos(playerid, 0.0, 0.0 - 100.0, 0.0 + 500.00); }
else if(position == 4) { SetPlayerPos(playerid, 0.0 + 150.0, 0.0, 0.0 + 500.00); }
else if(position == 5) { SetPlayerPos(playerid, 0.0, 0.0 + 150.0, 0.0 + 500.00); }
else if(position == 6) { SetPlayerPos(playerid, 0.0 - 150.0, 0.0, 0.0 + 500.00); }
}

SetRNPCHealth(playerid, health);
SetPlayerSkin(playerid, ZOMBIE_SKIN);
SetPlayerColor(playerid, ZOMBIE_COLOUR);

RNPC_SetShootable(playerid, 1);
RNPC_ToggleVehicleCollisionCheck(playerid, 1);

ZombieData[playerid][zombie_victim] = INVALID_PLAYER_ID;

    ZombieData[playerid][zombie_roam] = 0;
    ZombieData[playerid][zombie_movement] = 0;
}
else if(!IsPlayerNPC(playerid))
{
    VictimData[playerid][victim_status] = 0;
    VictimData[playerid][victim_detect] = ZOMBIE_DETECT;
}
return 1;
}

public OnPlayerDeath(playerid, killerid, reason)
{
    if(IsPlayerNPC(killerid))
{
new health = random(25) + 15;
SetRNPCHealth(killerid, health);
ApplyAnimation(killerid, "BOMBER", "BOM_Plant", 4.1, 0, 1, 1, 1, 0, 1);
SendDeathMessage(killerid, ZombieData[killerid][zombie_victim], reason);
ZombieData[killerid][zombie_victim] = INVALID_PLAYER_ID;
}
return 1;
}

public OnPlayerKeyStateChange(playerid, newkeys, oldkeys)
{
if(!IsPlayerNPC(playerid))
    {
if(PRESSED(KEY_JUMP) && GetPlayerState(playerid) == PLAYER_STATE_ONFOOT)//Shift
{
    if(VictimData[playerid][victim_status] == 0)
    {
    VictimData[playerid][victim_detect] = (ZOMBIE_DETECT * 2);
VictimData[playerid][victim_status] = 1;
VictimData[playerid][victim_timer] = SetTimerEx("ResetDetectRange", 25000, false, "i", playerid);
}
return 1;
}

        if(HOLDING(KEY_SPRINT) && GetPlayerState(playerid) == PLAYER_STATE_ONFOOT)//Space
{
    if(VictimData[playerid][victim_status] == 0)
    {
    VictimData[playerid][victim_detect] = (ZOMBIE_DETECT * 2);
VictimData[playerid][victim_status] = 1;
VictimData[playerid][victim_timer] = SetTimerEx("ResetDetectRange", 25000, false, "i", playerid);
}
return 1;
}

if(HOLDING(KEY_FIRE) && GetPlayerState(playerid) == PLAYER_STATE_ONFOOT)//LMB
{
if(IsHoldingFirearm(playerid) == 1)
{
    if(GetPlayerWeapon(playerid) != 23)
    {
VictimData[playerid][victim_detect] = (ZOMBIE_DETECT * 4);
if(VictimData[playerid][victim_status] == 1) { KillTimer(VictimData[playerid][victim_timer]); }
VictimData[playerid][victim_status] = 1;
VictimData[playerid][victim_timer] = SetTimerEx("ResetDetectRange", 25000, false, "i", playerid);
}
}
return 1;
}
}
return 1;
}

public OnRNPCDeath(npcid, killerid, reason)
{
    if(killerid != INVALID_PLAYER_ID)
{
if(VictimData[killerid][victim_kill] != npcid)
{
VictimData[killerid][victim_kill] = npcid;
SetTimerEx("ResetZombieKill", 4000, false, "i", killerid);
SendDeathMessage(killerid, npcid, reason);
    }
}

SetPlayerColor(npcid, 0xFFFFFF00);

    ApplyAnimation(npcid, "PED", "KO_shot_front", 4.1, 0, 0, 0, 1, 0);
    SetTimerEx("RemoveZombieBody", 10000, false, "i", npcid);
return 1;
}

public ResetDetectRange(playerid)
{
    VictimData[playerid][victim_status] = 0;
    VictimData[playerid][victim_detect] = ZOMBIE_DETECT;
return 1;
}

public ResetZombieKill(playerid)
{
    VictimData[playerid][victim_kill] = INVALID_PLAYER_ID;
return 1;
}

public RemoveZombieBody(npcid)
{
RespawnRNPC(npcid);
return 1;
}

public OnZombieCreate()
{
RNPC_SetUpdateRate(80);

    MapAndreas_Init(MAP_ANDREAS_MODE_NOBUFFER);

new type = random(4), name[MAX_PLAYER_NAME], zombieid = ServerData[server_zombies];
if(type == SPRINTER_ZOMBIE)
{
ZombieData[zombieid][zombie_species] = SPRINTER_ZOMBIE;
}
else
{
ZombieData[zombieid][zombie_species] = RUNNER_ZOMBIE;
}

ZombieData[zombieid][zombie_victim]= INVALID_PLAYER_ID;

format(name, sizeof(name), "Zombie_%i", zombieid + 1);
ConnectRNPC(name);

ServerData[server_zombies]++;

if(ServerData[server_zombies] >= MAX_ZOMBIES)
{
KillTimer(ServerData[server_zombietimer]);
printf("Number of zombies created: %i", ServerData[server_zombies]);
}
return 1;
}

public OnZombieUpdate()
{
for(new i = 0; i < MAX_ZOMBIES; i++)
{
if(IsPlayerConnected(i) || IsPlayerNPC(i))
{
if(GetRNPCHealth(i) > 0)
{
new victimid, Float:pos[3];
victimid = GetZombieVictim(i);
GetPlayerPos(i, pos[0], pos[1], pos[2]);

if(victimid != INVALID_PLAYER_ID)//Attack
  {
if(IsPlayerInRangeOfPoint(victimid, VictimData[victimid][victim_detect], pos[0], pos[1], pos[2]))
{
if(IsPlayerInRangeOfPoint(victimid, 1.0, pos[0], pos[1], pos[2]))
{
ZombieData[i][zombie_victim] = victimid;

ZombieData[i][zombie_movement] = 0;
ZombieData[i][zombie_roam] = 0;

RNPC_CreateBuild(i, PLAYER_RECORDING_TYPE_ONFOOT);
RNPC_AddPause(100);
RNPC_SetKeys(KEY_FIRE);
RNPC_AddPause(100);
RNPC_SetKeys(0);
RNPC_FinishBuild();
RNPC_StartBuildPlayback(i);

new Float:health;
GetPlayerHealth(victimid, health);
SetPlayerHealth(victimid, health - ZOMBIE_DAMAGE);

GameTextForPlayer(victimid, "~r~You are being bitten!", 3000, 5);
continue;
}
else
{
ZombieData[i][zombie_movement] = 0;
ZombieData[i][zombie_roam] = 0;

GetPlayerPos(victimid, pos[0], pos[1], pos[2]);

if(ZombieData[i][zombie_species] == SPRINTER_ZOMBIE)
{
MoveRNPC(i, pos[0], pos[1], pos[2], RNPC_SPEED_SPRINT, 1);
}
else
{
MoveRNPC(i, pos[0], pos[1], pos[2], RNPC_SPEED_RUN, 1);
}
continue;
}
}
}
else if(victimid == INVALID_PLAYER_ID)//Roam
{
    if(ZombieData[i][zombie_roam] == 0)
    {
ZombieData[i][zombie_roam]++;
        ZombieData[i][zombie_victim] = INVALID_PLAYER_ID;

RNPC_SetKeys(0);

new point = random(6);
if(point == 0) { pos[0] = pos[0] + 100.0; }
else if(point == 1) { pos[0] = pos[0] - 100.0; }
else if(point == 2) { pos[1] = pos[1] + 100.0; }
else if(point == 3) { pos[1] = pos[1] - 100.0; }

else if(point == 4) { pos[0] = pos[0] + 100.0; pos[1] = pos[1] + 100.0; }
else if(point == 5) { pos[0] = pos[0] - 100.0; pos[1] = pos[1] - 100.0; }

MoveRNPC(i, pos[0], pos[1], pos[2], RNPC_SPEED_WALK, 1);
continue;
    }
    else
    {
ZombieData[i][zombie_roam]++;

if(ZombieData[i][zombie_roam] >= MAX_ROAM)
{
ZombieData[i][zombie_roam] = 0;
ZombieData[i][zombie_victim] = INVALID_PLAYER_ID;

RNPC_SetKeys(0);

new point = random(6);
if(point == 0) { pos[0] = pos[0] + 100.0; }
else if(point == 1) { pos[0] = pos[0] - 100.0; }
else if(point == 2) { pos[1] = pos[1] + 100.0; }
else if(point == 3) { pos[1] = pos[1] - 100.0; }

else if(point == 4) { pos[0] = pos[0] + 100.0; pos[1] = pos[1] + 100.0; }
else if(point == 5) { pos[0] = pos[0] - 100.0; pos[1] = pos[1] - 100.0; }

MoveRNPC(i, pos[0], pos[1], pos[2], RNPC_SPEED_WALK, 1);

            ZombieData[i][zombie_movement]++;

if(ZombieData[i][zombie_movement] >= MAX_MOVEMENT && IsZombieStranded(i) == true)
{
ZombieData[i][zombie_movement] = 0;
SetRNPCHealth(i, 0.0);
}
continue;
}
}
}
}
}
}
return 1;
}