void NPC::AssignWaypoints(int32 grid) { if (grid == 0) return; // grid ID 0 not supported if (grid < 0) { // Allow setting negative grid values for pausing pathing this->CastToNPC()->SetGrid(grid); return; } Waypoints.clear(); roamer = false; // Retrieve the wander and pause types for this grid std::string query = StringFormat("SELECT `type`, `type2` FROM `grid` WHERE `id` = %i AND `zoneid` = %i", grid, zone->GetZoneID()); auto results = database.QueryDatabase(query); if (!results.Success()) { return; } if (results.RowCount() == 0) return; auto row = results.begin(); wandertype = atoi(row[0]); pausetype = atoi(row[1]); SetGrid(grid); // Assign grid number // Retrieve all waypoints for this grid query = StringFormat("SELECT `x`,`y`,`z`,`pause`,`heading` " "FROM grid_entries WHERE `gridid` = %i AND `zoneid` = %i " "ORDER BY `number`", grid, zone->GetZoneID()); results = database.QueryDatabase(query); if (!results.Success()) { return; } roamer = true; max_wp = 0; // Initialize it; will increment it for each waypoint successfully added to the list for (auto row = results.begin(); row != results.end(); ++row, ++max_wp) { wplist newwp; newwp.index = max_wp; newwp.x = atof(row[0]); newwp.y = atof(row[1]); newwp.z = atof(row[2]); if(zone->HasMap() && RuleB(Map, FixPathingZWhenLoading) ) { auto positon = glm::vec3(newwp.x,newwp.y,newwp.z); if(!RuleB(Watermap, CheckWaypointsInWaterWhenLoading) || !zone->HasWaterMap() || (zone->HasWaterMap() && !zone->watermap->InWater(positon))) { glm::vec3 dest(newwp.x, newwp.y, newwp.z); float newz = zone->zonemap->FindBestZ(dest, nullptr); if ((newz > -2000) && std::abs(newz - dest.z) < RuleR(Map, FixPathingZMaxDeltaLoading)) newwp.z = newz + 1; } } newwp.pause = atoi(row[3]); newwp.heading = atof(row[4]); Waypoints.push_back(newwp); } UpdateWaypoint(0); SetWaypointPause(); if (wandertype == 1 || wandertype == 2 || wandertype == 5) CalculateNewWaypoint(); if (wandertype == 1 || wandertype == 2 || wandertype == 5) CalculateNewWaypoint(); }
void CAIpyro2::DoBehavior() { m_Attack = 0; if (m_ShockTimer > 0 && m_ShockTimer--) { m_ReactionTime = 1 + frandom()*3; return; } HeadToMovingDirection(); SeekClosestEnemyInSight(); bool Jump = false; bool Shooting = false; // if we see a player if (m_EnemiesInSight > 0) { ReactToPlayer(); if (ShootAtClosestEnemy()) { Shooting = true; } else { if (SeekClosestEnemy()) { m_TargetPos = m_PlayerPos; if (WeaponShootRange() - m_PlayerDistance > 200) SeekRandomWaypoint(); } } } else { //if (Player()->GetCharacter()->PlayerCollision() && frandom()*10 < 3) // Jump = true; ShootAtClosestBuilding(); if (SeekClosestEnemy()) m_TargetPos = m_PlayerPos; else if(SeekRandomEnemy()) { m_TargetPos = m_PlayerPos; if (WeaponShootRange() - m_PlayerDistance > 200) SeekRandomWaypoint(); } } if ((Shooting && Player()->GetCharacter()->IsGrounded()) || (abs(m_Pos.x - m_TargetPos.x) < 40 && abs(m_Pos.y - m_TargetPos.y) < 40)) { // stand still m_Move = 0; m_Jump = 0; m_Hook = 0; } else { if (UpdateWaypoint()) { MoveTowardsWaypoint(); } else { m_WaypointPos = m_TargetPos; MoveTowardsWaypoint(true); } } if (Jump) m_Jump = 1; Player()->GetCharacter()->m_SkipPickups = 999; RandomlyStopShooting(); if (m_ShockTimer > 0 && m_ShockTimer--) { m_Attack = 0; m_Move = 0; m_Hook = 0; m_Jump = 0; } // next reaction in m_ReactionTime = 1 + frandom()*3; }
void NPC::CalculateNewWaypoint() { int old_wp = cur_wp; bool reached_end = false; bool reached_beginning = false; if (cur_wp == max_wp) reached_end = true; if (cur_wp == 0) reached_beginning = true; switch(wandertype) { case 0: //circle { if (reached_end) cur_wp = 0; else cur_wp = cur_wp + 1; break; } case 1: //10 closest { std::list<wplist> closest; GetClosestWaypoint(closest, 10, glm::vec3(GetPosition())); std::list<wplist>::iterator iter = closest.begin(); if(closest.size() != 0) { iter = closest.begin(); std::advance(iter, zone->random.Int(0, closest.size() - 1)); cur_wp = (*iter).index; } break; } case 2: //random { cur_wp = zone->random.Int(0, Waypoints.size() - 1); if(cur_wp == old_wp) { if(cur_wp == (Waypoints.size() - 1)) { if(cur_wp > 0) { cur_wp--; } } else if(cur_wp == 0) { if((Waypoints.size() - 1) > 0) { cur_wp++; } } } break; } case 3: //patrol { if(reached_end) patrol = 1; else if(reached_beginning) patrol = 0; if(patrol == 1) cur_wp = cur_wp - 1; else cur_wp = cur_wp + 1; break; } case 4: //goto the end and depop with spawn timer case 6: //goto the end and depop without spawn timer { cur_wp = cur_wp + 1; break; } case 5: //pick random closest 5 and pick one that's in sight { std::list<wplist> closest; GetClosestWaypoint(closest, 5, glm::vec3(GetPosition())); std::list<wplist>::iterator iter = closest.begin(); while(iter != closest.end()) { if(CheckLosFN((*iter).x, (*iter).y, (*iter).z, GetSize())) { ++iter; } else { iter = closest.erase(iter); } } if(closest.size() != 0) { iter = closest.begin(); std::advance(iter, zone->random.Int(0, closest.size() - 1)); cur_wp = (*iter).index; } break; } } tar_ndx = 52; // Preserve waypoint setting for quest controlled NPCs if (cur_wp < 0) cur_wp = old_wp; // Check to see if we need to update the waypoint. if (cur_wp != old_wp) UpdateWaypoint(cur_wp); }