mirror of
https://github.com/EQEmu/Server.git
synced 2026-04-03 17:32:33 +00:00
Water work and work with grids (still not perfect but i think its the ai code)
This commit is contained in:
parent
f76fffe622
commit
973abef1b0
@ -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
|
// first add self
|
||||||
|
|
||||||
// The damage on the hate list is used to award XP to the killer. This check is to prevent Killstealing.
|
// The damage on the hate list is used to award XP to the killer. This check is to prevent Killstealing.
|
||||||
|
|||||||
@ -1061,6 +1061,7 @@ public:
|
|||||||
void SetCurrentWP(uint16 waypoint) { cur_wp = waypoint; }
|
void SetCurrentWP(uint16 waypoint) { cur_wp = waypoint; }
|
||||||
virtual FACTION_VALUE GetReverseFactionCon(Mob* iOther) { return FACTION_INDIFFERENT; }
|
virtual FACTION_VALUE GetReverseFactionCon(Mob* iOther) { return FACTION_INDIFFERENT; }
|
||||||
|
|
||||||
|
virtual const bool IsUnderwaterOnly() const { return false; }
|
||||||
inline bool IsTrackable() const { return(trackable); }
|
inline bool IsTrackable() const { return(trackable); }
|
||||||
Timer* GetAIThinkTimer() { return AI_think_timer.get(); }
|
Timer* GetAIThinkTimer() { return AI_think_timer.get(); }
|
||||||
Timer* GetAIMovementTimer() { return AI_movement_timer.get(); }
|
Timer* GetAIMovementTimer() { return AI_movement_timer.get(); }
|
||||||
|
|||||||
@ -1710,7 +1710,7 @@ void NPC::AI_DoMovement() {
|
|||||||
|
|
||||||
SetWaypointPause();
|
SetWaypointPause();
|
||||||
SetAppearance(eaStanding, false);
|
SetAppearance(eaStanding, false);
|
||||||
if (m_CurrentWayPoint.w >= 0.0) {
|
if (cur_wp_pause > 0 && m_CurrentWayPoint.w >= 0.0) {
|
||||||
RotateTo(m_CurrentWayPoint.w);
|
RotateTo(m_CurrentWayPoint.w);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1756,7 +1756,7 @@ void NPC::AI_DoMovement() {
|
|||||||
|
|
||||||
}
|
}
|
||||||
else if (IsGuarding()) {
|
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) {
|
if (at_gp) {
|
||||||
|
|
||||||
|
|||||||
@ -46,15 +46,6 @@ public:
|
|||||||
|
|
||||||
auto rotate_to_speed = m_rotate_to_mode == MovementRunning ? 50.0 : 16.0; //todo: get this from mob
|
auto rotate_to_speed = m_rotate_to_mode == MovementRunning ? 50.0 : 16.0; //todo: get this from mob
|
||||||
|
|
||||||
if (!m_started) {
|
|
||||||
m_started = true;
|
|
||||||
m->SetMoving(true);
|
|
||||||
|
|
||||||
if (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 from = FixHeading(m->GetHeading());
|
||||||
auto to = FixHeading(m_rotate_to);
|
auto to = FixHeading(m_rotate_to);
|
||||||
auto diff = to - from;
|
auto diff = to - from;
|
||||||
@ -68,6 +59,16 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
auto dist = std::abs(diff);
|
auto dist = std::abs(diff);
|
||||||
|
|
||||||
|
if (!m_started) {
|
||||||
|
m_started = true;
|
||||||
|
m->SetMoving(true);
|
||||||
|
|
||||||
|
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 td = rotate_to_speed * 19.0 * frame_time;
|
auto td = rotate_to_speed * 19.0 * frame_time;
|
||||||
|
|
||||||
if (td >= dist) {
|
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)
|
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 partial = false;
|
||||||
bool stuck = false;
|
bool stuck = false;
|
||||||
auto route = zone->pathing->FindRoute(glm::vec3(who->GetX(), who->GetY(), who->GetZ()), glm::vec3(x, y, z), partial, stuck);
|
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()) {
|
if (route.empty()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto &first = route.front();
|
auto &first = route.front();
|
||||||
|
auto &last = route.back();
|
||||||
|
|
||||||
//if who is already at the first node, then cull it
|
if (zone->HasWaterMap()) {
|
||||||
if (IsPositionEqualWithinCertainZ(glm::vec3(who->GetX(), who->GetY(), who->GetZ()), first.pos, 5.0f)) {
|
//If who is underwater & who is not at the first node
|
||||||
route.pop_front();
|
//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 (route.empty()) {
|
//If xyz is underwater & xyz is not at the last node
|
||||||
return;
|
//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());
|
AdjustRoute(route, who->GetFlyMode(), who->GetZOffset());
|
||||||
|
|
||||||
auto iter = _impl->Entries.find(who);
|
auto eiter = _impl->Entries.find(who);
|
||||||
auto &ent = (*iter);
|
auto &ent = (*eiter);
|
||||||
|
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 ¤t_node = (*iter);
|
||||||
|
|
||||||
|
iter++;
|
||||||
|
|
||||||
|
if (iter == route.end()) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
previous_pos = current_node.pos;
|
||||||
|
auto &next_node = (*iter);
|
||||||
|
|
||||||
|
if (first_node) {
|
||||||
|
|
||||||
first = route.front();
|
|
||||||
//If mode = walking then rotateto first node (if possible, live does this)
|
|
||||||
if (mode == MovementWalking) {
|
if (mode == MovementWalking) {
|
||||||
auto h = who->CalculateHeadingToTarget(first.pos.x, first.pos.y);
|
auto h = who->CalculateHeadingToTarget(next_node.pos.x, next_node.pos.y);
|
||||||
PushRotateTo(ent.second, who, h, mode);
|
PushRotateTo(ent.second, who, h, mode);
|
||||||
}
|
}
|
||||||
|
|
||||||
//for each node create a moveto/teleport command
|
first_node = false;
|
||||||
glm::vec3 previous_pos(who->GetX(), who->GetY(), who->GetZ());
|
}
|
||||||
for (auto &node : route) {
|
//yet rotate to node + 1
|
||||||
if (node.teleport) {
|
//auto h = CalculateHeadingAngleBetweenPositions(current_node.pos.x, current_node.pos.y, next_node.pos.x, next_node.pos.z);
|
||||||
PushTeleportTo(ent.second, node.pos.x, node.pos.y, node.pos.z,
|
//PushRotateTo(ent.second, who, h, mode);
|
||||||
CalculateHeadingAngleBetweenPositions(previous_pos.x, previous_pos.y, node.pos.x, node.pos.y));
|
|
||||||
|
//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 {
|
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) {
|
if (stuck) {
|
||||||
PushTeleportTo(ent.second, x, y, z,
|
PushTeleportTo(ent.second, x, y, z,
|
||||||
CalculateHeadingAngleBetweenPositions(previous_pos.x, previous_pos.y, x, y));
|
CalculateHeadingAngleBetweenPositions(previous_pos.x, previous_pos.y, x, y));
|
||||||
|
|||||||
@ -381,7 +381,7 @@ public:
|
|||||||
/* Only allows players that killed corpse to loot */
|
/* Only allows players that killed corpse to loot */
|
||||||
const bool HasPrivateCorpse() const { return NPCTypedata->private_corpse; }
|
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; }
|
const char* GetRawNPCTypeName() const { return NPCTypedata->name; }
|
||||||
|
|
||||||
void ChangeLastName(const char* in_lastname);
|
void ChangeLastName(const char* in_lastname);
|
||||||
|
|||||||
@ -392,7 +392,6 @@ void NPC::SetWaypointPause()
|
|||||||
|
|
||||||
if (cur_wp_pause == 0) {
|
if (cur_wp_pause == 0) {
|
||||||
AI_walking_timer->Start(100);
|
AI_walking_timer->Start(100);
|
||||||
AI_walking_timer->Trigger();
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user