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.
Codigo:
Al crear la entidad:
Pathfinding
Aca es donde esta el problema ?
O aca esta el problema 2 ?
Think de la entidad:
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.
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 i = 0; i < HHH; ++i) {
ArrayPushCell(hhh, 0);
}
new Array:target = ArrayCreate(3, 1);
ArraySetCell(hhh, HHH_AStar_Target, target);
ArrayPushArray(target, Float:{0.0, 0.0, 0.0});
entity_set_int(ent, EV_INT_iuser2, hhh)
client_print(0, print_chat, "HHH_Create")
}
Código PHP:
AStar_Reset(ent)
{
new Array:hhh = HHH_Get(ent);
new Array:path = ArrayGetCell(hhh, HHH_AStar_Path);
if (path != Invalid_Array) {
ArrayDestroy(path);
}
new astarIdx = ArrayGetCell(hhh, HHH_AStar_Idx);
AStarAbort(astarIdx);
ArraySetCell(hhh, HHH_AStar_Idx, -1);
ArraySetCell(hhh, HHH_AStar_Path, Invalid_Array);
client_print(0, print_chat, "AStar_Reset")
}
Código PHP:
AStar_FindPath(ent)
{
new enemy = entity_get_int(ent, ZOMBIE_TARGET);
static Float:vOrigin[3];
entity_get_vector(ent, EV_VEC_origin, vOrigin)
static Float:vTarget[3];
entity_get_vector(enemy, EV_VEC_origin, vTarget)
new astarIdx = AStarThreaded(vOrigin, vTarget, "AStar_OnPathDone", 30, DONT_IGNORE_MONSTERS, ent, 35, 50);
new Array:hhh = HHH_Get(ent);
ArraySetCell(hhh, HHH_AStar_Idx, astarIdx);
client_print(0, print_chat, "AStar_FindPath")
if (astarIdx != -1) {
g_astarEnt[astarIdx] = ent;
}
}
public AStar_OnPathDone(astarIdx, Array:path, Float:Distance, NodesAdded, NodesValidated, NodesCleared)
{
if (path == Invalid_Array) {
return;
}
new ent = g_astarEnt[astarIdx];
if (!pev_valid(ent)) {
return;
}
new Array:hhh = HHH_Get(ent);
ArraySetCell(hhh, HHH_AStar_Path, path);
client_print(0, print_chat, "AStar_OnPathDone")
}
Aca es donde esta el problema ?
Código PHP:
AStar_ProcessPath(ent, Array:path)
{
new Array:hhh = HHH_Get(ent);
new Float:fArrivalTime = ArrayGetCell(hhh, HHH_AStar_ArrivalTime);
static Float:vOrigin[3];
entity_get_vector(ent, EV_VEC_origin, vOrigin)
static Float:vTarget[3];
new Array:target = ArrayGetCell(hhh, HHH_AStar_Target);
ArrayGetArray(target, 0, vTarget);
if (ArraySize(path) > 0) {
if (get_gametime() >= fArrivalTime) {
static curStep[3];
ArrayGetArray(path, 0, curStep);
ArrayDeleteItem(path, 0);
for (new i = 0; i < 3; ++i) {
vTarget[i] = float(curStep[i]);
}
//if (NPC_IsReachable(ent, vTarget)) {
new Float:fDistance = get_distance_f(vOrigin, vTarget);
ArraySetArray(target, 0, vTarget);
ArraySetCell(hhh, HHH_AStar_ArrivalTime, get_gametime() + (fDistance/240.0));
/*} else {
AStar_Reset(ent);
}*/
}
// NPC_PlayAction(ent, g_actions[Action_Run]);
NPC_MoveToTarget(ent, vTarget, 240.0);
} else {
vOrigin[2] = vTarget[2];
if (get_distance_f(vOrigin, vTarget) <= 64.0 && get_gametime() >= fArrivalTime) {
AStar_Reset(ent);
//NPC_PlayAction(ent, g_actions[Action_Idle]);
}
}
client_print(0, print_chat, "AStar_ProcessPath")
}
stock NPC_MoveToTarget(ent, const Float:vTarget[3], Float:fSpeed)
{
new bool:lockAxis[3] = {true, false, true};
lockAxis[0] = entity_get_int(ent, EV_INT_movetype) != MOVETYPE_FLY;
UTIL_TurnTo(ent, vTarget, lockAxis);
NPC_MoveForward(ent, fSpeed);
}
stock UTIL_TurnTo(ent, const Float:vTarget[3], const bool:lockAxis[3] = {true, false, false})
{
//Get user origin
new Float:vOrigin[3];
entity_get_vector(ent, EV_VEC_origin, vOrigin)
//Get sub vector from origin and target
xs_vec_sub(vTarget, vOrigin, vOrigin);
//Convert direction vector to angle
new Float:vAngles[3];
engfunc(EngFunc_VecToAngles, vOrigin, vAngles);
for (new i = 0; i < 3; ++i) {
if (lockAxis[i]) {
vAngles[i] = 0.0;
}
}
//Apply new angles
entity_set_vector(ent, EV_VEC_angles, vAngles)
entity_set_vector(ent, EV_VEC_v_angle, vAngles)
client_print(0, print_chat, "Angles: %f %f %f", vAngles[0], vAngles[1], vAngles[2])
}
stock NPC_MoveForward(ent, Float:fSpeed)
{
static Float:vDirection[3];
UTIL_GetDirectionVector(ent, vDirection, fSpeed);
static Float:vVelocity[3];
entity_get_vector(ent, EV_VEC_velocity, vVelocity)
vDirection[2] = vVelocity[2];
entity_set_vector(ent, EV_VEC_velocity, vDirection)
client_print(0, print_chat, "vVel: %f %f %f", vVelocity[0], vVelocity[1], vVelocity[2])
client_print(0, print_chat, "vdIR: %f %f %f", vDirection[0], vDirection[1], vDirection[2])
}
stock UTIL_GetDirectionVector(ent, Float:vOut[3], Float:fLength = 1.0)
{
new Float:vAngles[3];
entity_get_vector(ent, EV_VEC_angles, vAngles)
angle_vector(vAngles, ANGLEVECTOR_FORWARD, vOut);
xs_vec_normalize(vOut, vOut);
xs_vec_mul_scalar(vOut, fLength, vOut);
vOut[2] = -vOut[2];
client_print(0, print_chat, "Angles: %f %f %f", vAngles[0], vAngles[1], vAngles[2])
}
O aca esta el problema 2 ?
Think de la entidad:
Código PHP:
public think__Npc(const iEnt) {
if(!is_valid_ent(iEnt)) {
return;
}
if(!entity_get_int(iEnt, ZOMBIE_MAXHEALTH)) {
return;
}
static iVictim;
iVictim = entity_get_int(iEnt, ZOMBIE_TARGET);
if(!iVictim)
{
iVictim = searchHuman(iEnt)
entity_set_float(iEnt, EV_FL_nextthink, get_gametime() + 0.1);
return;
}
static Float:fDistance;
new Float:NpcOrigin[3];
new Float:VictimOrigin[3];
entity_get_vector(iEnt, EV_VEC_origin, NpcOrigin)
entity_get_vector(iVictim, EV_VEC_origin, VictimOrigin)
new Float:fGametime = get_gametime();
new Array:hhh = HHH_Get(iEnt);
new astarIdx = ArrayGetCell(hhh, HHH_AStar_Idx);
new Array:path = ArrayGetCell(hhh, HHH_AStar_Path);
new Float:fNextSearch = ArrayGetCell(hhh, HHH_AStar_NextSearch);
if (astarIdx == -1) {
if (iVictim) {
AStar_FindPath(iEnt);
ArraySetCell(hhh, HHH_AStar_NextSearch, fGametime + 10.0);
}
entity_set_int(iEnt, EV_INT_sequence, 1);
entity_set_float(iEnt, EV_FL_animtime, 2.0);
entity_set_float(iEnt, EV_FL_framerate, 1.0);
entity_set_int(iEnt, EV_INT_gamestate, 1);
} else if (path != Invalid_Array)
{
AStar_ProcessPath(iEnt, path);
}
else
{
if (fGametime > fNextSearch)
{
AStar_Reset(iEnt);
}
entity_set_int(iEnt, EV_INT_sequence, 1);
entity_set_float(iEnt, EV_FL_animtime, 2.0);
entity_set_float(iEnt, EV_FL_framerate, 1.0);
entity_set_int(iEnt, EV_INT_gamestate, 1);
}
if(is_user_alive(iVictim))
{
fDistance = vector_distance(NpcOrigin, VictimOrigin);
if(fDistance <= 64.0)
{
entitySetAim(iEnt, NpcOrigin, VictimOrigin, .iAngleMode=1);
entity_set_int(iEnt, EV_INT_sequence, 76);
entity_set_float(iEnt, EV_FL_animtime, 2.0);
entity_set_float(iEnt, EV_FL_framerate, 2.5);
entity_set_int(iEnt, EV_INT_gamestate, 1);
entity_get_vector(iVictim, EV_VEC_velocity, NpcOrigin);
NpcOrigin[0] = 15.0;
NpcOrigin[1] = 15.0;
entity_set_vector(iVictim, EV_VEC_velocity, NpcOrigin);
// ExecuteHam(Ham_TakeDamage, iVictim, 0, iEnt, random_float(25.0, 45.0), DMG_BULLET);
entity_set_float(iEnt, EV_FL_nextthink, get_gametime() + 0.4);
return;
}
else
{
entity_set_int(iEnt, EV_INT_sequence, 4);
entity_set_float(iEnt, EV_FL_animtime, 2.0);
entity_set_float(iEnt, EV_FL_framerate, 1.0);
entity_set_int(iEnt, EV_INT_gamestate, 1);
entity_set_float(iEnt, EV_FL_nextthink, get_gametime() + 0.1)
return;
}
}
entity_set_float(iEnt, EV_FL_nextthink, get_gametime() + 0.1);
}