void NPC::TaskBase(void) { if (m_goalWaypointAPI != -1) { if (m_goalWaypointAPI != m_goalWaypoint) { DeleteSearchNodes(); m_goalWaypoint = m_goalWaypointAPI; } } if (DoWaypointNav()) { m_goalWaypoint = -1; if (m_goalWaypointAPI != -1 && m_goalWaypointAPI == m_currentWaypointIndex) m_goalWaypointAPI = -1; } if (!GoalIsValid()) { if (m_goalWaypoint == -1) m_goalWaypoint = RANDOM_LONG(0, g_numWaypoints - 1); FindWaypoint(); DeleteSearchNodes(); FindShortestPath(m_currentWaypointIndex, m_goalWaypoint); } }
void NPC::SetMoveTarget(edict_t *entity) { if (FNullEnt(entity) || !IsAlive(entity)) { m_moveTargetEntity = null; m_task &= ~TASK_MOVETOTARGET; m_enemyUpdateTime = -1.0f; return; } if (!FNullEnt (m_enemy) || m_moveTargetEntity != entity) { LoadEntityWaypointPoint(entity); LoadEntityWaypointPoint(GetEntity(), entity); m_currentWaypointIndex = -1; // Pro P.45 - Move Target improve FindWaypoint(); } SetEnemy(null); m_moveTargetEntity = entity; m_task |= TASK_MOVETOTARGET; m_enemyUpdateTime = gpGlobals->time + 0.3f; }
void NPC::HeadTowardWaypoint(void) { FindWaypoint(); if (m_navNode == null) return; m_jumpAction = false; if (m_navNode->next != null) { for (int j = 0; j < Const_MaxPathIndex; j++) { if (g_waypoint->g_wpConnectionIndex[m_navNode->index][j] != m_navNode->next->index) continue; if (g_waypoint->g_wpConnectionFlags[m_navNode->index][j] & PATHFLAG_JUMP) { m_jumpAction = true; break; } } } m_oldNavIndex = m_navNode->index; m_navNode = m_navNode->next; if (m_navNode != null) m_currentWaypointIndex = m_navNode->index; SetWaypointOrigin(); m_navTime = gpGlobals->time + 5.0f; }
bool NPC::DoWaypointNav (void) { if (m_currentWaypointIndex < 0 || m_currentWaypointIndex >= g_numWaypoints) FindWaypoint(); float waypointDistance = GetDistance(pev->origin, m_waypointOrigin); float desiredDistance = g_waypoint->g_waypointPointRadius[m_currentWaypointIndex]; if (desiredDistance < 16.0f && waypointDistance < 30.0f) { Vector nextFrameOrigin = pev->origin + (pev->velocity * m_frameInterval); if (GetDistance(nextFrameOrigin, m_waypointOrigin) >= waypointDistance) desiredDistance = waypointDistance + 1.0f; } if (waypointDistance < desiredDistance) { if (m_goalWaypoint == m_currentWaypointIndex) return true; else if (m_navNode == null) return false; HeadTowardWaypoint(); return false; } if (GetDistance(m_waypointOrigin, pev->origin) <= 2.0f) HeadTowardWaypoint(); return false; }
static void SetAirfieldDetails(Waypoints &way_points, const TCHAR *name, const tstring &Details, const std::vector<tstring> &files_external, const std::vector<tstring> &files_embed) { auto wp = FindWaypoint(way_points, name); if (wp == nullptr) return; // TODO: eliminate this const_cast hack Waypoint &new_wp = const_cast<Waypoint &>(*wp); new_wp.details = Details.c_str(); new_wp.files_embed.assign(files_embed.begin(), files_embed.end()); #ifdef HAVE_RUN_FILE new_wp.files_external.assign(files_external.begin(), files_external.end()); #endif }
static void SetAirfieldDetails(Waypoints &way_points, const TCHAR *name, const tstring &Details, const std::vector<tstring> &files_external, const std::vector<tstring> &files_embed) { const Waypoint *wp = FindWaypoint(way_points, name); if (wp == NULL) return; Waypoint new_wp(*wp); new_wp.details = Details.c_str(); new_wp.files_embed.assign(files_embed.begin(), files_embed.end()); #ifdef ANDROID new_wp.files_external.assign(files_external.begin(), files_external.end()); #endif way_points.Replace(*wp, new_wp); way_points.Optimise(); }
void NPC::NPCAi(void) { m_frameInterval = gpGlobals->time - m_lastThinkTime; m_lastThinkTime = gpGlobals->time; m_nextThinkTime = gpGlobals->time + 0.1f; g_npcAS = ASC_IDLE; m_moveSpeed = 0.0f; m_destOrigin = nullvec; FindWaypoint(); FindEnemy(); if (m_task & TASK_ENEMY) TaskEnemy(); else if (m_task & TASK_MOVETOTARGET) TaskMoveTarget(); else TaskBase(); if (m_destOrigin == nullvec && m_currentWaypointIndex != -1) { m_destOrigin = m_waypointOrigin; m_lookAt = m_destOrigin; m_moveSpeed = pev->maxspeed; } if (m_iDamage) { m_changeActionTime = -1.0f; g_npcAS |= ASC_DAMAGE; m_iDamage = false; } FacePosition(); MoveAction(); ChangeAnim(); pev->nextthink = m_nextThinkTime; }
bool psPathNetwork::Load(iEngine *engine, iDataConnection *db,psWorld * world) { // First initialize pointers to some importent classes this->engine = engine; this->db = db; this->world = world; Result rs(db->Select("select wp.*,s.name as sector from sc_waypoints wp, sectors s where wp.loc_sector_id = s.id")); if (!rs.IsValid()) { Error2("Could not load waypoints from db: %s",db->GetLastError() ); return false; } for (int i=0; i<(int)rs.Count(); i++) { Waypoint *wp = new Waypoint(); if (wp->Load(rs[i],engine)) { Result rs2(db->Select("select id,alias,rotation_angle from sc_waypoint_aliases where wp_id=%d",wp->GetID())); for (int j=0; j<(int)rs2.Count(); j++) { wp->AddAlias(rs2[j].GetInt(0),rs2[j][1],rs2[j].GetFloat(2)*PI/180.0); } waypoints.Push(wp); // Push in groups if (strcmp(wp->GetGroup(),"")!=0) { AddWaypointToGroup(wp->GetGroup(),wp); } } else { Error2("Could not load waypoint: %s",db->GetLastError() ); delete wp; return false; } } Result rs1(db->Select("select * from sc_waypoint_links")); if (!rs1.IsValid()) { Error2("Could not load waypoint links from db: %s",db->GetLastError() ); return false; } for (int i=0; i<(int)rs1.Count(); i++) { Waypoint * wp1 = FindWaypoint(rs1[i].GetInt("wp1")); Waypoint * wp2 = FindWaypoint(rs1[i].GetInt("wp2")); if(!wp1 || !wp2) { if(!wp1) Error2("Could not find waypoint wp1 link with id %d",rs1[i].GetInt("wp1") ); if(!wp2) Error2("Could not find waypoint wp2 link with id %d",rs1[i].GetInt("wp2") ); return false; } psString flagStr(rs1[i]["flags"]); int pathId = rs1[i].GetInt("id"); csString pathType = rs1[i]["type"]; psPath * path; if (strcasecmp(pathType,"linear") == 0) { path = new psLinearPath(pathId,rs1[i]["name"],flagStr); } else { path = new psLinearPath(pathId,rs1[i]["name"],flagStr); // For now } path->SetStart(wp1); if (!path->Load(db,engine)) { Error1("Failed to load path"); return false; } path->SetEnd(wp2); paths.Push(path); float dist = path->GetLength(world,engine); wp1->AddLink(path,wp2,psPath::FORWARD,dist); if (!path->oneWay) { wp2->AddLink(path,wp1,psPath::REVERSE,dist); // bi-directional link is implied } } return true; }
void NPC::FindEnemy(void) { if (m_findEnemyMode == -1) { SetEnemy(null); SetMoveTarget(null); return; } int team = GetTeam(GetEntity()); if (m_enemyAPI != null && (FNullEnt(m_enemyAPI) || !IsAlive(m_enemyAPI) || GetTeam(m_enemyAPI) == team)) m_enemyAPI = null; if (!FNullEnt(m_enemy)) { if (!IsAlive(m_enemy) || GetTeam(m_enemy) == team) { SetEnemy(null); LoadEntityWaypointPoint(GetEntity()); m_currentWaypointIndex = -1; FindWaypoint(); } } if (!FNullEnt(m_moveTargetEntity)) { if (!IsAlive(m_moveTargetEntity) || GetTeam(m_moveTargetEntity) == team) SetMoveTarget(null); } edict_t *targetEntity = null; float enemy_distance = 9999.9f; if (!FNullEnt(m_enemy)) targetEntity = m_enemy; else if (!FNullEnt(m_moveTargetEntity)) targetEntity = m_moveTargetEntity; if (!FNullEnt(targetEntity)) { if (m_enemyUpdateTime > gpGlobals->time) return; enemy_distance = GetEntityDistance(targetEntity); } int i, allEnemy = 0; edict_t *entity = null; if (FNullEnt(m_enemyAPI)) { for (i = 0; i < checkEnemyNum; i++) { m_allEnemyId[i] = -1; m_allEnemyDistance[i] = 9999.9f; m_enemyEntityId[i] = -1; m_enemyEntityDistance[i] = 9999.9f; } for (i = 0; i < gpGlobals->maxClients; i++) { entity = INDEXENT(i + 1); if (FNullEnt(entity) || !IsAlive(entity) || GetTeam(entity) == team) continue; m_allEnemyId[allEnemy] = i + 1; m_allEnemyDistance[allEnemy] = GetEntityDistance(entity); allEnemy++; } for (i = 0; i < MAX_NPC; i++) { NPC *npc = g_npcManager->IsSwNPCForNum(i); if (npc == null) continue; entity = npc->GetEntity(); if (FNullEnt(entity) || !IsAlive(entity) || GetTeam(entity) == team) continue; if (entity->v.effects & EF_NODRAW || entity->v.takedamage == DAMAGE_NO) continue; m_allEnemyId[allEnemy] = npc->GetIndex(); m_allEnemyDistance[allEnemy] = GetEntityDistance(entity); allEnemy++; } for (i = 0; i < allEnemy; i++) { for (int y = 0; y < checkEnemyNum; y++) { if (m_allEnemyDistance[i] >= m_enemyEntityDistance[y]) continue; for (int z = allEnemy - 1; z >= y; z--) { if (z == allEnemy - 1 || m_enemyEntityId[z] == -1) continue; m_enemyEntityId[z + 1] = m_enemyEntityId[z]; m_enemyEntityDistance[z + 1] = m_enemyEntityDistance[z]; } m_enemyEntityId[y] = m_allEnemyId[i]; m_enemyEntityDistance[y] = m_allEnemyDistance[i]; break; } } for (i = 0; i < checkEnemyNum; i++) { if (m_enemyEntityId[i] == -1) continue; entity = INDEXENT(m_enemyEntityId[i]); if (IsEnemyViewable(entity)) { enemy_distance = m_enemyEntityDistance[i]; targetEntity = entity; break; } } } else { targetEntity = m_enemyAPI; enemy_distance = GetEntityDistance(m_enemyAPI); } if (!FNullEnt(m_moveTargetEntity) && m_moveTargetEntity != targetEntity) { if (m_currentWaypointIndex != g_waypoint->GetEntityWpIndex(targetEntity)) { float distance = GetEntityDistance(m_moveTargetEntity); if (distance <= enemy_distance + 400.0f) { enemy_distance = distance; targetEntity = null; } } } if (!FNullEnt(targetEntity)) { if (!IsEnemyViewable(targetEntity)) { if (targetEntity == m_enemyAPI) { SetMoveTarget(targetEntity); return; } targetEntity = null; } } if (!FNullEnt(m_enemy) && FNullEnt (targetEntity)) { SetMoveTarget(m_enemy); return; } if (!FNullEnt(targetEntity)) { if (m_attackDistance <= 300.0f) { bool moveTarget = true; int srcIndex = g_waypoint->GetEntityWpIndex(GetEntity()); int destIndex = g_waypoint->GetEntityWpIndex(targetEntity); enemy_distance = GetDistance(pev->origin, GetEntityOrigin (targetEntity)); if (srcIndex == destIndex || m_currentWaypointIndex == destIndex) moveTarget = false; else if (enemy_distance <= m_attackDistance) moveTarget = false; else if (m_attackDistance <= 120.0f) { if (targetEntity == m_moveTargetEntity && &m_navNode[0] != null) { if (m_navNode->index == destIndex) moveTarget = false; } else { int movePoint = 0; while (srcIndex != destIndex && movePoint < 99 && srcIndex >= 0 && destIndex >= 0) { srcIndex = *(g_waypoint->m_pathMatrix + (srcIndex * g_numWaypoints) + destIndex); if (srcIndex < 0) continue; movePoint++; } if ((enemy_distance <= 120.0f && movePoint <= 2) || (targetEntity == m_moveTargetEntity && movePoint <= 1)) moveTarget = false; } } if (!moveTarget) { SetEnemy(targetEntity); return; } SetMoveTarget(targetEntity); } else SetEnemy(targetEntity); } }