NPC y Pathfinding API problema
#1
Buenas gente. Les comento, estoy tratando de hacer un NPC con AI .

Lo que quiero hacer, es que seleccione un jugador al azar (que este vivo) y trazar una ruta hacia el jugador (victima) . El problema esta cuando uso la API "Pathfinding" (A* Pathfinding API) para trazar la ruta.

Problema: Llega un momento en que pierde el rastro y se queda completamente quieto, como si dejara de funcionar. O busca mal las rutas. Por ejemplo, subo X rampa y cuando el npc ya esta en la rampa y yo me bajo, ahi se bugea.

[Imagen: Kjwg2qm.jpg]



Codigo:

Código PHP:
enum _:HHH
{
    
HHH_AStar_Idx,
    Array:
HHH_AStar_Path,
    Array:
HHH_AStar_Target,
    
Float:HHH_AStar_ArrivalTime,
    
Float:HHH_AStar_NextSearch
};

new 
g_astarEnt[10]; 

Al crear la entidad:
Código PHP:
public createNpc(const Float:vecOrigin[3]) {
    
// codigo ..
    
HHH_Create(iEnt);
    
AStar_Reset(iEnt);
    
// codigo ..



Pathfinding

Código PHP:
HHH_Create(ent)
{
    new Array:
hhh ArrayCreate(HHH);
    for (new 
0HHH; ++i) {
        
ArrayPushCell(hhh0);
    }
    
    new Array:
target ArrayCreate(31);
    
ArraySetCell(hhhHHH_AStar_Targettarget);
    
ArrayPushArray(targetFloat:{0.00.00.0});
    
    
entity_set_int(entEV_INT_iuser2hhh)
    
client_print(0print_chat"HHH_Create")       


Código PHP:
AStar_Reset(ent)
{
    new Array:
hhh HHH_Get(ent);
    
    new Array:
path ArrayGetCell(hhhHHH_AStar_Path);
    if (
path != Invalid_Array) {
        
ArrayDestroy(path);
    }
    
    new 
astarIdx ArrayGetCell(hhhHHH_AStar_Idx);
    
AStarAbort(astarIdx);
    
    
ArraySetCell(hhhHHH_AStar_Idx, -1);
    
ArraySetCell(hhhHHH_AStar_PathInvalid_Array);

    
client_print(0print_chat"AStar_Reset")


Código PHP:
AStar_FindPath(ent)
{
    new 
enemy entity_get_int(entZOMBIE_TARGET);

    static 
Float:vOrigin[3];
    
entity_get_vector(entEV_VEC_originvOrigin)
    
    static 
Float:vTarget[3];
    
entity_get_vector(enemyEV_VEC_originvTarget)
    
    new 
astarIdx AStarThreaded(vOriginvTarget"AStar_OnPathDone"30DONT_IGNORE_MONSTERSent3550);    
    
    new Array:
hhh HHH_Get(ent);
    
ArraySetCell(hhhHHH_AStar_IdxastarIdx);

    
client_print(0print_chat"AStar_FindPath")  
    
    if (
astarIdx != -1) {
        
g_astarEnt[astarIdx] = ent;
    }
}

public 
AStar_OnPathDone(astarIdx, Array:pathFloat:DistanceNodesAddedNodesValidatedNodesCleared)
{
    if (
path == Invalid_Array) {
        return;
    }
    
    new 
ent g_astarEnt[astarIdx];

    if (!
pev_valid(ent)) {
        return;
    }

    new Array:
hhh HHH_Get(ent);
    
ArraySetCell(hhhHHH_AStar_Pathpath);

    
client_print(0print_chat"AStar_OnPathDone")


Aca es donde esta el problema ? Whatdone

Código PHP:
AStar_ProcessPath(ent, Array:path)
{
    new Array:
hhh HHH_Get(ent);

    new 
Float:fArrivalTime ArrayGetCell(hhhHHH_AStar_ArrivalTime);

    static 
Float:vOrigin[3];
    
entity_get_vector(entEV_VEC_originvOrigin)

    static 
Float:vTarget[3];
    new Array:
target ArrayGetCell(hhhHHH_AStar_Target);
    
ArrayGetArray(target0vTarget);

    if (
ArraySize(path) > 0) {
        if (
get_gametime() >= fArrivalTime) {
            static 
curStep[3];
            
ArrayGetArray(path0curStep);
            
ArrayDeleteItem(path0);
            
            for (new 
03; ++i) {
                
vTarget[i] = float(curStep[i]);
            }
            
            
//if (NPC_IsReachable(ent, vTarget)) {
            
new Float:fDistance get_distance_f(vOriginvTarget);
            
ArraySetArray(target0vTarget);
            
            
ArraySetCell(hhhHHH_AStar_ArrivalTimeget_gametime() + (fDistance/240.0));
            
/*} else {
                AStar_Reset(ent);
            }*/
        
}
        
      
//  NPC_PlayAction(ent, g_actions[Action_Run]);
        
NPC_MoveToTarget(entvTarget240.0);            
    } else {
        
vOrigin[2] = vTarget[2];
        if (
get_distance_f(vOriginvTarget) <= 64.0 && get_gametime() >= fArrivalTime) {
            
AStar_Reset(ent);
            
//NPC_PlayAction(ent, g_actions[Action_Idle]);
        
}
    }

    
client_print(0print_chat"AStar_ProcessPath")
}

stock NPC_MoveToTarget(ent, const Float:vTarget[3], Float:fSpeed)
{
    new 
bool:lockAxis[3] = {truefalsetrue};
    
lockAxis[0] = entity_get_int(entEV_INT_movetype) != MOVETYPE_FLY;

    
UTIL_TurnTo(entvTargetlockAxis);
    
NPC_MoveForward(entfSpeed);
}

stock UTIL_TurnTo(ent, const Float:vTarget[3], const bool:lockAxis[3] = {truefalsefalse}) 
{
    
//Get user origin
    
new Float:vOrigin[3];
    
entity_get_vector(entEV_VEC_originvOrigin)
    
    
//Get sub vector from origin and target
    
xs_vec_sub(vTargetvOriginvOrigin);
    
    
//Convert direction vector to angle
    
new Float:vAngles[3];
    
engfunc(EngFunc_VecToAnglesvOriginvAngles);

    for (new 
03; ++i) {
        if (
lockAxis[i]) {
            
vAngles[i] = 0.0;
        }
    }
    
    
//Apply new angles
    
entity_set_vector(entEV_VEC_anglesvAngles)
    
entity_set_vector(entEV_VEC_v_anglevAngles)

    
client_print(0print_chat"Angles: %f %f %f"vAngles[0], vAngles[1], vAngles[2])
}

stock NPC_MoveForward(entFloat:fSpeed)
{
    static 
Float:vDirection[3];
    
UTIL_GetDirectionVector(entvDirectionfSpeed);
    
    static 
Float:vVelocity[3];
    
entity_get_vector(entEV_VEC_velocityvVelocity)
    
vDirection[2] = vVelocity[2];
    
    
entity_set_vector(entEV_VEC_velocityvDirection)

    
client_print(0print_chat"vVel: %f %f %f"vVelocity[0], vVelocity[1], vVelocity[2])
    
client_print(0print_chat"vdIR: %f %f %f"vDirection[0], vDirection[1], vDirection[2])
}

stock UTIL_GetDirectionVector(entFloat:vOut[3], Float:fLength 1.0)
{
    new 
Float:vAngles[3];
    
entity_get_vector(entEV_VEC_anglesvAngles)
    
angle_vector(vAnglesANGLEVECTOR_FORWARDvOut);
    
xs_vec_normalize(vOutvOut);
    
xs_vec_mul_scalar(vOutfLengthvOut);
    
vOut[2] = -vOut[2];

    
client_print(0print_chat"Angles: %f %f %f"vAngles[0], vAngles[1], vAngles[2])


O aca esta el problema 2 ? pacman Whatdone

Think de la entidad:
Código PHP:
public think__Npc(const iEnt) {
    if(!
is_valid_ent(iEnt)) {
        return;
    }
    
    if(!
entity_get_int(iEntZOMBIE_MAXHEALTH)) {
        return;
    }

    static 
iVictim;
    
iVictim entity_get_int(iEntZOMBIE_TARGET);

    if(!
iVictim)
    {
        
iVictim searchHuman(iEnt)
        
entity_set_float(iEntEV_FL_nextthinkget_gametime() + 0.1);
        return;
    }
    
    static 
Float:fDistance;
    new 
Float:NpcOrigin[3];
    new 
Float:VictimOrigin[3];

    
entity_get_vector(iEntEV_VEC_originNpcOrigin)
    
entity_get_vector(iVictimEV_VEC_originVictimOrigin)


    new 
Float:fGametime get_gametime();    
    
    new Array:
hhh HHH_Get(iEnt);
    new 
astarIdx ArrayGetCell(hhhHHH_AStar_Idx);
    new Array:
path ArrayGetCell(hhhHHH_AStar_Path);
    new 
Float:fNextSearch ArrayGetCell(hhhHHH_AStar_NextSearch);
    
    if (
astarIdx == -1) {
        if (
iVictim) {
            
AStar_FindPath(iEnt);  
            
ArraySetCell(hhhHHH_AStar_NextSearchfGametime 10.0);       
        }

        
entity_set_int(iEntEV_INT_sequence1);
        
entity_set_float(iEntEV_FL_animtime2.0);
        
entity_set_float(iEntEV_FL_framerate1.0);
    
        
entity_set_int(iEntEV_INT_gamestate1);
            
    } else if (
path != Invalid_Array)
    {
        
AStar_ProcessPath(iEntpath);  
    }
    else
    {
        if (
fGametime fNextSearch)
        {
            
AStar_Reset(iEnt);
        }

        
entity_set_int(iEntEV_INT_sequence1);
        
entity_set_float(iEntEV_FL_animtime2.0);
        
entity_set_float(iEntEV_FL_framerate1.0);
    
        
entity_set_int(iEntEV_INT_gamestate1);
        
    }


    if(
is_user_alive(iVictim))
    {
        
fDistance vector_distance(NpcOriginVictimOrigin);
        
        if(
fDistance <= 64.0)
        {
            
entitySetAim(iEntNpcOriginVictimOrigin, .iAngleMode=1);
            
            
entity_set_int(iEntEV_INT_sequence76);
            
entity_set_float(iEntEV_FL_animtime2.0);
            
entity_set_float(iEntEV_FL_framerate2.5);
            
            
entity_set_int(iEntEV_INT_gamestate1);
            
            
entity_get_vector(iVictimEV_VEC_velocityNpcOrigin);
            
            
NpcOrigin[0] = 15.0;
            
NpcOrigin[1] = 15.0;
            
            
entity_set_vector(iVictimEV_VEC_velocityNpcOrigin);
                        
           
// ExecuteHam(Ham_TakeDamage, iVictim, 0, iEnt, random_float(25.0, 45.0), DMG_BULLET);

            
entity_set_float(iEntEV_FL_nextthinkget_gametime() + 0.4);
            
            return;
        }
        else
        {
            
entity_set_int(iEntEV_INT_sequence4);
            
entity_set_float(iEntEV_FL_animtime2.0);
            
entity_set_float(iEntEV_FL_framerate1.0);
            
            
entity_set_int(iEntEV_INT_gamestate1);

            
entity_set_float(iEntEV_FL_nextthinkget_gametime() + 0.1)

            return;
         }
    }

    
    
entity_set_float(iEntEV_FL_nextthinkget_gametime() + 0.1);

Responder
#2
No mire todo el código, solo por arriba, a simple viste se me ocurre que tu método 'searchHuman' no está modificando 'ZOMBIE_TARGET', podrías chequear ?
O mejor dicho, mostrá todos los lugares donde estás asignando 'ZOMBIE_TARGET'.

Además de eso, que EV_INT_* corresponde a tu 'ZOMBIE_TARGET' ?
Responder
#3
(10/06/2018, 11:15 AM)KISKE escribió: No mire todo el código, solo por arriba, a simple viste se me ocurre que tu método 'searchHuman' no está modificando 'ZOMBIE_TARGET', podrías chequear ?
O mejor dicho, mostrá todos los lugares donde estás asignando 'ZOMBIE_TARGET'.

Además de eso, que EV_INT_* corresponde a tu 'ZOMBIE_TARGET' ?

Eso funciona bien porque le puse un print.. igual aca te lo dejo:

Código PHP:
#define ZOMBIE_TARGET                   EV_INT_iuser4 

think:

Código PHP:
public think__Npc(const iEnt) {
    if(!
is_valid_ent(iEnt)) {
        return;
    }
    
    if(!
entity_get_int(iEntZOMBIE_MAXHEALTH)) {
        return;
    }

    static 
iVictim;
    
iVictim entity_get_int(iEntZOMBIE_TARGET);

    if(!
iVictim)
    {
        
iVictim searchHuman(iEnt)
        
entity_set_float(iEntEV_FL_nextthinkget_gametime() + 0.1);
        return;
    }
    
// code code..
 


Código PHP:
AStar_FindPath(ent)
{
    new 
enemy entity_get_int(entZOMBIE_TARGET);

    static 
Float:vOrigin[3];
    
entity_get_vector(entEV_VEC_originvOrigin)
    
    static 
Float:vTarget[3];
    
entity_get_vector(enemyEV_VEC_originvTarget)
    
    new 
astarIdx AStarThreaded(vOriginvTarget"AStar_OnPathDone"30DONT_IGNORE_MONSTERSent3550);    
    
    new Array:
hhh HHH_Get(ent);
    
ArraySetCell(hhhHHH_AStar_IdxastarIdx);

    
client_print(0print_chat"AStar_FindPath")  
    
    if (
astarIdx != -1) {
        
g_astarEnt[astarIdx] = ent;
    }


Al crear la entidad:
Código PHP:
entity_set_int(iEntZOMBIE_TARGET0); 

Código PHP:
public searchHuman(const iEnt) {
    new 
iVictim 0;
    new 
i;
        
    for(
1<= g_maxplayers; ++i)
    {
        if(
is_user_alive(i))
        {
                
iVictim i

                entity_set_int
(iEntZOMBIE_TARGETiVictim);
                
client_print(iprint_chat"Fuiste encontrado por el zombie je")
                break;
        }
    }
    
    return 
iVictim;

Responder
#4
Ya lo pude solucionar con un par de cosillas.

EDIT:

Estoy tratando de hacer que el NPC duckee.

Código PHP:
case ACTIVITY_DUCK:
        {
            
NPC_PlayAction(iEntAI_ACTIONS[5][NPC_SEQUENCE], AI_ACTIONS[5][NPC_ANIMTIME], AI_ACTIONS[5][NPC_FRAMERATE])

            
NPC_MoveToTarget(iEntvecVictimOrigin240.0)

            new 
Float:vecMins[3];
            new 
Float:vecMax[3];
            
//new Float:VecSize[3]
    
            
vecMins Float:{-16.0, -16.0, -18.0};
            
vecMax Float:{16.016.032.0};
            
//VecSize = Float:{32.0, 32.0, 50.0};
    
            //entity_set_size(iEnt, vecMins, vecMax);
    
            
entity_set_vector(iEntEV_VEC_minsvecMins);
            
entity_set_vector(iEntEV_VEC_maxsvecMax);

            
client_print(0print_chat"Duck")

            if(
fDistance <= 64.0)
            {    
                
// Sequence Duck And Attack 

                
entity_set_int(iEntEV_INT_sequence81);
                
entity_set_float(iEntEV_FL_animtimeg_animtime);
                
entity_set_float(iEntEV_FL_framerateg_framerate);

                
entity_set_float(iEntEV_FL_nextthinkget_gametime() + 0.5);
            
                return;    

             }

            
//if( !(pev(iVictim, pev_oldbuttons) & IN_DUCK) )
            //{
                
entity_set_int(iEntZOMBIE_ACTIVITYACTIVITY_STAND)

            
//}

            
entity_set_float(iEntEV_FL_nextthinkget_gametime() + 0.5);
            
            return;

        }
        case 
ACTIVITY_STAND:
        {
            
NPC_PlayAction(iEntAI_ACTIONS[0][NPC_SEQUENCE], AI_ACTIONS[0][NPC_ANIMTIME], AI_ACTIONS[0][NPC_FRAMERATE])

            new 
Float:vecMins[3];
            new 
Float:vecMax[3];
           
// new Float:VecSize[3]
    
            
vecMins Float:{-16.0, -16.0, -36.0};
            
vecMax Float:{16.016.036.0};
            
//VecSize = Float:{32.0, 32.0, 72.0};
    
            //entity_set_size(iEnt, vecMins, vecMax);
    
            
entity_set_vector(iEntEV_VEC_minsvecMins);
            
entity_set_vector(iEntEV_VEC_maxsvecMax);

            
entity_set_int(iEntZOMBIE_ACTIVITYACTIVITY_RUN)

            
client_print(0print_chat"Stand")

            
entity_set_float(iEntEV_FL_nextthinkget_gametime() + 0.5);

            return;
        } 

La parte de duckear funciona bien. El problema viene cuando se ejecutaria la funcion "STAND" (En donde el NPC se para digamos).

Al estar agachado:

[Imagen: jM1R73W.jpg]

Y al pararse pasa esto:

[Imagen: AHAlYtx.jpg]
Responder


Salto de foro:


Usuarios navegando en este tema: 1 invitado(s)