mirror of
https://github.com/therealKyp/Earth-and-Beyond-server
synced 2026-08-13 22:23:03 -04:00
579 lines
No EOL
14 KiB
C++
579 lines
No EOL
14 KiB
C++
#include "Net7.h"
|
|
#include "ObjectClass.h"
|
|
#include "PlayerClass.h"
|
|
#include "ObjectManager.h"
|
|
#include <float.h>
|
|
|
|
void Object::ExtrapolatePosition(float av_speed, float tdiff)
|
|
{
|
|
float pos[3];
|
|
float *_heading = Heading();
|
|
|
|
pos[0] = av_speed * tdiff * _heading[0];
|
|
pos[1] = av_speed * tdiff * _heading[1];
|
|
pos[2] = av_speed * tdiff * _heading[2];
|
|
|
|
MovePosition(pos[0], pos[1], pos[2]);
|
|
}
|
|
|
|
//TODO: read in and use the sector boundaries
|
|
bool Object::CheckBoundaries()
|
|
{
|
|
float zboundary = 7500.0f;
|
|
float xmin = -1000000.0f;
|
|
float ymin = -1000000.0f;
|
|
float xmax = 1000000.0f;
|
|
float ymax = 1000000.0f;
|
|
bool interrupt_warp = false;
|
|
|
|
ServerParameters *params = m_SectorMgr->GetSectorParams();
|
|
|
|
if (params->XMax > 0 && params->YMax > 0)
|
|
{
|
|
xmin = params->XMin;
|
|
xmax = params->XMax;
|
|
ymin = params->YMin;
|
|
ymax = params->YMax;
|
|
}
|
|
|
|
m_Mutex.Lock();
|
|
|
|
if (PosZ() > zboundary)
|
|
{
|
|
m_Position_info.Position[2] = zboundary;
|
|
}
|
|
else if (PosZ() < -zboundary)
|
|
{
|
|
m_Position_info.Position[2] = -zboundary;
|
|
}
|
|
|
|
if (PosX() > xmax)
|
|
{
|
|
m_Position_info.Position[0] = xmax;
|
|
interrupt_warp = true;
|
|
}
|
|
else if (PosX() < xmin)
|
|
{
|
|
m_Position_info.Position[0] = xmin;
|
|
interrupt_warp = true;
|
|
}
|
|
|
|
if (PosY() > ymax)
|
|
{
|
|
m_Position_info.Position[1] = ymax;
|
|
interrupt_warp = true;
|
|
}
|
|
else if (PosY() < ymin)
|
|
{
|
|
m_Position_info.Position[1] = ymin;
|
|
interrupt_warp = true;
|
|
}
|
|
|
|
m_Mutex.Unlock();
|
|
|
|
return (interrupt_warp);
|
|
}
|
|
|
|
void Object::Turn(float Intensity)
|
|
{
|
|
long current_time = GetNet7TickCount();
|
|
CalcNewPosition(current_time, true);
|
|
m_Mutex.Lock();
|
|
m_ZInput = Intensity;
|
|
m_Position_info.RotZ = -Intensity/883.0f;
|
|
SetLastAccessTime(current_time);
|
|
m_ReceivedMovement = true;
|
|
m_Mutex.Unlock();
|
|
}
|
|
|
|
void Object::Tilt(float Intensity)
|
|
{
|
|
long current_time = GetNet7TickCount();
|
|
CalcNewPosition(current_time, true);
|
|
m_Mutex.Lock();
|
|
m_YInput = Intensity;
|
|
m_Position_info.RotY = -Intensity/883.0f;
|
|
SetLastAccessTime(current_time);
|
|
m_ReceivedMovement = true;
|
|
m_Mutex.Unlock();
|
|
}
|
|
|
|
void Object::CalcNewPosition(unsigned long current_tick, bool turn)
|
|
{
|
|
float tdiff;
|
|
float av_speed = 0.0f;
|
|
|
|
tdiff = (float)(current_tick - m_LastUpdate)/1000.0f;
|
|
|
|
if (tdiff < 5.0f) //if > 5.0s the system was hibernating
|
|
{
|
|
CalcNewHeading(tdiff);
|
|
|
|
//Now perform the acceleration calculations to update player velocity and get average speed of tdiff period
|
|
//av_speed = CalcVelocity(tdiff);
|
|
av_speed = m_Velocity;
|
|
|
|
if (av_speed != 0.0f)
|
|
{
|
|
ExtrapolatePosition(av_speed, tdiff);
|
|
}
|
|
}
|
|
|
|
m_LastUpdate = current_tick;
|
|
}
|
|
|
|
float *Object::MutexedPos()
|
|
{
|
|
m_Mutex.Lock();
|
|
return (m_Position_info.Position);
|
|
m_Mutex.Unlock();
|
|
}
|
|
|
|
void Object::CalcNewHeading(float tdiff)
|
|
{
|
|
float rot_Z[4] = { 0.0f, 0.0f, 0.0f, 1.0f };
|
|
float rot_Y[4] = { 0.0f, 0.0f, 0.0f, 1.0f };
|
|
float result[4];
|
|
|
|
if (m_ZInput != 0.0f)
|
|
{
|
|
rot_Z[2] = -m_ZInput*tdiff*0.42f/883.0f*1000.0f;
|
|
}
|
|
|
|
if (m_YInput != 0.0f)
|
|
{
|
|
rot_Y[1] = -m_YInput*tdiff*0.42f/883.0f*1000.0f;
|
|
}
|
|
|
|
Quat4fMul(rot_Z, rot_Y, result);
|
|
Quat4fMul(Orientation(), result, Orientation());
|
|
Quat4fNormalize(Orientation());
|
|
SetHeading();
|
|
}
|
|
|
|
///////////////////////////////////////////////////
|
|
// Range List Handling
|
|
//
|
|
// These methods handle adding to and removing from
|
|
// the object range lists.
|
|
|
|
//Generic method we can use to see if the input object can see 'this' object
|
|
//This virtual method is overriden where we can do something more efficient
|
|
bool Object::ObjectInRangeList(Object *obj)
|
|
{
|
|
bool in_range = false;
|
|
Player *p = (0);
|
|
if (obj->ObjectType() == OT_PLAYER)
|
|
{
|
|
p = (Player*)obj;
|
|
switch (this->ObjectType())
|
|
{
|
|
case OT_HULK:
|
|
case OT_RESOURCE:
|
|
case OT_FIELD:
|
|
case OT_HUSK:
|
|
in_range = GetIndex(p->ObjectRangeList());
|
|
break;
|
|
|
|
case OT_NAV:
|
|
case OT_DECO:
|
|
case OT_STATION:
|
|
case OT_STARGATE:
|
|
if (RangeFrom(p->Position()) < (Signature() + p->ShipIndex()->CurrentStats.GetScanRange()))
|
|
{
|
|
in_range = true;
|
|
}
|
|
break;
|
|
|
|
case OT_PLAYER:
|
|
LogMessage("*** Error - player/player range scan using baseclass Range method.\n");
|
|
//drop through to generic method
|
|
case OT_MOB:
|
|
//to be deprecated, should have method in MOB class
|
|
if (RangeFrom(p->Position()) < (5000.0f + p->ShipIndex()->CurrentStats.GetScanRange())) //Mob has 5000 sig
|
|
{
|
|
in_range = true;
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
else // just use a generic ranging method
|
|
{
|
|
if (RangeFrom(p->Position()) < (Signature() + 3000.0f))
|
|
{
|
|
in_range = true;
|
|
}
|
|
}
|
|
|
|
return in_range;
|
|
}
|
|
|
|
//End object rangelist stuff.
|
|
|
|
|
|
bool Object::ObjectIsMoving()
|
|
{
|
|
bool moving = true;
|
|
if (m_Velocity < 1.0f && m_Velocity > -1.0f)
|
|
{
|
|
moving = false;
|
|
}
|
|
return moving;
|
|
}
|
|
|
|
void Object::SendLocationAndSpeed(bool include_player) // this will be used for MOBs and hijacked Objects.
|
|
{
|
|
if (Active())
|
|
{
|
|
m_Mutex.Lock();
|
|
if (m_Velocity == 0.0f) //only transmit speed if required
|
|
{
|
|
m_Position_info.Bitmask = 0x00;
|
|
}
|
|
else
|
|
{
|
|
m_Position_info.Bitmask = 0x27;
|
|
}
|
|
|
|
m_Position_info.CurrentSpeed = m_Velocity*0.001f;
|
|
m_Position_info.MovementID = m_MovementID;
|
|
m_Position_info.SetSpeed = m_Velocity*0.001f;
|
|
m_Mutex.Unlock();
|
|
|
|
SendToVisibilityList(include_player); //send to all players in range
|
|
}
|
|
}
|
|
|
|
void Object::SendLocationAndSpeed(Player *player) // this will be used for MOBs, Players and hijacked Objects.
|
|
{
|
|
if (Active())
|
|
{
|
|
m_Mutex.Lock();
|
|
if (m_Velocity == 0.0f) //only transmit speed if required
|
|
{
|
|
m_Position_info.Bitmask = 0x00;
|
|
}
|
|
else
|
|
{
|
|
m_Position_info.Bitmask = 0x27;
|
|
}
|
|
|
|
if (ObjectType() == OT_MOB)
|
|
{
|
|
//m_Position_info.Bitmask |= 0x0100;
|
|
//m_Position_info.UpdatePeriod = 5000;
|
|
}
|
|
m_Position_info.CurrentSpeed = m_Velocity*0.001f;
|
|
m_Position_info.MovementID = m_MovementID;
|
|
m_Position_info.SetSpeed = m_Velocity*0.001f;
|
|
m_Mutex.Unlock();
|
|
|
|
player->SendAdvancedPositionalUpdate(GameID(), &m_Position_info);
|
|
}
|
|
}
|
|
|
|
//Send object to all players who can see us
|
|
void Object::SendToVisibilityList(bool include_player)
|
|
{
|
|
LogMessage("*** error, generic object baseclass send used!\n");
|
|
}
|
|
|
|
void Object::SetVelocity(float velocity)
|
|
{
|
|
m_Mutex.Lock();
|
|
m_Velocity = velocity;
|
|
m_Position_info.CurrentSpeed = m_Velocity*0.001f;
|
|
m_Mutex.Unlock();
|
|
}
|
|
|
|
void Object::SetHeading()
|
|
{
|
|
float _canDir[4] = { 1, 0, 0, 0 };
|
|
float _heading[4]= { 1, 0, 0, 0 };
|
|
|
|
float *ori = Orientation();
|
|
|
|
Quat4fMulInv(_canDir, Orientation(), _heading);
|
|
Quat4fMul(Orientation(), _heading, _heading);
|
|
|
|
m_Position_info.Velocity[0] = _heading[0];
|
|
m_Position_info.Velocity[1] = _heading[1];
|
|
m_Position_info.Velocity[2] = _heading[2];
|
|
}
|
|
|
|
//Vector Math members
|
|
void Object::CalcOrientation(float ZHeading, float YHeading)
|
|
{
|
|
float ZHdr = -(ZHeading + 3.141592654f) / 2.0f;
|
|
float YHdr = (YHeading) / 2.0f;
|
|
|
|
float rotation0[] = { 0.0f, 0.0f, 0.0f, 1.0f };
|
|
float rotation1[] = { 0.0f, sinf(YHdr), 0.0f, cosf(YHdr) };
|
|
float rotation2[] = { 0.0f, 0.0f, sinf(ZHdr), cosf(ZHdr) };
|
|
|
|
Quat4fMul1(rotation0, rotation1, Orientation());
|
|
Quat4fMul1(Orientation(), rotation2, Orientation());
|
|
}
|
|
|
|
//Object
|
|
void Object::Quat4fMul1(float vector1[], float vector2[], float *vector3)
|
|
{
|
|
float x1,y1,z1,w1,x2,y2,z2,w2;
|
|
|
|
w1 = vector1[0];
|
|
x1 = vector1[1];
|
|
y1 = vector1[2];
|
|
z1 = vector1[3];
|
|
|
|
w2 = vector2[0];
|
|
x2 = vector2[1];
|
|
y2 = vector2[2];
|
|
z2 = vector2[3];
|
|
|
|
vector3[0] = (w1*w2 - x1*x2 - y1*y2 - z1*z2);
|
|
vector3[1] = (w1*x2 + x1*w2 + y1*z2 - z1*y2);
|
|
vector3[2] = (w1*y2 - x1*z2 + y1*w2 + z1*x2);
|
|
vector3[3] = (w1*z2 + x1*y2 - y1*x2 + z1*w2);
|
|
}
|
|
|
|
void Object::Quat4fNormalize(float *vector1)
|
|
{
|
|
float x,y,z,w,magnitude;
|
|
|
|
x = vector1[0];
|
|
y = vector1[1];
|
|
z = vector1[2];
|
|
w = vector1[3];
|
|
|
|
magnitude = sqrtf(w*w + x*x + y*y + z*z);
|
|
vector1[3] /= magnitude;
|
|
vector1[0] /= magnitude;
|
|
vector1[1] /= magnitude;
|
|
vector1[2] /= magnitude;
|
|
}
|
|
|
|
//Object
|
|
void Object::Quat4fMul(float vector1[], float vector2[], float *vector3)
|
|
{
|
|
float x1,y1,z1,w1,x2,y2,z2,w2;
|
|
|
|
w1 = vector1[3];
|
|
x1 = vector1[0];
|
|
y1 = vector1[1];
|
|
z1 = vector1[2];
|
|
|
|
w2 = vector2[3];
|
|
x2 = vector2[0];
|
|
y2 = vector2[1];
|
|
z2 = vector2[2];
|
|
|
|
vector3[3] = (w1*w2 - x1*x2 - y1*y2 - z1*z2);
|
|
vector3[0] = (w1*x2 + x1*w2 + y1*z2 - z1*y2);
|
|
vector3[1] = (w1*y2 - x1*z2 + y1*w2 + z1*x2);
|
|
vector3[2] = (w1*z2 + x1*y2 - y1*x2 + z1*w2);
|
|
}
|
|
|
|
//Object
|
|
void Object::Quat4fMulInv(float vector1[], float vector2[], float *vector3)
|
|
{
|
|
float x1,y1,z1,w1,x2,y2,z2,w2;
|
|
|
|
w1 = vector1[3];
|
|
x1 = vector1[0];
|
|
y1 = vector1[1];
|
|
z1 = vector1[2];
|
|
|
|
w2 = vector2[3];
|
|
x2 = - vector2[0];
|
|
y2 = - vector2[1];
|
|
z2 = - vector2[2];
|
|
|
|
vector3[3] = (w1*w2 - x1*x2 - y1*y2 - z1*z2);
|
|
vector3[0] = (w1*x2 + x1*w2 + y1*z2 - z1*y2);
|
|
vector3[1] = (w1*y2 - x1*z2 + y1*w2 + z1*x2);
|
|
vector3[2] = (w1*z2 + x1*y2 - y1*x2 + z1*w2);
|
|
}
|
|
|
|
void Object::TransformCoords(float *pos1, float *pos2, float ori[])
|
|
{
|
|
float posr[3];
|
|
float w = ori[3];
|
|
float x = ori[0];
|
|
float y = ori[1];
|
|
float z = ori[2];
|
|
|
|
float px = pos2[0] - pos1[0];
|
|
float py = pos2[1] - pos1[1];
|
|
float pz = pos2[2] - pos1[2];
|
|
|
|
posr[0] = w*w*px + 2*y*w*pz - 2*z*w*py + x*x*px + 2*y*x*py + 2*z*x*pz - z*z*px - y*y*px;
|
|
posr[1] = 2*x*y*px + y*y*py + 2*z*y*pz + 2*w*z*px - z*z*py + w*w*py - 2*x*w*pz - x*x*py;
|
|
posr[2] = 2*x*z*px + 2*y*z*py + z*z*pz - 2*w*y*px - y*y*pz + 2*w*x*py - x*x*pz + w*w*pz;
|
|
|
|
pos1[0] = posr[0] + pos2[0];
|
|
pos1[1] = posr[1] + pos2[1];
|
|
pos1[2] = posr[2] + pos2[2];
|
|
}
|
|
|
|
//leave the object facing pos1 from pos2
|
|
void Object::CalcOrientation(float *pos1, float *pos2, bool set_heading)
|
|
{
|
|
float Distance;
|
|
float xdiff = fabsf(pos1[0]-pos2[0]);
|
|
float ydiff = fabsf(pos1[1]-pos2[1]);
|
|
float ZHeading, YHeading;
|
|
|
|
if (xdiff == 0) xdiff = 0.00001f;
|
|
if (ydiff == 0) ydiff = 0.00001f;
|
|
|
|
//first work out the total distance
|
|
Distance = sqrtf(powf(pos1[0]-pos2[0],2)
|
|
+ powf(pos1[1]-pos2[1],2)
|
|
+ powf(pos1[2]-pos2[2],2));
|
|
|
|
m_Mutex.Lock();
|
|
|
|
//now see what quadrant we're in and calculate the Z plane angle appropriately
|
|
if (pos1[0]-pos2[0] > 0)
|
|
{
|
|
if (pos1[1]-pos2[1] > 0)
|
|
{
|
|
//Quadrant 2
|
|
ZHeading = (PI/2.0f) + atanf(xdiff/ydiff);
|
|
}
|
|
else
|
|
{
|
|
//Quadrant 3
|
|
ZHeading = (PI) + atanf(ydiff/xdiff);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (pos1[1]-pos2[1] > 0)
|
|
{
|
|
//Quadrant 1
|
|
ZHeading = atanf(ydiff/xdiff);
|
|
}
|
|
else
|
|
{
|
|
//Quadrant 4
|
|
ZHeading = (3.0f/2.0f*PI) + atanf(xdiff/ydiff);
|
|
}
|
|
}
|
|
|
|
if (Distance > 0.0f)
|
|
{
|
|
YHeading = asinf((pos1[2] - pos2[2])/Distance);
|
|
}
|
|
else
|
|
{
|
|
YHeading = 0.0f;
|
|
}
|
|
|
|
if (_isnan(YHeading))
|
|
{
|
|
YHeading = 0.0f;
|
|
}
|
|
|
|
m_Mutex.Unlock();
|
|
|
|
CalcOrientation(ZHeading, YHeading);
|
|
|
|
if (set_heading)
|
|
{
|
|
SetHeading();
|
|
}
|
|
}
|
|
|
|
void Object::Face(Object *obj)
|
|
{
|
|
if (obj)
|
|
{
|
|
CalcOrientation(obj->Position(), Position());
|
|
m_ReceivedMovement = true;
|
|
}
|
|
}
|
|
|
|
float Object::GetAngleTo(float *pos)
|
|
{
|
|
float theta;
|
|
float distance = RangeFrom(pos, true);
|
|
float distance2;
|
|
//now work out a position in front of the object at 'Distance' range.
|
|
|
|
float epos[3];
|
|
float *_heading = Heading();
|
|
|
|
epos[0] = PosX() + ( distance * _heading[0] );
|
|
epos[1] = PosY() + ( distance * _heading[1] );
|
|
epos[2] = PosZ() + ( distance * _heading[2] );
|
|
|
|
//now calc distance between two points
|
|
|
|
distance2 = sqrtf(powf(pos[0]-epos[0],2)
|
|
+ powf(pos[1]-epos[1],2)
|
|
+ powf(pos[2]-epos[2],2));
|
|
|
|
//now do some trig to work out the theta
|
|
theta = 2* asinf(distance2/(2*distance));
|
|
|
|
return theta;
|
|
}
|
|
|
|
void Object::SetEulerOrientation(float roll, float pitch, float yaw)
|
|
{
|
|
float XHdr = (roll) / 2.0f;
|
|
float ZHdr = -(yaw + 3.141592654f) / 2.0f;
|
|
float YHdr = (pitch) / 2.0f;
|
|
|
|
float candirection[] = { 0.0f, 1.0f, 0.0f, 0.0f };
|
|
float rotation0[] = { sinf(XHdr), 0.0f, 0.0f, cosf(XHdr) };
|
|
float rotation1[] = { 0.0f, sinf(YHdr), 0.0f, cosf(YHdr) };
|
|
float rotation2[] = { 0.0f, 0.0f, sinf(ZHdr), cosf(ZHdr) };
|
|
|
|
m_Mutex.Lock();
|
|
Quat4fMul(rotation0, rotation1, Orientation());
|
|
Quat4fMul(Orientation(), rotation2, Orientation());
|
|
m_Mutex.Unlock();
|
|
}
|
|
|
|
void Object::LevelOrientation()
|
|
{
|
|
//work out a position in front of the object's nose at a fair distance.
|
|
float epos[3];
|
|
float *_heading = Heading();
|
|
|
|
epos[0] = PosX() + ( 2000.0f * _heading[0] );
|
|
epos[1] = PosY() + ( 2000.0f * _heading[1] );
|
|
epos[2] = PosZ() + ( 2000.0f * _heading[2] );
|
|
|
|
//now leave object facing that point directly
|
|
CalcOrientation(epos, Position(), false);
|
|
}
|
|
|
|
void Object::Rotate(float x, float y, float z)
|
|
{
|
|
float sinx = sin(x/2);
|
|
float siny = sin(y/2);
|
|
float sinz = sin(z/2);
|
|
|
|
float candirection[] = { 0.0f, 1.0f, 0.0f, 0.0f };
|
|
float rot_X[4] = { sinx, 0.0f, 0.0f, cosf(x/2) };
|
|
float rot_Y[4] = { 0.0f, siny, 0.0f, cosf(y/2) };
|
|
float rot_Z[4] = { 0.0f, 0.0f, sinz, cosf(z/2) };
|
|
|
|
float result[4];
|
|
|
|
Quat4fMul(rot_X, rot_Y, result);
|
|
Quat4fMul(result, rot_Z, result);
|
|
Quat4fMul(Orientation(), result, Orientation());
|
|
Quat4fMulInv(candirection, result, Heading());
|
|
Quat4fNormalize(Orientation());
|
|
SetHeading();
|
|
}
|
|
|
|
void Object::LevelOut()
|
|
{
|
|
float *_heading = Heading();
|
|
_heading[2] = 0.0f;
|
|
} |