Allied Modders en español

Versión completa: NPC y Pathfinding API problema
Actualmente estas viendo una versión simplificada de nuestro contenido. Ver la versión completa con el formato correcto.
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);

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' ?
(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;

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]