Changes to various path finding behavior

This commit is contained in:
KimLS 2018-11-09 00:54:51 -08:00
parent fd7b6deafa
commit 8f0051db8d
20 changed files with 157 additions and 165 deletions

View File

@ -126,7 +126,7 @@ void Mob::TemporaryPets(uint16 spell_id, Mob *targ, const char *name_override, u
(npc_dup != nullptr) ? npc_dup : npc_type, //make sure we give the NPC the correct data pointer
0,
GetPosition() + glm::vec4(swarmPetLocations[summon_count], 0.0f, 0.0f),
GravityBehavior::Ground);
GravityBehavior::Water);
if (followme)
swarm_pet_npc->SetFollowID(GetID());
@ -225,7 +225,7 @@ void Mob::TypesTemporaryPets(uint32 typesid, Mob *targ, const char *name_overrid
(npc_dup!=nullptr)?npc_dup:npc_type, //make sure we give the NPC the correct data pointer
0,
GetPosition() + glm::vec4(swarmPetLocations[summon_count], 0.0f, 0.0f),
GravityBehavior::Ground);
GravityBehavior::Water);
if (followme)
swarm_pet_npc->SetFollowID(GetID());
@ -413,7 +413,7 @@ void Mob::WakeTheDead(uint16 spell_id, Mob *target, uint32 duration)
make_npc->d_melee_texture1 = 0;
make_npc->d_melee_texture2 = 0;
auto npca = new NPC(make_npc, 0, GetPosition(), GravityBehavior::Ground);
auto npca = new NPC(make_npc, 0, GetPosition(), GravityBehavior::Water);
if(!npca->GetSwarmInfo()){
auto nSI = new SwarmPet;

View File

@ -954,7 +954,7 @@ bool Mob::CombatRange(Mob* other)
if (_DistNoRoot <= size_mod)
{
//A hack to kill an exploit till we get something better.
if (flymode == GravityBehavior::Ground && _zDist > 500 && !CheckLastLosState()) {
if (flymode != GravityBehavior::Flying && _zDist > 500 && !CheckLastLosState()) {
return false;
}

View File

@ -6281,7 +6281,7 @@ void Client::Doppelganger(uint16 spell_id, Mob *target, const char *name_overrid
(npc_dup!=nullptr)?npc_dup:npc_type, //make sure we give the NPC the correct data pointer
0,
GetPosition() + glm::vec4(swarmPetLocations[summon_count], 0.0f, 0.0f),
GravityBehavior::Ground);
GravityBehavior::Water);
if(!swarm_pet_npc->GetSwarmInfo()){
auto nSI = new SwarmPet;

View File

@ -2611,7 +2611,7 @@ void command_npctypespawn(Client *c, const Seperator *sep)
const NPCType* tmp = 0;
if ((tmp = database.LoadNPCTypesData(atoi(sep->arg[1])))) {
//tmp->fixedZ = 1;
auto npc = new NPC(tmp, 0, c->GetPosition(), GravityBehavior::Ground);
auto npc = new NPC(tmp, 0, c->GetPosition(), GravityBehavior::Water);
if (npc && sep->IsNumber(2))
npc->SetNPCFactionID(atoi(sep->arg[2]));

View File

@ -3438,22 +3438,6 @@ void EntityList::ProcessMove(NPC *n, float x, float y, float z) {
args.push_back(&evt.area_type);
parse->EventNPC(evt.event_id, evt.npc, evt.client, "", 0, &args);
}
if (zone->watermap) {
auto mode = n->GetFlyMode();
if (mode == GravityBehavior::Ground) {
if (zone->watermap->InLiquid(glm::vec3(x, y, z)))
{
n->SetFlyMode(GravityBehavior::Water);
}
}
else if (mode == GravityBehavior::Water) {
if (!zone->watermap->InLiquid(glm::vec3(x, y, z)))
{
n->SetFlyMode(GravityBehavior::Ground);
}
}
}
}
void EntityList::AddArea(int id, int type, float min_x, float max_x, float min_y,

View File

@ -284,7 +284,7 @@ void Client::GoFish()
if (tmp != nullptr) {
auto positionNPC = GetPosition();
positionNPC.x = positionNPC.x + 3;
auto npc = new NPC(tmp, nullptr, positionNPC, GravityBehavior::Ground);
auto npc = new NPC(tmp, nullptr, positionNPC, GravityBehavior::Water);
npc->AddLootTable();
if (npc->DropsGlobalLoot())
npc->CheckGlobalLootTables();

View File

@ -335,15 +335,6 @@ Mob *HateList::GetEntWithMostHateOnList(Mob *center, Mob *skip)
continue;
}
auto hateEntryPosition = glm::vec3(cur->entity_on_hatelist->GetX(), cur->entity_on_hatelist->GetY(), cur->entity_on_hatelist->GetZ());
if (center->IsNPC() && center->CastToNPC()->IsUnderwaterOnly() && zone->HasWaterMap()) {
if (!zone->watermap->InLiquid(hateEntryPosition)) {
skipped_count++;
++iterator;
continue;
}
}
if (cur->entity_on_hatelist->Sanctuary()) {
if (hate == -1)
{
@ -474,14 +465,6 @@ Mob *HateList::GetEntWithMostHateOnList(Mob *center, Mob *skip)
continue;
}
if (center->IsNPC() && center->CastToNPC()->IsUnderwaterOnly() && zone->HasWaterMap()) {
if(!zone->watermap->InLiquid(glm::vec3(cur->entity_on_hatelist->GetPosition()))) {
skipped_count++;
++iterator;
continue;
}
}
if (cur->entity_on_hatelist != nullptr && ((cur->stored_hate_amount > hate) || cur->is_entity_frenzy))
{
top_hate = cur->entity_on_hatelist;

View File

@ -30,7 +30,7 @@ std::map<uint16, const NPCType *> Horse::horse_types;
LinkedList<NPCType *> horses_auto_delete;
Horse::Horse(Client *_owner, uint16 spell_id, const glm::vec4& position)
: NPC(GetHorseType(spell_id), nullptr, position, GravityBehavior::Ground)
: NPC(GetHorseType(spell_id), nullptr, position, GravityBehavior::Water)
{
//give the horse its proper name.
strn0cpy(name, _owner->GetCleanName(), 55);

View File

@ -1499,7 +1499,7 @@ void lua_create_npc(luabind::adl::object table, float x, float y, float z, float
LuaCreateNPCParse(no_target_hotkey, bool, false);
LuaCreateNPCParse(raid_target, bool, false);
NPC* npc = new NPC(npc_type, nullptr, glm::vec4(x, y, z, heading), GravityBehavior::Ground);
NPC* npc = new NPC(npc_type, nullptr, glm::vec4(x, y, z, heading), GravityBehavior::Water);
npc->GiveNPCTypeData(npc_type);
entity_list.AddNPC(npc);
}

View File

@ -29,7 +29,7 @@ extern volatile bool is_zone_loaded;
#endif
Merc::Merc(const NPCType* d, float x, float y, float z, float heading)
: NPC(d, nullptr, glm::vec4(x, y, z, heading), GravityBehavior::Ground, false), endupkeep_timer(1000), rest_timer(1), confidence_timer(6000), check_target_timer(2000)
: NPC(d, nullptr, glm::vec4(x, y, z, heading), GravityBehavior::Water, false), endupkeep_timer(1000), rest_timer(1), confidence_timer(6000), check_target_timer(2000)
{
base_hp = d->max_hp;
base_mana = d->Mana;

View File

@ -24,6 +24,7 @@
#include "string_ids.h"
#include "worldserver.h"
#include "mob_movement_manager.h"
#include "water_map.h"
#include <limits.h>
#include <math.h>
@ -427,7 +428,7 @@ Mob::Mob(const char* in_name,
m_TargetRing = glm::vec3();
flymode = GravityBehavior::Ground;
flymode = GravityBehavior::Water;
DistractedFromGrid = false;
hate_list.SetHateOwner(this);
@ -5995,8 +5996,16 @@ float Mob::GetDefaultRaceSize() const {
void Mob::TryFixZ(int32 z_find_offset, bool fix_client_z)
{
if (fix_z_timer.Check() && flymode == GravityBehavior::Ground) {
FixZ();
if (fix_z_timer.Check() && flymode != GravityBehavior::Flying) {
auto watermap = zone->watermap;
if (watermap) {
if (!watermap->InLiquid(m_Position)) {
FixZ();
}
}
else {
FixZ();
}
}
}

View File

@ -1363,16 +1363,20 @@ void Mob::AI_Process() {
else {
//we cannot reach our target...
//underwater stuff only works with water maps in the zone!
if (IsNPC() && CastToNPC()->IsUnderwaterOnly() && zone->HasWaterMap()) {
auto targetPosition = glm::vec3(target->GetX(), target->GetY(), target->GetZ());
if (!zone->watermap->InLiquid(targetPosition)) {
Mob *tar = hate_list.GetEntWithMostHateOnList(this);
if (tar != nullptr && tar != target) {
SetTarget(tar);
return;
}
}
}
//if (IsNPC() && CastToNPC()->IsUnderwaterOnly() && zone->HasWaterMap()) {
// auto targetPosition = glm::vec3(target->GetX(), target->GetY(), target->GetZ());
// if (!zone->watermap->InLiquid(targetPosition)) {
// Mob *tar = hate_list.GetEntWithMostHateOnList(this);
// if (tar != nullptr && tar != target) {
// SetTarget(tar);
// RunTo(tar->GetX(), tar->GetY(), tar->GetZ());
// return;
// }
// else {
// RunTo(target->GetX(), target->GetY(), target->GetZ());
// }
// }
//}
// See if we can summon the mob to us
if (!HateSummon()) {

View File

@ -428,18 +428,20 @@ struct MobMovementEntry
NavigateTo NavTo;
};
void AdjustRoute(std::list<IPathfinder::IPathNode> &nodes, int flymode, float offset) {
void AdjustRoute(std::list<IPathfinder::IPathNode> &nodes, Mob *who) {
if (!zone->HasMap() || !zone->HasWaterMap()) {
return;
}
auto offset = who->GetZOffset();
for (auto &node : nodes) {
if (flymode == GravityBehavior::Ground || !zone->watermap->InLiquid(node.pos)) {
if(!zone->watermap->InLiquid(node.pos)) {
auto best_z = zone->zonemap->FindBestZ(node.pos, nullptr);
if (best_z != BEST_Z_INVALID) {
node.pos.z = best_z + offset;
}
}
} // todo: floating logic?
}
}
@ -701,99 +703,48 @@ void MobMovementManager::UpdatePath(Mob *who, float x, float y, float z, MobMove
if (!zone->HasMap() || !zone->HasWaterMap()) {
auto iter = _impl->Entries.find(who);
auto &ent = (*iter);
PushMoveTo(ent.second, x, y, z, mode);
PushStopMoving(ent.second);
}
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);
PushSwimTo(ent.second, x, y, z, mode);
PushStopMoving(ent.second);
return;
}
bool partial = false;
bool stuck = false;
IPathfinder::IPath route;
if (who->IsUnderwaterOnly()) {
route = zone->pathing->FindRoute(glm::vec3(who->GetX(), who->GetY(), who->GetZ()), glm::vec3(x, y, z), partial, stuck, PathingWater | PathingLava | PathingVWater | PathingPortal | PathingPrefer);
if (who->IsBoat()) {
UpdatePathBoat(who, x, y, z, mode);
} else if (who->IsUnderwaterOnly()) {
UpdatePathUnderwater(who, x, y, z, mode);
}
else {
route = zone->pathing->FindRoute(glm::vec3(who->GetX(), who->GetY(), who->GetZ()), glm::vec3(x, y, z), partial, stuck, PathingNotDisabled ^ PathingZoneLine);
UpdatePathGround(who, x, y, z, mode);
}
}
//if route empty or only has two points, and we have los, then just force npc to move to location
if (route.size() < 3) {
auto iter = _impl->Entries.find(who);
auto &ent = (*iter);
if (zone->zonemap->CheckLoS(who->GetPosition(), glm::vec3(x, y, z)) && route.size() > 0)
{
auto &first = route.front();
auto &last = route.back();
if (zone->watermap->InLiquid(who->GetPosition())) {
PushSwimTo(ent.second, x, y, z, mode);
}
else {
PushMoveTo(ent.second, x, y, z, mode);
}
PushStopMoving(ent.second);
return;
}
else if(route.size() < 2)
{
if (zone->watermap->InLiquid(who->GetPosition())) {
PushSwimTo(ent.second, x, y, z, mode);
}
else {
PushMoveTo(ent.second, x, y, z, mode);
}
void MobMovementManager::UpdatePathGround(Mob * who, float x, float y, float z, MobMovementMode mode)
{
//This is probably pointless since the nav mesh tool currently sets zonelines to disabled anyway
auto partial = false;
auto stuck = false;
auto route = zone->pathing->FindRoute(
glm::vec3(who->GetX(), who->GetY(), who->GetZ()),
glm::vec3(x, y, z),
partial,
stuck,
PathingNotDisabled ^ PathingZoneLine);
PushMoveTo(ent.second, x, y, z, mode);
PushStopMoving(ent.second);
return;
}
}
auto &first = route.front();
auto &last = route.back();
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 eiter = _impl->Entries.find(who);
auto &ent = (*eiter);
if (route.size() == 0) {
//handle stuck behavior
return;
}
AdjustRoute(route, who);
auto iter = route.begin();
glm::vec3 previous_pos(who->GetX(), who->GetY(), who->GetZ());
bool first_node = true;
//for each node
while (iter != route.end()) {
auto &current_node = (*iter);
@ -830,14 +781,86 @@ void MobMovementManager::UpdatePath(Mob *who, float x, float y, float z, MobMove
}
}
}
//if stuck then handle stuck
if (stuck) {
PushMoveTo(ent.second, x, y, z, mode);
//handle stuck
}
else {
PushStopMoving(ent.second);
}
void MobMovementManager::UpdatePathUnderwater(Mob * who, float x, float y, float z, MobMovementMode mode)
{
auto partial = false;
auto stuck = false;
auto route = zone->pathing->FindRoute(
glm::vec3(who->GetX(), who->GetY(), who->GetZ()),
glm::vec3(x, y, z),
partial,
stuck,
PathingWater | PathingLava | PathingVWater | PathingPortal | PathingPrefer);
auto eiter = _impl->Entries.find(who);
auto &ent = (*eiter);
if (route.size() == 0) {
//handle stuck behavior
return;
}
AdjustRoute(route, who);
auto iter = route.begin();
glm::vec3 previous_pos(who->GetX(), who->GetY(), who->GetZ());
bool first_node = true;
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;
}
//move to / teleport to node + 1
if (next_node.teleport && next_node.pos.x != 0.0f && next_node.pos.y != 0.0f) {
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 {
if (zone->watermap->InLiquid(previous_pos)) {
PushSwimTo(ent.second, next_node.pos.x, next_node.pos.y, next_node.pos.z, mode);
}
else {
PushMoveTo(ent.second, next_node.pos.x, next_node.pos.y, next_node.pos.z, mode);
}
}
}
if (stuck) {
//handle stuck
}
}
void MobMovementManager::UpdatePathBoat(Mob *who, float x, float y, float z, MobMovementMode mode)
{
auto eiter = _impl->Entries.find(who);
auto &ent = (*eiter);
PushSwimTo(ent.second, x, y, z, mode);
PushStopMoving(ent.second);
}
void MobMovementManager::PushTeleportTo(MobMovementEntry &ent, float x, float y, float z, float heading)

View File

@ -58,6 +58,9 @@ private:
void FillCommandStruct(PlayerPositionUpdateServer_Struct *spu, Mob *m, float dx, float dy, float dz, float dh, int anim);
void UpdatePath(Mob *who, float x, float y, float z, MobMovementMode mode);
void UpdatePathGround(Mob *who, float x, float y, float z, MobMovementMode mode);
void UpdatePathUnderwater(Mob *who, float x, float y, float z, MobMovementMode mode);
void UpdatePathBoat(Mob *who, float x, float y, float z, MobMovementMode mode);
void PushTeleportTo(MobMovementEntry &ent, float x, float y, float z, float heading);
void PushMoveTo(MobMovementEntry &ent, float x, float y, float z, MobMovementMode mode);
void PushSwimTo(MobMovementEntry &ent, float x, float y, float z, MobMovementMode mode);

View File

@ -413,20 +413,6 @@ NPC::NPC(const NPCType* d, Spawn2* in_respawn, const glm::vec4& position, Gravit
AISpellVar.idle_no_sp_recast_min = RuleI(Spells, AI_IdleNoSpellMinRecast);
AISpellVar.idle_no_sp_recast_max = RuleI(Spells, AI_IdleNoSpellMaxRecast);
AISpellVar.idle_beneficial_chance = RuleI(Spells, AI_IdleBeneficialChance);
if (zone->watermap) {
auto mode = GetFlyMode();
if (mode == GravityBehavior::Ground) {
if (zone->watermap->InLiquid(m_Position)) {
SetFlyMode(GravityBehavior::Water);
}
}
else if (mode == GravityBehavior::Water) {
if (!zone->watermap->InLiquid(m_Position)) {
SetFlyMode(GravityBehavior::Ground);
}
}
}
}
NPC::~NPC()
@ -1202,7 +1188,7 @@ NPC* NPC::SpawnNPC(const char* spawncommand, const glm::vec4& position, Client*
npc_type->prim_melee_type = 28;
npc_type->sec_melee_type = 28;
auto npc = new NPC(npc_type, nullptr, position, GravityBehavior::Ground);
auto npc = new NPC(npc_type, nullptr, position, GravityBehavior::Water);
npc->GiveNPCTypeData(npc_type);
entity_list.AddNPC(npc);

View File

@ -425,7 +425,7 @@ void Mob::MakePoweredPet(uint16 spell_id, const char* pettype, int16 petpower,
into walls or objects (+10), this sometimes creates the "ghost" effect. I changed to +2 (as close as I
could get while it still looked good). I also noticed this can happen if an NPC is spawned on the same spot of another or in a related bad spot.*/
Pet::Pet(NPCType *type_data, Mob *owner, PetType type, uint16 spell_id, int16 power)
: NPC(type_data, 0, owner->GetPosition() + glm::vec4(2.0f, 2.0f, 0.0f, 0.0f), GravityBehavior::Ground)
: NPC(type_data, 0, owner->GetPosition() + glm::vec4(2.0f, 2.0f, 0.0f, 0.0f), GravityBehavior::Water)
{
GiveNPCTypeData(type_data);
typeofpet = type;

View File

@ -208,7 +208,7 @@ Mob* QuestManager::spawn2(int npc_type, int grid, int unused, const glm::vec4& p
const NPCType* tmp = 0;
if (tmp = database.LoadNPCTypesData(npc_type))
{
auto npc = new NPC(tmp, nullptr, position, GravityBehavior::Ground);
auto npc = new NPC(tmp, nullptr, position, GravityBehavior::Water);
npc->AddLootTable();
if (npc->DropsGlobalLoot())
npc->CheckGlobalLootTables();
@ -232,7 +232,7 @@ Mob* QuestManager::unique_spawn(int npc_type, int grid, int unused, const glm::v
const NPCType* tmp = 0;
if (tmp = database.LoadNPCTypesData(npc_type))
{
auto npc = new NPC(tmp, nullptr, position, GravityBehavior::Ground);
auto npc = new NPC(tmp, nullptr, position, GravityBehavior::Water);
npc->AddLootTable();
if (npc->DropsGlobalLoot())
npc->CheckGlobalLootTables();
@ -308,7 +308,7 @@ Mob* QuestManager::spawn_from_spawn2(uint32 spawn2_id)
found_spawn->SetCurrentNPCID(npcid);
auto position = glm::vec4(found_spawn->GetX(), found_spawn->GetY(), found_spawn->GetZ(), found_spawn->GetHeading());
auto npc = new NPC(tmp, found_spawn, position, GravityBehavior::Ground);
auto npc = new NPC(tmp, found_spawn, position, GravityBehavior::Water);
found_spawn->SetNPCPointer(npc);
npc->AddLootTable();
@ -1686,7 +1686,7 @@ void QuestManager::respawn(int npcTypeID, int grid) {
const NPCType* npcType = nullptr;
if ((npcType = database.LoadNPCTypesData(npcTypeID)))
{
owner = new NPC(npcType, nullptr, owner->GetPosition(), GravityBehavior::Ground);
owner = new NPC(npcType, nullptr, owner->GetPosition(), GravityBehavior::Water);
owner->CastToNPC()->AddLootTable();
if (owner->CastToNPC()->DropsGlobalLoot())
owner->CastToNPC()->CheckGlobalLootTables();

View File

@ -255,7 +255,7 @@ bool Spawn2::Process() {
}
currentnpcid = npcid;
NPC *npc = new NPC(tmp, this, glm::vec4(x, y, z, heading), GravityBehavior::Ground);
NPC *npc = new NPC(tmp, this, glm::vec4(x, y, z, heading), GravityBehavior::Water);
npc->mod_prespawn(this);

View File

@ -610,7 +610,7 @@ float Mob::GetFixedZ(const glm::vec3 &destination, int32 z_find_offset) {
if (zone->HasMap() && RuleB(Map, FixZWhenMoving)) {
if (flymode != GravityBehavior::Ground)
if (flymode == GravityBehavior::Flying)
return new_z;
if (zone->HasWaterMap() && zone->watermap->InLiquid(glm::vec3(m_Position)))

View File

@ -2257,7 +2257,7 @@ void Zone::DoAdventureActions()
const NPCType* tmp = database.LoadNPCTypesData(ds->data_id);
if(tmp)
{
NPC* npc = new NPC(tmp, nullptr, glm::vec4(ds->assa_x, ds->assa_y, ds->assa_z, ds->assa_h), GravityBehavior::Ground);
NPC* npc = new NPC(tmp, nullptr, glm::vec4(ds->assa_x, ds->assa_y, ds->assa_z, ds->assa_h), GravityBehavior::Water);
npc->AddLootTable();
if (npc->DropsGlobalLoot())
npc->CheckGlobalLootTables();