MoveTo while saving guard position no longer hops.

This commit is contained in:
Paul Coene 2017-11-17 13:12:26 -05:00
parent ceadb1325d
commit 5880593cb1
4 changed files with 79 additions and 46 deletions

View File

@ -123,8 +123,6 @@ Mob::Mob(const char* in_name,
tar_vector=0;
currently_fleeing = false;
last_z = 0;
last_major_update_position = m_Position;
AI_Init();
@ -3439,6 +3437,19 @@ void Mob::SetTarget(Mob* mob) {
this->GetTarget()->SendHPUpdate(false, true);
}
// For when we want a Ground Z at a location we are not at yet
// Like MoveTo.
float Mob::FindDestGroundZ(glm::vec3 dest, float z_offset)
{
float best_z = BEST_Z_INVALID;
if (zone->zonemap != nullptr)
{
dest.z += z_offset;
best_z = zone->zonemap->FindBestZ(dest, nullptr);
}
return best_z;
}
float Mob::FindGroundZ(float new_x, float new_y, float z_offset)
{
float ret = BEST_Z_INVALID;

View File

@ -954,7 +954,8 @@ public:
void SendTo(float new_x, float new_y, float new_z);
void SendToFixZ(float new_x, float new_y, float new_z);
float GetZOffset() const;
void FixZ(int32 z_find_offset = 5);
void FixZ(int32 z_find_offset = 5);
float GetFixedZ(glm::vec3 position, int32 z_find_offset = 5);
void NPCSpecialAttacks(const char* parse, int permtag, bool reset = true, bool remove = false);
inline uint32 DontHealMeBefore() const { return pDontHealMeBefore; }
inline uint32 DontBuffMeBefore() const { return pDontBuffMeBefore; }
@ -1108,8 +1109,6 @@ public:
int GetWeaponDamage(Mob *against, const EQEmu::ItemData *weapon_item);
int GetWeaponDamage(Mob *against, const EQEmu::ItemInstance *weapon_item, uint32 *hate = nullptr);
float last_z;
// Bots HealRotation methods
#ifdef BOTS
bool IsHealRotationTarget() { return (m_target_of_heal_rotation.use_count() && m_target_of_heal_rotation.get()); }
@ -1267,6 +1266,7 @@ protected:
virtual int16 GetFocusEffect(focusType type, uint16 spell_id) { return 0; }
void CalculateNewFearpoint();
float FindGroundZ(float new_x, float new_y, float z_offset=0.0);
float FindDestGroundZ(glm::vec3 dest, float z_offset=0.0);
glm::vec3 UpdatePath(float ToX, float ToY, float ToZ, float Speed, bool &WaypointChange, bool &NodeReached);
void PrintRoute();

View File

@ -503,7 +503,7 @@ void NPC::AI_Start(uint32 iMoveDelay) {
AIautocastspell_timer->Disable();
} else {
AIautocastspell_timer = std::unique_ptr<Timer>(new Timer(750));
AIautocastspell_timer->Start(RandomTimer(0, 15000), false);
AIautocastspell_timer->Start(RandomTimer(0, 300), false);
}
if (NPCTypedata) {
@ -1582,18 +1582,22 @@ void NPC::AI_DoMovement() {
}
this->FixZ();
SendPosition();
//kick off event_waypoint arrive
char temp[16];
sprintf(temp, "%d", cur_wp);
parse->EventNPC(EVENT_WAYPOINT_ARRIVE, CastToNPC(), nullptr, temp, 0);
// start moving directly to next waypoint if we're at a 0 pause waypoint and we didn't get quest halted.
if (!AI_walking_timer->Enabled())
// No need to move as we are there. Next loop will
// take care of normal grids, even at pause 0.
// We do need to call and setup a wp if we're cur_wp=-2
// as that is where roamer is unset and we don't want
// the next trip through to move again based on grid stuff.
doMove = false;
if (cur_wp == -2) {
AI_SetupNextWaypoint();
else
doMove = false;
}
// wipe feign memory since we reached our first waypoint
if(cur_wp == 1)
ClearFeignMemory();
@ -2593,7 +2597,7 @@ void NPC::AddSpellToNPCList(int16 iPriority, int16 iSpellID, uint32 iType,
// If we're going from an empty list, we need to start the timer
if (AIspells.size() == 1)
AIautocastspell_timer->Start(RandomTimer(0, 15000), false);
AIautocastspell_timer->Start(RandomTimer(0, 300), false);
}
void NPC::RemoveSpellFromNPCList(int16 spell_id)

View File

@ -176,9 +176,15 @@ void NPC::MoveTo(const glm::vec4& position, bool saveguardspot)
cur_wp = -2; // flag as quest controlled w/no grid
Log(Logs::Detail, Logs::AI, "MoveTo %s without a grid.", to_string(static_cast<glm::vec3>(position)).c_str());
}
glm::vec3 dest(position);
m_CurrentWayPoint = position;
m_CurrentWayPoint.z = GetFixedZ(dest);
if (saveguardspot)
{
m_GuardPoint = position;
m_GuardPoint = m_CurrentWayPoint;
if (m_GuardPoint.w == 0)
m_GuardPoint.w = 0.0001; //hack to make IsGuarding simpler
@ -189,7 +195,6 @@ void NPC::MoveTo(const glm::vec4& position, bool saveguardspot)
Log(Logs::Detail, Logs::AI, "Setting guard position to %s", to_string(static_cast<glm::vec3>(m_GuardPoint)).c_str());
}
m_CurrentWayPoint = position;
cur_wp_pause = 0;
pLastFightingDelayMoving = 0;
if (AI_walking_timer->Enabled())
@ -838,49 +843,62 @@ void Mob::SendToFixZ(float new_x, float new_y, float new_z) {
}
}
void Mob::FixZ(int32 z_find_offset /*= 5*/)
float Mob::GetFixedZ(glm::vec3 dest, int32 z_find_offset)
{
BenchTimer timer;
timer.reset();
float new_z = dest.z;
if (zone->HasMap() && RuleB(Map, FixZWhenMoving) && (flymode != 1 && flymode != 2))
if (zone->HasMap() && RuleB(Map, FixZWhenMoving) &&
(flymode != 1 && flymode != 2))
{
if (!RuleB(Watermap, CheckForWaterWhenMoving) || !zone->HasWaterMap() ||
(zone->HasWaterMap() && !zone->watermap->InWater(glm::vec3(m_Position))))
if (!RuleB(Watermap, CheckForWaterWhenMoving) || !zone->HasWaterMap()
|| (zone->HasWaterMap() &&
!zone->watermap->InWater(glm::vec3(m_Position))))
{
/* Any more than 5 in the offset makes NPC's hop/snap to ceiling in small corridors */
float new_z = this->FindGroundZ(m_Position.x, m_Position.y, z_find_offset);
new_z += this->GetZOffset();
new_z = this->FindDestGroundZ(dest,z_find_offset);
if (new_z != BEST_Z_INVALID)
{
new_z += this->GetZOffset();
auto duration = timer.elapsed();
Log(
Logs::Moderate,
Logs::FixZ,
"Mob::FixZ() (%s) returned %4.3f at %4.3f, %4.3f, %4.3f - Took %lf",
this->GetCleanName(),
new_z,
m_Position.x,
m_Position.y,
m_Position.z,
duration
);
if ((new_z > -2000) && new_z != BEST_Z_INVALID) {
if (RuleB(Map, MobZVisualDebug))
this->SendAppearanceEffect(78, 0, 0, 0, 0);
m_Position.z = new_z;
// If bad new Z restore old one
if (new_z < -2000) {
new_z = m_Position.z;
}
}
else {
if (RuleB(Map, MobZVisualDebug))
this->SendAppearanceEffect(103, 0, 0, 0, 0);
}
Log(Logs::General, Logs::FixZ, "%s is failing to find Z %f", this->GetCleanName(), std::abs(m_Position.z - new_z));
}
auto duration = timer.elapsed();
last_z = m_Position.z;
Log(Logs::Moderate, Logs::FixZ,
"Mob::FixZ() (%s) returned %4.3f at %4.3f, %4.3f, %4.3f - Took %lf",
this->GetCleanName(), new_z, m_Position.x, m_Position.y,
m_Position.z, duration);
}
return new_z;
}
void Mob::FixZ(int32 z_find_offset /*= 5*/)
{
glm::vec3 current_loc(m_Position);
float new_z=GetFixedZ(current_loc, z_find_offset);
if (new_z != m_Position.z)
{
if ((new_z > -2000) && new_z != BEST_Z_INVALID) {
if (RuleB(Map, MobZVisualDebug))
this->SendAppearanceEffect(78, 0, 0, 0, 0);
m_Position.z = new_z;
}
else {
if (RuleB(Map, MobZVisualDebug))
this->SendAppearanceEffect(103, 0, 0, 0, 0);
Log(Logs::General, Logs::FixZ, "%s is failing to find Z %f",
this->GetCleanName(), std::abs(m_Position.z - new_z));
}
}
}