Da immer mehr danach gefragt wird, schreibe ich hier einfach mal ein kleines Tutorial.
Was benötigt wird:
Also fangen wir mal an.
Als erstes muss der BOT connecten, dies macht ihr mit der Funktion "ConnectRNPC" über einen Command.
Außerdem brauchen wir für später noch die ID des NPCs, die von der Funktion returnt wird. Diese legen wir in eine PVar.
Bsp:
new cmd[128], idx;
cmd = strtok(cmdtext, idx);
if(strcmp(cmd, "/cnb", true) == 0)
{
new tmp[128];
tmp = strtok(cmdtext, idx);
if(strlen(tmp) > 0)
{
new npc = ConnectRNPC(tmp);
SetPVarString(npc, "NPCNAME", tmp);
SetPVarInt(npc, "NPCID", npc);
new string[128];
format(string,sizeof(string), "Bot wurde verbunden. (ID: %d | Name: %s)", npc, tmp);
print(string);
}
else
{
SendClientMessage(playerid, 0xFFFFFFFF, "/cnb [BOTNAME]");
}
return 1;
}
Bei Fragen zur Benutzung von Strtok, einfach den Wiki Beitragdurchlesen.
Falls ihr den BOT an einem bestimmten Ort spawnen lassen wollt, könnt ihr dies unter OnPlayerSpawn mit SetPlayerPos machen.
Bsp:
if(IsPlayerNPC(playerid)==1)
{
SetPlayerPos(playerid, -1756.4594, -1976.4883, 92.5628);
}
Jetzt haben wir zwar einen BOT an unserem Wunschort, aber noch keinen Zombie.
Als erstes geben wir dem BOT einen Skin, den wir passend für einen Zombie halten. Das machen wir auch unter OnPlayerSpawn.
Bsp:
if(IsPlayerNPC(playerid)==1)
{
SetPlayerSkin(playerid, 162);
SetPlayerPos(playerid, -1756.4594, -1976.4883, 92.5628);
}
Jetzt müssen wir den BOT noch dazu bringen, euch zu verfolgen.
Dazu brauchen wir einen Timer, der unter OnPlayerStreamIn gestartet, und unter bestimmten Umständen unter OnPlayerStreamOut gestoppt wird.
Wir geben dem BOT unter OnPlayerSpawn erstmal ein PVar, die die Anzahl der Spieler in Reichweite behält.
if(IsPlayerNPC(playerid)==1)
{
SetPlayerSkin(playerid, 162);
SetPlayerPos(playerid, -1756.4594, -1976.4883, 92.5628);
SetPVarInt(playerid, "SpielerInReichweite", 0);
}
Und jetzt unter OnPlayerStreamIn die PVar immer pro Spieler erhöhen.
public OnPlayerStreamIn(playerid, forplayerid)
{
if(IsPlayerNPC(playerid)==0)
{
if(IsPlayerNPC(forplayerid)==1)
{
SetPVarInt(forplayerid, "SpielerInReichweite", GetPVarInt(forplayerid, "SpielerInReichweite") + 1);
}
}
}
Gleichzeitig können wir jetzt schon mal unter OnPlayerStreamOut, die PVar um 1 niedriger machen.
public OnPlayerStreamOut(playerid, forplayerid)
{
if(IsPlayerNPC(playerid)==0)
{
if(IsPlayerNPC(forplayerid)==1)
{
SetPVarInt(forplayerid, "SpielerInReichweite", GetPVarInt(forplayerid, "SpielerInReichweite") - 1);
}
}
}
Jetzt kommen wir zum Timer. Der Timer soll aktiv werden, wenn ein oder mehr Spieler in der Reichweite des BOTs sind. Dies machen wir unter OnPlayerStreamIn.
Diesen Timer müssen wir noch als PVar speichern, damit wir ihn später wieder stoppen können.
public OnPlayerStreamIn(playerid, forplayerid)
{
if(IsPlayerNPC(playerid)==0)
{
if(IsPlayerNPC(forplayerid)==1)
{
SetPVarInt(forplayerid, "SpielerInReichweite", GetPVarInt(forplayerid, "SpielerInReichweite") + 1);
if(GetPVarInt(forplayerid, "SpielerInReichweite") == 1)
{
new tid = SetTimerEx("zombietimer1",1000,true,"i",forplayerid);
SetPVarInt(forplayerid, "zombietimer1ID", tid);
}
}
}
}
Nun können wir den Timer gleich mal forwarden.
Das macht ihr ganz oben unter den Includes.
forward zombietimer1(playerid);
Jetzt kommen wir zum Timer selbst. Um am Timer selbst was machen zu können, müsst ihr das in euer Script schreiben.
public zombietimer1(playerid)
{
}
Als erstes müssen wir mithilfe einer Schleife abfragen, ob ein Spieler in der Nähe des Zombies ist.
public zombietimer1(playerid)
{
new Float:x, Float:y, Float:z;
for(new i=0;i<MAX_PLAYERS;i++)
{
if(IsPlayerNPC(i)==0)
{
GetPlayerPos(i, x,y,z);
if(IsPlayerInRangeOfPoint(playerid, 20.0, x,y,z))
{
}
}
}
}
Jetzt ist noch die Frage, was passiert, wenn ein Spieler in der Reichweite ist.
Wir sollten dem Zombie eine PVar geben, dafür, dass er einen bestimmten Spieler verfolgt und eine PVar für den bestimmten Spieler.
Wozu wir das machen, erkläre ich gleich. Außerdem noch ein Abbruch für die Schleife sobald ein Spieler in Reichweite ist.
public zombietimer1(playerid)
{
new Float:x, Float:y, Float:z;
for(new i=0;i<MAX_PLAYERS;i++)
{
if(IsPlayerNPC(i)==0)
{
GetPlayerPos(i, x,y,z);
if(IsPlayerInRangeOfPoint(playerid, 20.0, x,y,z))
{
SetPVarInt(playerid, "AufVerfolgung", 1);
SetPVarInt(playerid, "VerfolgterSpieler", i);
break;
}
}
}
}
Jetzt müssen wir den Zombie noch bewegen. Dies machen wir mit der Funktion MoveRNPC. Da wir für diese Funktion die ID des BOTs als Parameter brauchen, holen wir uns diese erstmal.
public zombietimer1(playerid)
{
new Float:x, Float:y, Float:z;
for(new i=0;i<MAX_PLAYERS;i++)
{
if(IsPlayerNPC(i)==0)
{
GetPlayerPos(i, x,y,z);
if(IsPlayerInRangeOfPoint(playerid, 20.0, x,y,z))
{
SetPVarInt(playerid, "AufVerfolgung", 1);
SetPVarInt(playerid, "VerfolgterSpieler", i);
MoveRNPC(playerid, x,y,z, 0.004);
break;
}
}
}
}
0.004 ist die angepasste Geschwindigkeit. Damit das alles noch zombiemäßig aussieht, geben wir dem Zombie noch eine Animation.
Außerdem sollten wir jetzt noch zusätzliche Abfragen einbauen, damit er nicht jede Sekunde einen neuen Spieler verfolgt, sondern sich erstmal an den einen hält.
public zombietimer1(playerid)
{
new Float:x, Float:y, Float:z;
if(GetPVarInt(playerid, "AufVerfolgung")==1)
{
GetPlayerPos(GetPVarInt(playerid, "VerfolgterSpieler"),x,y,z);
if(IsPlayerInRangeOfPoint(playerid, 20.0, x,y,z))
{
ApplyAnimation(playerid,"PED","WALK_DRUNK",4.1,1,1,1,1,1,1);
MoveRNPC(playerid, x,y,z, 0.004);
}
else
{
SetPVarInt(playerid, "AufVerfolgung", 0);
}
}
else
{
for(new i=0;i<MAX_PLAYERS;i++)
{
if(IsPlayerNPC(i)==0)
{
GetPlayerPos(i, x,y,z);
if(IsPlayerInRangeOfPoint(playerid, 20.0, x,y,z))
{
SetPVarInt(playerid, "AufVerfolgung", 1);
SetPVarInt(playerid, "VerfolgterSpieler", i);
ApplyAnimation(playerid,"PED","WALK_DRUNK",4.1,1,1,1,1,1,1);
MoveRNPC(playerid, x,y,z, 0.004);
break;
}
}
}
}
}
Jetzt müssen wir nur noch unter OnPlayerStreamOut, wenn gar keine Spieler mehr in der Nähe sind, den Timer stoppen.
public OnPlayerStreamOut(playerid, forplayerid)
{
if(IsPlayerNPC(playerid)==0)
{
if(IsPlayerNPC(forplayerid)==1)
{
SetPVarInt(forplayerid, "SpielerInReichweite", GetPVarInt(forplayerid, "SpielerInReichweite") - 1);
if(GetPVarInt(forplayerid, "SpielerInReichweite") == 0)
{
KillTimer(GetPVarInt(playerid, "zombietimer1ID"));
}
}
}
}
Wie ihr sicherlich gemerkt habt, habe ich anfangs etwas genauer erklärt und später etwas grober. Ich hoffe ihr versteht, dass das Tutorial sonst viel zu lang werden würde. Ich hoffe ihr könnt die späteren Schritte trotzdem gut nachvollziehen.
Solltet ihr Syntaxfehler oder logische Fehler entdecken, bitte melden.
Bisherige Fehler und Lösungen
Problem: Es kommt nur "Incomming Connection" und nichts weiteres
Lösung: In der Server.cfg maxnpc hoch genug stellen.
Problem: BOTS disconnecten direkt nach dem Connect
Lösung: Die BOTS dürfen unter OnPlayerConnect nicht mit SendClientMessage "zugespammt" werden.