Water work and work with grids (still not perfect but i think its the ai code)

This commit is contained in:
KimLS 2018-10-18 20:44:46 -07:00
parent f76fffe622
commit 973abef1b0
6 changed files with 100 additions and 50 deletions

View File

@ -2667,12 +2667,6 @@ void Mob::AddToHateList(Mob* other, uint32 hate /*= 0*/, int32 damage /*= 0*/, b
}
}
}
if (IsNPC() && CastToNPC()->IsUnderwaterOnly() && zone->HasWaterMap()) {
if (!zone->watermap->InLiquid(glm::vec3(other->GetPosition()))) {
return;
}
}
// first add self
// The damage on the hate list is used to award XP to the killer. This check is to prevent Killstealing.

View File

@ -1061,6 +1061,7 @@ public:
void SetCurrentWP(uint16 waypoint) { cur_wp = waypoint; }
virtual FACTION_VALUE GetReverseFactionCon(Mob* iOther) { return FACTION_INDIFFERENT; }
virtual const bool IsUnderwaterOnly() const { return false; }
inline bool IsTrackable() const { return(trackable); }
Timer* GetAIThinkTimer() { return AI_think_timer.get(); }
Timer* GetAIMovementTimer() { return AI_movement_timer.get(); }

View File

@ -1710,7 +1710,7 @@ void NPC::AI_DoMovement() {
SetWaypointPause();
SetAppearance(eaStanding, false);
if (m_CurrentWayPoint.w >= 0.0) {
if (cur_wp_pause > 0 && m_CurrentWayPoint.w >= 0.0) {
RotateTo(m_CurrentWayPoint.w);
}
@ -1756,7 +1756,7 @@ void NPC::AI_DoMovement() {
}
else if (IsGuarding()) {
bool at_gp = IsPositionEqualWithinCertainZ(m_Position, m_GuardPoint, 5.0f);
bool at_gp = IsPositionEqualWithinCertainZ(m_Position, m_GuardPoint, 15.0f);
if (at_gp) {

View File

@ -46,28 +46,29 @@ public:
auto rotate_to_speed = m_rotate_to_mode == MovementRunning ? 50.0 : 16.0; //todo: get this from mob
auto from = FixHeading(m->GetHeading());
auto to = FixHeading(m_rotate_to);
auto diff = to - from;
while (diff < -256.0) {
diff += 512.0;
}
while (diff > 256) {
diff -= 512.0;
}
auto dist = std::abs(diff);
if (!m_started) {
m_started = true;
m->SetMoving(true);
if (rotate_to_speed > 0.0 && rotate_to_speed <= 25.0) { //send basic rotation
if (dist > 15.0f && rotate_to_speed > 0.0 && rotate_to_speed <= 25.0) { //send basic rotation
mgr->SendCommandToClients(m, 0.0, 0.0, 0.0, m_rotate_to_dir * rotate_to_speed, 0, ClientRangeClose);
}
}
auto from = FixHeading(m->GetHeading());
auto to = FixHeading(m_rotate_to);
auto diff = to - from;
while (diff < -256.0) {
diff += 512.0;
}
while (diff > 256) {
diff -= 512.0;
}
auto dist = std::abs(diff);
auto td = rotate_to_speed * 19.0 * frame_time;
if (td >= dist) {
@ -604,51 +605,106 @@ void MobMovementManager::FillCommandStruct(PlayerPositionUpdateServer_Struct *sp
void MobMovementManager::UpdatePath(Mob *who, float x, float y, float z, MobMovementMode mode)
{
//If who is underwater & xyz is underwater & who can see xyz
//Create a route directly from who to xyz
//else
//Create Route
if (zone->HasMap() && zone->HasWaterMap()) {
if (zone->watermap->InLiquid(who->GetPosition()) && zone->watermap->InLiquid(glm::vec3(x, y, z)) && zone->zonemap->CheckLoS(who->GetPosition(), glm::vec3(x, y, z))) {
auto iter = _impl->Entries.find(who);
auto &ent = (*iter);
PushMoveTo(ent.second, x, y, z, mode);
return;
}
}
bool partial = false;
bool stuck = false;
auto route = zone->pathing->FindRoute(glm::vec3(who->GetX(), who->GetY(), who->GetZ()), glm::vec3(x, y, z), partial, stuck);
//if route empty then return
if (route.empty()) {
return;
}
auto &first = route.front();
auto &last = route.back();
//if who is already at the first node, then cull it
if (IsPositionEqualWithinCertainZ(glm::vec3(who->GetX(), who->GetY(), who->GetZ()), first.pos, 5.0f)) {
route.pop_front();
}
if (route.empty()) {
return;
if (zone->HasWaterMap()) {
//If who is underwater & who is not at the first node
//Add node at who
if (!IsPositionEqualWithinCertainZ(glm::vec3(who->GetX(), who->GetY(), who->GetZ()), first.pos, 5.0f)
&& zone->watermap->InLiquid(who->GetPosition()))
{
IPathfinder::IPathNode node(who->GetPosition());
route.push_front(node);
}
//If xyz is underwater & xyz is not at the last node
//Add node at xyz
if (!IsPositionEqualWithinCertainZ(glm::vec3(x, y, z), last.pos, 5.0f)
&& zone->watermap->InLiquid(glm::vec3(x, y, z)))
{
IPathfinder::IPathNode node(glm::vec3(x, y, z));
route.push_back(node);
}
}
//adjust route
AdjustRoute(route, who->GetFlyMode(), who->GetZOffset());
auto iter = _impl->Entries.find(who);
auto &ent = (*iter);
first = route.front();
//If mode = walking then rotateto first node (if possible, live does this)
if (mode == MovementWalking) {
auto h = who->CalculateHeadingToTarget(first.pos.x, first.pos.y);
PushRotateTo(ent.second, who, h, mode);
}
//for each node create a moveto/teleport command
auto eiter = _impl->Entries.find(who);
auto &ent = (*eiter);
auto iter = route.begin();
glm::vec3 previous_pos(who->GetX(), who->GetY(), who->GetZ());
for (auto &node : route) {
if (node.teleport) {
PushTeleportTo(ent.second, node.pos.x, node.pos.y, node.pos.z,
CalculateHeadingAngleBetweenPositions(previous_pos.x, previous_pos.y, node.pos.x, node.pos.y));
bool first_node = true;
//for each node
while (iter != route.end()) {
auto &current_node = (*iter);
iter++;
if (iter == route.end()) {
continue;
}
previous_pos = current_node.pos;
auto &next_node = (*iter);
if (first_node) {
if (mode == MovementWalking) {
auto h = who->CalculateHeadingToTarget(next_node.pos.x, next_node.pos.y);
PushRotateTo(ent.second, who, h, mode);
}
first_node = false;
}
//yet rotate to node + 1
//auto h = CalculateHeadingAngleBetweenPositions(current_node.pos.x, current_node.pos.y, next_node.pos.x, next_node.pos.z);
//PushRotateTo(ent.second, who, h, mode);
//if underwater only mob and node -> node + 1 is moving to land (terminate route, npc will go to the point where it would normally exit the water but no further)
if (who->IsUnderwaterOnly()) {
if (zone->HasWaterMap() && !zone->watermap->InLiquid(next_node.pos)) {
PushStopMoving(ent.second);
return;
}
}
//move to / teleport to node + 1
if (next_node.teleport) {
PushTeleportTo(ent.second, next_node.pos.x, next_node.pos.y, next_node.pos.z,
CalculateHeadingAngleBetweenPositions(current_node.pos.x, current_node.pos.y, next_node.pos.x, next_node.pos.y));
}
else {
PushMoveTo(ent.second, node.pos.x, node.pos.y, node.pos.z, mode);
PushMoveTo(ent.second, next_node.pos.x, next_node.pos.y, next_node.pos.z, mode);
}
previous_pos = node.pos;
}
//if stuck then handle stuck
if (stuck) {
PushTeleportTo(ent.second, x, y, z,
CalculateHeadingAngleBetweenPositions(previous_pos.x, previous_pos.y, x, y));

View File

@ -381,7 +381,7 @@ public:
/* Only allows players that killed corpse to loot */
const bool HasPrivateCorpse() const { return NPCTypedata->private_corpse; }
const bool IsUnderwaterOnly() const { return NPCTypedata->underwater; }
virtual const bool IsUnderwaterOnly() const { return NPCTypedata->underwater; }
const char* GetRawNPCTypeName() const { return NPCTypedata->name; }
void ChangeLastName(const char* in_lastname);

View File

@ -392,7 +392,6 @@ void NPC::SetWaypointPause()
if (cur_wp_pause == 0) {
AI_walking_timer->Start(100);
AI_walking_timer->Trigger();
}
else
{