NPC/Bots implementation in VCMP 0.4 Servers

Started by habi, Apr 01, 2022, 05:37 PM

Previous topic - Next topic

habi

#60
NPCClient v1.7 Beta 2 Released

We're excited to announce the release of NPCClient v1.7 Beta 2! This new version comes with various improvements and enhancements to make your experience even better.

You can check out the detailed release notes on the V1.7 Beta 2 Release Notes page for more information about the changes and new features.
Quote
  • New field I_ACTION added for GetLocalValue and SetLocalValue for getting/setting action of npc.
  • Fixed serious bug in RECORDING PLAYER ACTION i.e. in StartRecordingPlayerData, which showed error when playing .rec files (message version different). Now VERSION of .rec files is 4. Use recupdate to convert old playback recordings.
  • npc's can now exit vehicle properly (ExitVehicle, ExitVehicleEx).
  • In windows builds, pressing Ctrl+C will effect /q to server and npcclient client disconnect properly.
  • Changed KEY_ONFOOT_JUMP to 2048 from 2176, because of the latter not causing npc to jump.
  • The playback recordings (onfoot) now records player Action and will reproduce on playback with an npc.


Please give it a try and let us know your feedback. Your input is invaluable in making NPCClient even better. Thank you for your continued support!

The NPCClient Team

PSL

I tried to delete the shot timer, after deleting it, the npc kept shooting but wouldn't aim at me, how do I get him to cancel the shot?

PSL

This is my script code,It did remove the timer after 90 meters from the NPC, but it was still firing。
function OnNPCScriptLoad(params)
{
    shootwaittimer=SetTimer("ShootTimer",2000,1);
}
function ShootTimer()
{
    local x=0;
    while(x!=MAX_PLAYERS)
    {
        if(IsPlayerConnected(x))
        {
            if(IsPlayerStreamedIn(x))
            {
                local pos=GetPlayerPos(x);
                if(GetDistanceFromMeToPoint(pos)<=90.0)
                {
                    KillTimer(shootwaittimer);
                    shootwaittimer=null;

                    StartShoot(x);
                    break;
                }
            }
        }
        x+=1;
    }
}

function ShootPlayer(pid)
{
    if(IsPlayerStreamedIn(pid)&&GetPlayerState(pid)!=PLAYER_STATE_WASTED)
    {
        local pos=GetPlayerPos(pid),weapon=GetPlayerArmedWeapon(npcid);
        if(GetDistanceFromMeToPoint(pos)<90.0)
        {
            local now=GetTickCount();
            if(!isReloading||now-last_fired>=1000)
            {
                isReloading=false; //Checking interval between 2 bullets. In milliseconds.
                if(now-last_fired>=150) // 150ms is firing rate of rifle ruger
                {
                    //Decrease Ammo by One.
                    local NewAmmo=GetLocalValue(I_CURWEP_AMMO)-1;
                    if(NewAmmo<=0) NewAmmo=1; //fool the server
                       
                    SetLocalValue(I_CURWEP_AMMO,NewAmmo);
                    ShootAt(pos);
                    bullets_fired++;
                    if(bullets_fired%30==0) isReloading=true; //rifle has 30 bullets in one catridge
                    last_fired=now;    //Store tick
                }
                else SendOnFootSyncDataLV(); //Send a packet,same as last one. (for Sync Issues)
            }
            else ShootAt(pos,true); //still reloading... Call function 'ShootAt' with 'isReloading' as 'true'
        }
        else StopShoot();
    }
    else StopShoot();
}
function StartShoot(shootid)
{
    shottimer=SetTimerEx("ShootPlayer",60,0,shootid);
}
function StopShoot()
{
    KillTimer(shottimer);
    shottimer=null;
    shootwaittimer=SetTimer("ShootTimer",2000,1);
}

habi


habi

Your code is working when i tested. When i am inside 90 meters, it shoots me. When i am outside 90 meters, it stops.
See when i moved away 90 meters, it stopped shooting.

npcscripts/attack_psl.nut
local shootwaittimer;
local npcid;
local isReloading=false;
local last_fired=0;
local shottimer;
local bullets_fired=0;
//Shoot at a point. Most important function
function ShootAt(tPos, isReloading = false, isHeadShot=false)
{
if(isHeadShot)tPos.z+=0.627299;
local Pos= GetMyPos();
local angle= atan2(-(tPos.x-Pos.x), tPos.y-Pos.y);
local aimPos= Vector(tPos.x,tPos.y,tPos.z);
local aimDir = Vector( PI, PI, -angle );
local keys= KEY_ONFOOT_FIRE ;
SetLocalValue(I_KEYS, keys );
local ammo = GetLocalValue(I_CURWEP_AMMO );
SendOnFootSyncData( keys, Pos.x,Pos.y, Pos.z, angle, GetPlayerHealth( npcid ), GetPlayerArmour( npcid ), GetPlayerArmedWeapon( npcid ),ammo, 0.0, 0.0, 0.0, aimPos.x, aimPos.y, aimPos.z, PI, PI, -angle, false, isReloading );
}
function OnNPCConnect(myplayerid)
{
    npcid=myplayerid;
}
function OnNPCScriptLoad(params)
{
    shootwaittimer=SetTimer("ShootTimer",2000,1);
}
function ShootTimer()
{
    local x=0;
    while(x!=MAX_PLAYERS)
    {
        if(IsPlayerConnected(x))
        {
            if(IsPlayerStreamedIn(x))
            {
                local pos=GetPlayerPos(x);
                if(GetDistanceFromMeToPoint(pos)<=90.0)
                {
                    KillTimer(shootwaittimer);
                    shootwaittimer=null;

                    StartShoot(x);
                    break;
                }
            }
        }
        x+=1;
    }
}

function ShootPlayer(pid)
{
    if(IsPlayerStreamedIn(pid)&&GetPlayerState(pid)!=PLAYER_STATE_WASTED)
    {
        local pos=GetPlayerPos(pid),weapon=GetPlayerArmedWeapon(npcid);
        if(GetDistanceFromMeToPoint(pos)<90.0)
        {
            local now=GetTickCount();
            if(!isReloading||now-last_fired>=1000)
            {
                isReloading=false; //Checking interval between 2 bullets. In milliseconds.
                if(now-last_fired>=150) // 150ms is firing rate of rifle ruger
                {
                    //Decrease Ammo by One.
                    local NewAmmo=GetLocalValue(I_CURWEP_AMMO)-1;
                    if(NewAmmo<=0) NewAmmo=1; //fool the server
                       
                    SetLocalValue(I_CURWEP_AMMO,NewAmmo);
                    ShootAt(pos);
                    bullets_fired++;
                    if(bullets_fired%30==0) isReloading=true; //rifle has 30 bullets in one catridge
                    last_fired=now;    //Store tick
                }
                else SendOnFootSyncDataLV(); //Send a packet,same as last one. (for Sync Issues)
            }
            else ShootAt(pos,true); //still reloading... Call function 'ShootAt' with 'isReloading' as 'true'
        }
        else StopShoot();
    }
    else StopShoot();
}
function StartShoot(shootid)
{
    shottimer=SetTimerEx("ShootPlayer",60,0,shootid);
}
function StopShoot()
{
    KillTimer(shottimer);
    shottimer=null;
    shootwaittimer=SetTimer("ShootTimer",2000,1);
}
scripts/main.nut
ConnectNPC("habi","attack_psl.nut",true)
How i measured 90 meter distance:
npcconsole:

When npcid is 0 and my id is 1

PSL

#65
I used the above script, but as before, when I left the range, it always shot at the last point, when I entered the range, it still aimed at me normally, I tried to send a command to clear the weapon when I turned off the timer, but it still didn't work, I was using version 1.7, or maybe there was a problem with the system。

pic: https://img1.imgtp.com/2023/09/27/tjpLHgP4.png

habi

I think this will solve the problem:
local KEY_NONE=0;
function StopShoot()
{
    ...
    shootwaittimer=
    ...
    SetLocalValue(I_KEYS, KEY_NONE); //Set NPC to non-shooting mode
    SendOnFootSyncDataLV();
}

PSL

Oh my God, this problem is solved, thank you so much, now npc can stop shooting normally, your plugin is great.

habi


PSL

#69
Hi Habi. After I added armor to the NPC after respawn, the NPC got kicked. The probability of this phenomenon is relatively high.
Console display:
Kicking player 'NPC_pq' (0), armour increased from 0 to 50.
Player 'NPC_pq' ID 0 disconnected (kicked).

habi

Hi PSL, could you provide more info?
I tried four times killing npc by player.Health=0 then respawned by RequestSpawn() as well as player.Spawn(). Then i set player.Armour=50 and nothing happened except it got half  armour.

Are you using latest version v1.7 beta 2 ?

Was it after playback recording using .rec files ?

Thank you

PSL

Hi Habi, This is the relevant code, in the main script. If you need any more information, please let me know.
When I opened the server, the npc joined, and the npc resurrected and got kicked for adding armor. NPC are kicked when they first enter the server and add armor after they spawn.
I'm sure I'm using v1.7 beta 2, I didn't add a recording to the npc.
Screenshot of console when error occurs:https://img1.imgtp.com/2023/10/01/r7y4Xra2.png
The npc's console sent a message that it had been resurrected before it was shut down.
function onScriptLoad()
{
     ConnectNPC("NPC_pq","npctest.nut",true,"127.0.0.1","rpclib z-finder");
}
function onPlayerJoin(player)
{
    if(IsPlayerNPC(player.ID)==true)  onNPCJoin(player.ID);
}

function onNPCJoin(i)
{
    local plr=FindPlayer(i);
    if(plr)
    {
        plr.IsAdmin=true;
        state[plr.ID].isnpc=true;
    }
}

function onPlayerRequestClass(player,classID,team,skin)
{
     if(state[player.ID].isnpc==true) player.Spawn();
}
function onPlayerSpawn(player)
{
    if(state[player.ID].isnpc==true) onNPCSpawn(player.ID);
}

function onNPCSpawn(i)
{
    local plr=FindPlayer(i);
    if(plr)
    {
        plr.Pos=NPCPos[plr.ID];
        plr.Skin=1;
        plr.Armour=50; //kick in here
        plr.Colour=RGB(255,255,0);
        plr.GiveWeapon(22,9999);
        NewTimer("update",500,1,plr.ID);
    }
}

function update(id)
{
    local p=FindPlayer(id);
    if(p)
    {
        if(p.IsSpawned==true)
        {
            p.Pos=p.Pos;
        }
    }
}

PSL

I then found something useful, this is my cfg file, I have seen before in other server scripts to add the code anticheat 0, I also tried to add this code, I found that I started nearly 10 times without the NPC being kicked, and I deleted this line rule, Two out of five booting sessions an NPC gets kicked.
plugins announce04rel64 mmdb04rel64 httprequest04rel64 mysql04rel64 npc04rel64 logfile64 remexec04rel64 cmdinputrel64 miamiscale04rel64 squirrel04rel64
sqgamemode scripts/主脚本.nut
port 8192

habi

#73
Hi, thank you for providing me the code.

I tried several times. But npc was not kicked each time. Same script except i created stats array with isnpc field and vector NPCPos.

Is it possible to take a screenshot of npcconsole when it gets kicked?

I will investigate the issue deeply tomorrow.

About anticheat, i did not add line in server. cfg

If armour is the problem the  you can put it in a timer
function onNPCSpawn(i)
{
..
NewTimer("shield", 500, 1, plr.ID, 50);
plr.Colour= .
..
}
function shield(id, amount)
{
local plr=FindPlayer(id);
if(plr && plr.IsNPC)plr.Armour=amount;
}

PSL

Hi Habi, The npc console was shut down in less than 0.5 seconds, I have a screenshot of it before the shutdown, as well as some screenshots of the script。 https://postimg.cc/gallery/ygmpBbF
I didn't add armor before because the NPC had m4, now I added armor because the NPC had TEC-9, and then there was this problem, thanks for the idea, the timer is a good way to do it。
There is a NPCtimerEX timer in the NPC script, which controls the NPC's shooting and running, but it will not be executed without the player, I think there is no scripting error in this part of the script.