I've been messing around with the code to make mobs move smoothly instead of jumping on top of you. I re-wrote portions of the Mob::CalculateNewPosition to use a more refined approach to moving. Also, I changed all references to CalculateNewPosition2 to use CalculateNewPosition.
This was developed and tested on 0.5.3 DR2 code.
In MobAI.cpp, just drop in this code to replace the old function:
Code:
bool Mob::CalculateNewPosition(float x, float y, float z, float speed) {
float ratio;
float target_distance;
if(GetID()==0)
return true;
// if NPC is rooted
if (speed == 0.0) {
SetHeading(CalculateHeadingToTarget(x, y));
if(moved){
SendPosition();
SetMoving(false);
moved=false;
}
SetRunAnimSpeed(0);
return true;
}
float nx = this->x_pos;
float ny = this->y_pos;
float nz = this->z_pos;
float nh = this->heading;
tarx=x;
tary=y;
tarz=z;
tar_vx = x - nx;
tar_vy = y - ny;
tar_vz = z - nz;
//If we are at our destination, then we don't need move!
if (tar_vx == 0 && tar_vy == 0 && tar_vz==0)
return false;
pRunAnimSpeed = (sint8)(speed*30);
speed *= 2.0f; //The 2.0 is adjustable to get the speed just right.
target_distance = sqrt (tar_vx*tar_vx + tar_vy*tar_vy + tar_vz*tar_vz);
heading = CalculateHeadingToTarget(x, y);
if(target_distance >= speed) // If we need to go father than we can in one cycle...
{
ratio = (speed/target_distance);
x_pos += tar_vx * ratio;
y_pos += tar_vy * ratio;
z_pos += tar_vz * ratio;
}
else //If we are with-in our one cycle distance...
{
x_pos = x;
y_pos = y;
z_pos = z;
}
//OP_MobUpdate
APPLAYER* outapp = NULL;
PlayerPositionUpdateServer_Struct* spu = NULL;
this->SetMoving(true);
moved=true;
outapp = new APPLAYER(OP_ClientUpdate, sizeof(PlayerPositionUpdateServer_Struct));
spu = (PlayerPositionUpdateServer_Struct*)outapp->pBuffer;
delta_x=x_pos-nx;
delta_y=y_pos-ny;
delta_z=z_pos-nz;
delta_heading=heading-nh;
MakeSpawnUpdate(spu);
spu->heading*=8;
entity_list.QueueCloseClients(this, outapp, true, 300);
safe_delete(outapp);
SetAppearance(0, false);
pLastChange = Timer::GetCurrentTime();
return true;
}
Another quick fix helps smooth out pet movement.
In MobAI.cpp, in the Mob::AI_Process function around line 892
Code:
else if (AImovement_timer->Check() && !IsRooted()) {
------------>>>>> //SetRunAnimSpeed(0);
if (GetOwnerID()) {
// we're a pet, do as we're told
By commenting out the SetRunAnimSpeed(0), the pet seems to move a little smoother, don't know why.
UPDATE - This is probably as good as it will get. Until the server can know the Z coordinate for each X,Y (or at least be pretty close), the mob will not handle large vertical changes between 2 way points that are far apart, such as steep stairs. My suggestion is to make a way point at the top and bottom of such things as stairs and hills.
I've tested the code out on Windows with great success. There is still some refining that needs to be done, but this gets us alot closer to properly moving creatures.
-Valdain
[Edit] - Fixed code after talking with Doodman