Changing object rotations to use 16 bit unsigned values instead of the current

mix of signed and floating point types. This allows us to use under and over
flow as features instead of failures. There are many conversions using DEG() and
UNDEG() in the code now - these should be read as TODO items for further work.
There is a high chance of bugs being introduced. Patch reviewed by Cyp_.


git-svn-id: https://warzone2100.svn.sourceforge.net/svnroot/warzone2100/trunk@10067 4a71c877-e1ca-e34f-864e-861f7616d084
master
Per Inge Mathisen 2010-02-28 23:14:52 +00:00 committed by Git SVN Gateway
parent 78c10eb0e7
commit 924b6c5169
37 changed files with 340 additions and 582 deletions

View File

@ -46,11 +46,8 @@ extern "C"
static const int DEG_360 = 65536;
static const float DEG_1 = (float)65536 / 360.f;
static inline WZ_DECL_CONST int DEG(const float degree)
{
return (int)(degree * DEG_1);
}
static inline WZ_DECL_CONST float UNDEG(uint16_t angle) { return angle * 360 / 65536.0f; }
static inline WZ_DECL_CONST int DEG(const float degree) { return (int)(degree * DEG_1); }
#ifdef __cplusplus
}

View File

@ -37,9 +37,8 @@ typedef struct { int x, y; } Vector2i;
typedef struct { float x, y; } Vector2f;
typedef struct { int x, y, z; } Vector3i;
typedef struct { float x, y, z; } Vector3f;
typedef struct { uint16_t x, y, z; } Vector3uw;
typedef struct { uint16_t direction, pitch, roll; } Rotation;
typedef Vector3i Position;
typedef Vector3uw Rotation;
/*!
* Create a Vector from x and y
@ -361,18 +360,6 @@ static inline WZ_DECL_CONST Vector3i Vector3f_To3i(const Vector3f v)
}
/*!
* Convert a float vector to short
* \param v Vector to convert
* \return Short vector
*/
static inline WZ_DECL_CONST Vector3uw Vector3f_To3uw(const Vector3f v)
{
Vector3uw dest = { (uint16_t)v.x, (uint16_t)v.y, (uint16_t)v.z };
return dest;
}
/*!
* \return true if both vectors are equal
*/
@ -608,18 +595,6 @@ static inline WZ_DECL_CONST Vector3f Vector3i_To3f(const Vector3i v)
}
/*!
* Convert an integer vector to short
* \param v Vector to convert
* \return Short vector
*/
static inline WZ_DECL_CONST Vector3uw Vector3i_To3uw(const Vector3i v)
{
Vector3uw dest = { (uint16_t)v.x, (uint16_t)v.y, (uint16_t)v.z };
return dest;
}
/*!
* Convert a vector of degree angles into radians.
* \param v Vector to convert
@ -821,51 +796,6 @@ static inline WZ_DECL_CONST Vector3i Vector3i_LinearInterpolate(const Vector3i f
}
/*!
* Print a vector to stdout
*/
static inline void Vector3uw_Print(const Vector3uw v)
{
printf("V: x:%u, y:%u, z:%u\n", v.x, v.y, v.z);
}
/*!
* Set the vector field by field, same as v = (Vector3uw){x, y, z};
* Needed for MSVC which doesn't support C99 struct assignments.
* \param x,y,z Coordinates
* \return New Vector
*/
static inline WZ_DECL_CONST Vector3uw Vector3uw_Init(const unsigned int x, const unsigned int y, const unsigned int z)
{
Vector3uw dest = { x, y, z };
return dest;
}
/*!
* Convert an short vector to int
* \param v Vector to convert
* \return Short vector
*/
static inline WZ_DECL_CONST Vector3i Vector3uw_To3i(const Vector3uw v)
{
Vector3i dest = { (int)v.x, (int)v.y, (int)v.z };
return dest;
}
/*!
* Convert an short vector to int
* \param v Vector to convert
* \return Short vector
*/
static inline WZ_DECL_CONST Vector3f Vector3uw_To3f(const Vector3uw v)
{
Vector3f dest = { (float)v.x, (float)v.y, (float)v.z };
return dest;
}
#ifdef __cplusplus
}
#endif //__cplusplus

View File

@ -413,14 +413,14 @@ BOOL NETbin(char *str, uint16_t maxlen)
return true;
}
BOOL NETVector3uw(Vector3uw* vp)
BOOL NETRotation(Rotation *vp)
{
return (NETuint16_t(&vp->x)
&& NETuint16_t(&vp->y)
&& NETuint16_t(&vp->z));
return (NETuint16_t(&vp->direction)
&& NETuint16_t(&vp->pitch)
&& NETuint16_t(&vp->roll));
}
BOOL NETVector3i(Vector3i* vp)
BOOL NETPosition(Position *vp)
{
return (NETint32_t(&vp->x)
&& NETint32_t(&vp->y)

View File

@ -91,9 +91,8 @@ do \
} while(0)
#endif
BOOL NETVector3uw(Vector3uw* vp);
BOOL NETVector3i(Vector3i* vp);
#define NETPosition(_pos) NETVector3i(_pos)
BOOL NETPosition(Position *vp);
BOOL NETRotation(Rotation *vp);
/**
* Get player who is the source of the current packet.

View File

@ -315,12 +315,12 @@ void actionAlignTurret(BASE_OBJECT *psObj, int weapon_slot)
switch (psObj->type)
{
case OBJ_DROID:
tRot = ((DROID *)psObj)->asWeaps[weapon_slot].rotation;
tPitch = ((DROID *)psObj)->asWeaps[weapon_slot].pitch;
tRot = UNDEG(((DROID *)psObj)->asWeaps[weapon_slot].rot.direction);
tPitch = UNDEG(((DROID *)psObj)->asWeaps[weapon_slot].rot.pitch);
break;
case OBJ_STRUCTURE:
tRot = ((STRUCTURE *)psObj)->asWeaps[weapon_slot].rotation;
tPitch = ((STRUCTURE *)psObj)->asWeaps[weapon_slot].pitch;
tRot = UNDEG(((STRUCTURE *)psObj)->asWeaps[weapon_slot].rot.direction);
tPitch = UNDEG(((STRUCTURE *)psObj)->asWeaps[weapon_slot].rot.pitch);
// now find the nearest 90 degree angle
nearest = (UWORD)(((tRot + 45) / 90) * 90);
@ -388,15 +388,15 @@ void actionAlignTurret(BASE_OBJECT *psObj, int weapon_slot)
switch (psObj->type)
{
case OBJ_DROID:
((DROID *)psObj)->asWeaps[weapon_slot].rotation = tRot;
((DROID *)psObj)->asWeaps[weapon_slot].pitch = tPitch;
((DROID *)psObj)->asWeaps[weapon_slot].rot.direction = DEG(tRot);
((DROID *)psObj)->asWeaps[weapon_slot].rot.pitch = DEG(tPitch);
break;
case OBJ_STRUCTURE:
// now adjust back to the nearest 90 degree angle
tRot = (UWORD)((tRot + nearest) % 360);
((STRUCTURE *)psObj)->asWeaps[weapon_slot].rotation = tRot;
((STRUCTURE *)psObj)->asWeaps[weapon_slot].pitch = tPitch;
((STRUCTURE *)psObj)->asWeaps[weapon_slot].rot.direction = DEG(tRot);
((STRUCTURE *)psObj)->asWeaps[weapon_slot].rot.pitch = DEG(tPitch);
break;
default:
ASSERT(!"invalid object type", "invalid object type");
@ -448,8 +448,8 @@ BOOL actionTargetTurret(BASE_OBJECT *psAttacker, BASE_OBJECT *psTarget, WEAPON *
pitchRate = (SWORD) (rotRate / 2);
}
tRotation = psWeapon->rotation;
tPitch = psWeapon->pitch;
tRotation = UNDEG(psWeapon->rot.direction);
tPitch = UNDEG(psWeapon->rot.pitch);
//set the pitch limits based on the weapon stats of the attacker
pitchLowerLimit = pitchUpperLimit = 0;
@ -505,9 +505,9 @@ BOOL actionTargetTurret(BASE_OBJECT *psAttacker, BASE_OBJECT *psTarget, WEAPON *
}*/
//and point the turret at target
targetRotation = calcDirection(psAttacker->pos.x, psAttacker->pos.y, psTarget->pos.x, psTarget->pos.y);
targetRotation = UNDEG(calcDirection(psAttacker->pos.x, psAttacker->pos.y, psTarget->pos.x, psTarget->pos.y));
rotationError = targetRotation - (tRotation + psAttacker->direction);
rotationError = targetRotation - (tRotation + UNDEG(psAttacker->rot.direction));
//restrict rotationerror to =/- 180 degrees
while (rotationError > 180)
@ -540,13 +540,13 @@ BOOL actionTargetTurret(BASE_OBJECT *psAttacker, BASE_OBJECT *psTarget, WEAPON *
}
else //roughly there so lock on and fire
{
if ( (SDWORD)psAttacker->direction > targetRotation )
if (UNDEG(psAttacker->rot.direction) > targetRotation)
{
tRotation = (SWORD)(targetRotation + 360 - psAttacker->direction);
tRotation = (SWORD)(targetRotation + 360 - UNDEG(psAttacker->rot.direction));
}
else
{
tRotation = (SWORD)(targetRotation - psAttacker->direction);
tRotation = (SWORD)(targetRotation - UNDEG(psAttacker->rot.direction));
}
onTarget = true;
}
@ -635,8 +635,8 @@ BOOL actionTargetTurret(BASE_OBJECT *psAttacker, BASE_OBJECT *psTarget, WEAPON *
}
}
psWeapon->rotation = tRotation;
psWeapon->pitch = tPitch;
psWeapon->rot.direction = DEG(tRotation);
psWeapon->rot.pitch = DEG(tPitch);
return onTarget;
}
@ -1447,11 +1447,11 @@ void actionUpdateDroid(DROID *psDroid)
if (!psWeapStats->rotate)
{
// no rotating turret - need to check aligned with target
const int targetDir = calcDirection(psDroid->pos.x,
const int targetDir = UNDEG(calcDirection(psDroid->pos.x,
psDroid->pos.y,
psActionTarget->pos.x,
psActionTarget->pos.y);
dirDiff = labs(targetDir - psDroid->direction);
psActionTarget->pos.y));
dirDiff = labs(targetDir - UNDEG(psDroid->rot.direction));
}
if (dirDiff > FIXED_TURRET_DIR)
@ -1708,8 +1708,8 @@ void actionUpdateDroid(DROID *psDroid)
{
for(i = 0;i < psDroid->numWeaps;i++)
{
if ((psDroid->asWeaps[i].rotation != 0) ||
(psDroid->asWeaps[i].pitch != 0))
if ((psDroid->asWeaps[i].rot.direction != 0) ||
(psDroid->asWeaps[i].rot.pitch != 0))
{
actionAlignTurret((BASE_OBJECT *)psDroid, i);
}
@ -2553,8 +2553,7 @@ void actionUpdateDroid(DROID *psDroid)
//use 0 for all non-combat droid types
if (psDroid->numWeaps == 0)
{
if ((psDroid->asWeaps[0].rotation != 0) ||
(psDroid->asWeaps[0].pitch != 0))
if (psDroid->asWeaps[0].rot.direction != 0 || psDroid->asWeaps[0].rot.pitch != 0)
{
actionAlignTurret((BASE_OBJECT *)psDroid, 0);
}
@ -2563,8 +2562,7 @@ void actionUpdateDroid(DROID *psDroid)
{
for (i = 0;i < psDroid->numWeaps;i++)
{
if ((psDroid->asWeaps[i].rotation != 0) ||
(psDroid->asWeaps[i].pitch != 0))
if (psDroid->asWeaps[i].rot.direction != 0 || psDroid->asWeaps[i].rot.pitch != 0)
{
actionAlignTurret((BASE_OBJECT *)psDroid, i);
}

View File

@ -65,10 +65,8 @@ typedef struct _tilePos
OBJECT_TYPE type; /**< The type of object */ \
UDWORD id; /**< ID number of the object */ \
Position pos; /**< Position of the object */ \
float direction; /**< Object's yaw +ve rotation around up-axis */ \
SWORD pitch; /**< Object's pitch +ve rotation around right-axis (nose up/down) */ \
Rotation rot; /**< Object's yaw +ve rotation around up-axis */ \
UBYTE player; /**< Which player the object belongs to */ \
SWORD roll; /**< Object's roll +ve rotation around forward-axis (left wing up/down) */ \
UDWORD born; /**< Time the game object was born */ \
UDWORD died; /**< When an object was destroyed, if 0 still alive */ \
uint32_t time /**< Game time of given space-time position. */
@ -125,27 +123,22 @@ typedef struct SpaceTime
uint32_t time; ///< Game time
Position pos; ///< Position of the object
int16_t pitch; ///< Object's pitch +ve rotation around right-axis (nose up/down)
float direction; ///< Object's yaw +ve rotation around up-axis
int16_t roll; ///< Object's roll +ve rotation around forward-axis (left wing up/down)
Rotation rot; ///< Rotation of the object
} SPACETIME;
static inline SPACETIME constructSpacetime(Position pos, float direction, int16_t pitch, int16_t roll, uint32_t time)
static inline SPACETIME constructSpacetime(Position pos, Rotation rot, uint32_t time)
{ // we don't support C99 struct assignments
SPACETIME ret;
ret.time = time;
ret.pos.x = pos.x;
ret.pos.y = pos.y;
ret.pos.z = pos.z;
ret.pitch = pitch;
ret.direction = direction;
ret.roll = roll;
ret.pos = pos;
ret.rot = rot;
return ret;
}
#define GET_SPACETIME(psObj) constructSpacetime(psObj->pos, psObj->direction, psObj->pitch, psObj->roll, psObj->time)
#define SET_SPACETIME(psObj, st) do { psObj->pos = st.pos; psObj->direction = st.direction; psObj->pitch = st.pitch; psObj->roll = st.roll; psObj->time = st.time; } while(0)
#define GET_SPACETIME(psObj) constructSpacetime(psObj->pos, psObj->rot, psObj->time)
#define SET_SPACETIME(psObj, st) do { psObj->pos = st.pos; psObj->rot = st.rot; psObj->time = st.time; } while(0)
static inline bool isDead(const BASE_OBJECT* psObj)
{

View File

@ -31,32 +31,29 @@ static inline float interpolateFloat(float v1, float v2, uint32_t t1, uint32_t t
return v1 + (v2 - v1) * numer/denom;
}
Vector3i interpolatePos(Vector3i p1, Vector3i p2, uint32_t t1, uint32_t t2, uint32_t t)
static inline uint16_t interpolateDegree(uint16_t v1, uint16_t v2, uint32_t t1, uint32_t t2, uint32_t t)
{
Vector3i ret = { interpolateInt(p1.x, p2.x, t1, t2, t),
uint16_t numer = t - t1, denom = t2 - t1;
int16_t diff = v2 - v1;
return v1 + diff * numer / denom;
}
Vector3i interpolatePos(Position p1, Position p2, uint32_t t1, uint32_t t2, uint32_t t)
{
Position ret = { interpolateInt(p1.x, p2.x, t1, t2, t),
interpolateInt(p1.y, p2.y, t1, t2, t),
interpolateInt(p1.z, p2.z, t1, t2, t)
};
return ret;
}
float interpolateDirection(float v1, float v2, uint32_t t1, uint32_t t2, uint32_t t)
Rotation interpolateRot(Rotation v1, Rotation v2, uint32_t t1, uint32_t t2, uint32_t t)
{
if (v1 > v2 + 180)
{
v2 += 360;
}
else if(v2 > v1 + 180)
{
v1 += 360;
}
return interpolateFloat(v1, v2, t1, t2, t);
}
int16_t interpolateIntAngle(int16_t v1, int16_t v2, uint32_t t1, uint32_t t2, uint32_t t)
{
int delta = (v2 - v1 + 360000 + 180)%360 - 180; // delta: [-180; 179].
return (interpolateInt(v1, v1 + delta, t1, t2, t) + 360000)%360; // [0; 359]
Rotation rot = { interpolateDegree(v1.direction, v2.direction, t1, t2, t),
interpolateDegree(v1.pitch, v2.pitch, t1, t2, t),
interpolateDegree(v1.roll, v2.roll, t1, t2, t),
};
return rot;
}
SPACETIME interpolateSpacetime(SPACETIME st1, SPACETIME st2, uint32_t t)
@ -66,12 +63,7 @@ SPACETIME interpolateSpacetime(SPACETIME st1, SPACETIME st2, uint32_t t)
debug(LOG_WARNING, "st1.time = %u, st2.time = %u, t = %u\n", (unsigned)st1.time, (unsigned)st2.time, (unsigned)t);
return st2;
}
return constructSpacetime(interpolatePos(st1.pos, st2.pos, st1.time, st2.time, t),
interpolateDirection(st1.direction, st2.direction, st1.time, st2.time, t),
interpolateIntAngle(st1.pitch, st2.pitch, st1.time, st2.time, t),
interpolateIntAngle(st1.roll, st2.roll, st1.time, st2.time, t),
t
);
return constructSpacetime(interpolatePos(st1.pos, st2.pos, st1.time, st2.time, t), interpolateRot(st1.rot, st2.rot, st1.time, st2.time, t), t);
}
SPACETIME interpolateObjectSpacetime(SIMPLE_OBJECT *obj, uint32_t t)
@ -119,8 +111,4 @@ void checkObject(const BASE_OBJECT* psObject, const char * const location_descri
|| psObject->type == OBJ_TARGET
|| psObject->player < MAX_PLAYERS,
location_description, function, "CHECK_OBJECT: Out of bound owning player number (%u)", (unsigned int)psObject->player);
ASSERT_HELPER(psObject->direction <= 360.0f
&& psObject->direction >= 0.0f,
location_description, function, "CHECK_OBJECT: Out of range direction (%f)", (float)psObject->direction);
}

View File

@ -40,11 +40,9 @@ static inline unsigned interpolateInt(int32_t v1, int32_t v2, uint32_t t1, uint3
}
/// Get interpolated position at time t.
Vector3i interpolatePos(Vector3i p1, Vector3i p2, uint32_t t1, uint32_t t2, uint32_t t);
Position interpolatePos(Vector3i p1, Vector3i p2, uint32_t t1, uint32_t t2, uint32_t t);
/// Get interpolated direction at time t.
float interpolateDirection(float v1, float v2, uint32_t t1, uint32_t t2, uint32_t t);
/// Get interpolated pitch or roll at time t.
int16_t interpolateIntAngle(int16_t v1, int16_t v2, uint32_t t1, uint32_t t2, uint32_t t);
Rotation interpolateRot(Rotation v1, Rotation v2, uint32_t t1, uint32_t t2, uint32_t t);
/// Get interpolated spacetime at time t.
SPACETIME interpolateSpacetime(SPACETIME st1, SPACETIME st2, uint32_t t);
/// Get interpolated object spacetime at time t.

View File

@ -228,8 +228,8 @@ void combFire(WEAPON *psWeap, BASE_OBJECT *psAttacker, BASE_OBJECT *psTarget, in
// if the turret doesn't turn, check if the attacker is in alignment with the target
if (psAttacker->type == OBJ_DROID && !psStats->rotate)
{
targetDir = calcDirection(psAttacker->pos.x, psAttacker->pos.y, psTarget->pos.x, psTarget->pos.y);
dirDiff = labs(targetDir - (SDWORD)psAttacker->direction);
targetDir = UNDEG(calcDirection(psAttacker->pos.x, psAttacker->pos.y, psTarget->pos.x, psTarget->pos.y));
dirDiff = labs(targetDir - (SDWORD)UNDEG(psAttacker->rot.direction));
if (dirDiff > FIXED_TURRET_DIR)
{
return;
@ -383,9 +383,9 @@ void combFire(WEAPON *psWeap, BASE_OBJECT *psAttacker, BASE_OBJECT *psTarget, in
}
}
predict.x = trigSin( ((DROID *)psTarget)->sMove.moveDir ) * ((DROID *)psTarget)->sMove.speed * flightTime;
predict.x = trigSin(UNDEG(((DROID *)psTarget)->sMove.moveDir)) * ((DROID *)psTarget)->sMove.speed * flightTime;
predict.x += psTarget->pos.x;
predict.y = trigCos( ((DROID *)psTarget)->sMove.moveDir ) * ((DROID *)psTarget)->sMove.speed * flightTime;
predict.y = trigCos(UNDEG(((DROID *)psTarget)->sMove.moveDir)) * ((DROID *)psTarget)->sMove.speed * flightTime;
predict.y += psTarget->pos.y;
// Make sure we don't pass any negative or out of bounds numbers to proj_SendProjectile

View File

@ -226,7 +226,7 @@ void displayIMDButton(iIMDShape *IMDShape, Vector3i *Rotation, Vector3i *Positio
//changed it to loop thru and draw all weapons
void displayStructureButton(STRUCTURE *psStructure, Vector3i *Rotation, Vector3i *Position, BOOL RotXYZ, SDWORD scale)
void displayStructureButton(STRUCTURE *psStructure, Vector3i *rotation, Vector3i *Position, BOOL RotXYZ, SDWORD scale)
{
iIMDShape *baseImd,*strImd;//*mountImd,*weaponImd;
iIMDShape *mountImd[STRUCT_MAXWEAPS];
@ -243,7 +243,7 @@ void displayStructureButton(STRUCTURE *psStructure, Vector3i *Rotation, Vector3i
Position->y -= 20;
}
setMatrix(Position, Rotation, RotXYZ);
setMatrix(Position, rotation, RotXYZ);
pie_MatScale(scale);
/* Draw the building's base first */
@ -300,9 +300,11 @@ void displayStructureButton(STRUCTURE *psStructure, Vector3i *Rotation, Vector3i
{
for (i = 0; i < MAX(1, psStructure->numWeaps); i++)
{
Rotation rot = structureGetInterpolatedWeaponRotation(psStructure, i, graphicsTime);
iV_MatrixBegin();
iV_TRANSLATE(strImd->connectors[i].x,strImd->connectors[i].z,strImd->connectors[i].y);
pie_MatRotY(DEG(-structureGetInterpolatedWeaponRotation(psStructure, i, graphicsTime)));
pie_MatRotY(-rot.direction);
if (mountImd[i] != NULL)
{
pie_Draw3DShape(mountImd[i], 0, getPlayerColour(selectedPlayer), WZCOL_WHITE, WZCOL_BLACK, pie_BUTTON, 0);
@ -311,7 +313,7 @@ void displayStructureButton(STRUCTURE *psStructure, Vector3i *Rotation, Vector3i
iV_TRANSLATE(mountImd[i]->connectors->x,mountImd[i]->connectors->z,mountImd[i]->connectors->y);
}
}
iV_MatrixRotateX(DEG(structureGetInterpolatedWeaponPitch(psStructure, i, graphicsTime)));
iV_MatrixRotateX(rot.pitch);
pie_Draw3DShape(weaponImd[i], 0, getPlayerColour(selectedPlayer), WZCOL_WHITE, WZCOL_BLACK, pie_BUTTON, 0);
//we have a droid weapon so do we draw a muzzle flash
iV_MatrixEnd();
@ -582,7 +584,7 @@ void displayComponentObject(DROID *psDroid)
psPropStats = asPropulsionStats + psDroid->asBits[COMP_PROPULSION].nStat;
worldAngle = (UDWORD)(player.r.y / DEG_1) % 360;
difference = worldAngle - st.direction;
difference = worldAngle - UNDEG(st.rot.direction);
leftFirst = !((difference> 0 && difference < 180) || difference < -180);
@ -607,17 +609,17 @@ void displayComponentObject(DROID *psDroid)
}
/* Get all the pitch,roll,yaw info */
rotation.y = -st.direction;
rotation.x = st.pitch;
rotation.z = st.roll;
rotation.y = -st.rot.direction;
rotation.x = st.rot.pitch;
rotation.z = st.rot.roll;
/* Translate origin */
pie_TRANSLATE(position.x,position.y,position.z);
/* Rotate for droid */
pie_MatRotY(DEG(rotation.y));
pie_MatRotX(DEG(rotation.x));
pie_MatRotZ(DEG(rotation.z));
pie_MatRotY(rotation.y);
pie_MatRotX(rotation.x);
pie_MatRotZ(rotation.z);
if( (gameTime-psDroid->timeLastHit < GAME_TICKS_PER_SEC) && psDroid->lastHitWeapon == WSC_ELECTRONIC)
{
@ -668,9 +670,11 @@ void displayComponentObject(DROID *psDroid)
static void pie_MatRotYMinusDroidRotation(DROID *psDroid, int weaponSlot, uint32_t time)
{
// Is this check really useful? Left it in here, in case it somehow helps performance.
if(psDroid->asWeaps[0].rotation != 0 || psDroid->asWeaps[0].prevRotation != 0)
if(psDroid->asWeaps[0].rot.direction != 0 || psDroid->asWeaps[0].prevRot.direction != 0)
{
pie_MatRotY(DEG(-getInterpolatedWeaponRotation(psDroid, weaponSlot, time)));
Rotation rot = getInterpolatedWeaponRotation(psDroid, weaponSlot, time);
pie_MatRotY(-rot.direction);
}
}
@ -875,6 +879,8 @@ void displayCompObj(DROID *psDroid, BOOL bButton)
{
if ( psShapeTemp->connectors )
{
Rotation rot = getInterpolatedWeaponRotation(psDroid, i, graphicsTime);
pie_MatBegin();
//reset Z?
dummyZ = pie_RotateProject(&zero, &screenCoords);
@ -924,12 +930,12 @@ void displayCompObj(DROID *psDroid, BOOL bButton)
if ( iConnector >= VTOL_CONNECTOR_START )
{
//pitch the barrel down
pie_MatRotX(DEG(-getInterpolatedWeaponPitch(psDroid, i, graphicsTime)));
pie_MatRotX(-rot.pitch);
}
else
{
//pitch the barrel up
pie_MatRotX(DEG(getInterpolatedWeaponPitch(psDroid, i, graphicsTime)));
pie_MatRotX(rot.pitch);
}
/* Get the weapon (gun?) graphic */
@ -1150,6 +1156,7 @@ void displayCompObj(DROID *psDroid, BOOL bButton)
if(psShape->nconnectors && psDroid->action == DACTION_DROIDREPAIR)
{
SPACETIME st = interpolateSpacetime(psDroid->prevSpacetime, GET_SPACETIME(psDroid), graphicsTime);
Rotation rot = getInterpolatedWeaponRotation(psDroid, 0, graphicsTime);
pie_TRANSLATE( psShape->connectors[0].x,
psShape->connectors[0].z,
@ -1159,11 +1166,11 @@ void displayCompObj(DROID *psDroid, BOOL bButton)
psShape = getImdFromIndex(MI_FLAME);
/* Rotate for droid */
pie_MatRotY(DEG(st.direction));
pie_MatRotX(DEG(-st.pitch));
pie_MatRotZ(DEG(-st.roll));
pie_MatRotY(st.rot.direction);
pie_MatRotX(-st.rot.pitch);
pie_MatRotZ(-st.rot.roll);
//rotate Y
pie_MatRotY(DEG(getInterpolatedWeaponRotation(psDroid, 0, graphicsTime)));
pie_MatRotY(rot.direction);
iV_MatrixRotateY(-player.r.y);
iV_MatrixRotateX(-player.r.x);

View File

@ -1851,11 +1851,11 @@ static inline void dealWithLMBDroid(DROID* psDroid, SELECTION_TYPE selection)
if (getDebugMappingStatus()) // cheating on, so output debug info
{
CONPRINTF(ConsoleString, (ConsoleString,
"%s - Damage %d%% - ID %d - experience %f, %s - order %s - action %s - sensor range %hu power %hu - ECM %u",
"%s - Damage %d%% - ID %d - experience %f, %s - order %s - action %s - sensor range %hu power %hu - ECM %u - pitch %.0f",
droidGetName(psDroid),
100 - clip(PERCENT(psDroid->body, psDroid->originalBody), 0, 100), psDroid->id,
psDroid->experience, getDroidLevelName(psDroid), getDroidOrderName(psDroid->order), getDroidActionName(psDroid->action),
droidSensorRange(psDroid), droidSensorPower(psDroid), droidConcealment(psDroid)));
droidSensorRange(psDroid), droidSensorPower(psDroid), droidConcealment(psDroid), UNDEG(psDroid->rot.pitch)));
FeedbackOrderGiven();
}
else

View File

@ -1147,11 +1147,11 @@ void renderProjectile(PROJECTILE *psCurr)
iV_TRANSLATE(rx,0,-rz);
/* Rotate it to the direction it's facing */
imdRot2.y = DEG(st.direction);
imdRot2.y = st.rot.direction;
iV_MatrixRotateY(-imdRot2.y);
/* pitch it */
imdRot2.x = DEG(st.pitch);
imdRot2.x = st.rot.pitch;
iV_MatrixRotateX(imdRot2.x);
if (psStats->weaponSubClass == WSC_ROCKET || psStats->weaponSubClass == WSC_MISSILE
@ -1215,9 +1215,9 @@ void renderAnimComponent( const COMPONENT_OBJECT *psObj )
iV_TRANSLATE(rx, 0, -rz);
/* parent object rotations */
imdRot2.y = DEG(spacetime.direction);
imdRot2.y = spacetime.rot.direction;
iV_MatrixRotateY(-imdRot2.y);
imdRot2.x = DEG(spacetime.pitch);
imdRot2.x = spacetime.rot.pitch;
iV_MatrixRotateX(imdRot2.x);
/* Set frame numbers - look into this later?? FIXME!!!!!!!! */
@ -1370,7 +1370,7 @@ static void drawWallDrag(STRUCTURE_STATS *psStats, int left, int right, int up,
if ((psStats->type == REF_WALL || psStats->type == REF_GATE) && left == right && up != down)
{
blueprint->direction = 90; // rotate so walls will look like walls
blueprint->rot.direction = DEG(90); // rotate so walls will look like walls
}
for(i = left; i < right + 1; i++)
@ -1797,7 +1797,7 @@ void renderFeature(FEATURE *psFeature)
/* Translate */
iV_TRANSLATE(rx,0,-rz);
rotation = DEG( (int)psFeature->direction );
rotation = psFeature->rot.direction;
iV_MatrixRotateY(-rotation);
@ -2078,7 +2078,7 @@ void renderStructure(STRUCTURE *psStructure)
/* OK - here is where we establish which IMD to draw for the building - luckily static objects,
* buildings in other words are NOT made up of components - much quicker! */
rotation = DEG((int)psStructure->direction);
rotation = psStructure->rot.direction;
iV_MatrixRotateY(-rotation);
if (!defensive
&& gameTime2-psStructure->timeLastHit < ELEC_DAMAGE_DURATION
@ -2212,11 +2212,13 @@ void renderStructure(STRUCTURE *psStructure)
// draw Weapon / ECM / Sensor for structure
for (i = 0; i < psStructure->numWeaps || i == 0; i++)
{
Rotation rot = structureGetInterpolatedWeaponRotation(psStructure, i, graphicsTime);
if (weaponImd[i] != NULL)
{
iV_MatrixBegin();
iV_TRANSLATE(strImd->connectors[i].x, strImd->connectors[i].z, strImd->connectors[i].y);
pie_MatRotY(DEG(-structureGetInterpolatedWeaponRotation(psStructure, i, graphicsTime)));
pie_MatRotY(-rot.direction);
if (mountImd[i] != NULL)
{
pie_TRANSLATE(0, 0, psStructure->asWeaps[i].recoilValue / 3);
@ -2227,7 +2229,7 @@ void renderStructure(STRUCTURE *psStructure)
iV_TRANSLATE(mountImd[i]->connectors->x, mountImd[i]->connectors->z, mountImd[i]->connectors->y);
}
}
iV_MatrixRotateX(DEG(structureGetInterpolatedWeaponPitch(psStructure, i, graphicsTime)));
iV_MatrixRotateX(rot.pitch);
pie_TRANSLATE(0, 0, psStructure->asWeaps[i].recoilValue);
pie_Draw3DShape(weaponImd[i], 0, colour, buildingBrightness, WZCOL_BLACK, pieFlag, pieFlagData);
@ -2251,7 +2253,7 @@ void renderStructure(STRUCTURE *psStructure)
iV_TRANSLATE(weaponImd[i]->connectors->x,weaponImd[i]->connectors->z-12,weaponImd[i]->connectors->y);
pRepImd = getImdFromIndex(MI_FLAME);
pie_MatRotY(DEG(structureGetInterpolatedWeaponRotation(psStructure, i, graphicsTime)));
pie_MatRotY(rot.direction);
iV_MatrixRotateY(-player.r.y);
iV_MatrixRotateX(-player.r.x);
@ -2259,7 +2261,7 @@ void renderStructure(STRUCTURE *psStructure)
iV_MatrixRotateX(player.r.x);
iV_MatrixRotateY(player.r.y);
pie_MatRotY(DEG(structureGetInterpolatedWeaponRotation(psStructure, i, graphicsTime)));
pie_MatRotY(rot.direction);
}
}
}
@ -2321,16 +2323,16 @@ void renderStructure(STRUCTURE *psStructure)
if (strImd->max.y > 80) // babatower
{
iV_TRANSLATE(0, 80, 0);
pie_MatRotY(DEG(-structureGetInterpolatedWeaponRotation(psStructure, i, graphicsTime)));
pie_MatRotY(-rot.direction);
iV_TRANSLATE(0, 0, -20);
}
else//baba bunker
{
iV_TRANSLATE(0, 10, 0);
pie_MatRotY(DEG(-structureGetInterpolatedWeaponRotation(psStructure, i, graphicsTime)));
pie_MatRotY(-rot.direction);
iV_TRANSLATE(0, 0, -40);
}
pie_MatRotX(DEG(structureGetInterpolatedWeaponPitch(psStructure, i, graphicsTime)));
pie_MatRotX(rot.pitch);
// draw the muzzle flash?
if (psStructure && psStructure->visible[selectedPlayer] > UBYTE_MAX / 2)
{
@ -2533,7 +2535,7 @@ static BOOL renderWallSection(STRUCTURE *psStructure)
/* Translate */
iV_TRANSLATE(rx, 0, -rz);
rotation = DEG( (int)psStructure->direction );
rotation = psStructure->rot.direction;
iV_MatrixRotateY(-rotation);
if(imd != NULL)
@ -2549,7 +2551,7 @@ static BOOL renderWallSection(STRUCTURE *psStructure)
imd = psStructure->sDisplay.imd;
temp = imd->points;
flattenImd(imd, structX, structY, psStructure->direction );
flattenImd(imd, structX, structY, UNDEG(psStructure->rot.direction));
/* Actually render it */
if ( (psStructure->status == SS_BEING_BUILT ) ||
@ -2629,7 +2631,7 @@ void renderShadow( DROID *psDroid, iIMDShape *psShadowIMD )
if(psDroid->droidType == DROID_TRANSPORTER)
{
iV_MatrixRotateY( DEG( -psDroid->direction ) );
iV_MatrixRotateY(-psDroid->rot.direction);
}
pVecTemp = psShadowIMD->points;
@ -2641,9 +2643,9 @@ void renderShadow( DROID *psDroid, iIMDShape *psShadowIMD )
}
else
{
pie_MatRotY( DEG(-psDroid->direction ) );
pie_MatRotX( DEG( psDroid->pitch ) );
pie_MatRotZ( DEG( psDroid->roll ) );
pie_MatRotY(-psDroid->rot.direction);
pie_MatRotX(psDroid->rot.pitch);
pie_MatRotZ(psDroid->rot.roll);
}
pie_Draw3DShape(psShadowIMD, 0, 0, WZCOL_WHITE, WZCOL_BLACK, pie_TRANSLUCENT, 128);

View File

@ -207,7 +207,7 @@ BOOL StartDriverMode(DROID *psOldDroid)
if(psDrivenDroid) {
driveDir = (int)psDrivenDroid->direction % 360;
driveDir = UNDEG(psDrivenDroid->rot.direction);
driveSpeed = 0;
driveBumpTime = gameTime;
@ -533,7 +533,7 @@ void driveUpdate(void)
if(psDrivenDroid->sMove.Status != MOVEDRIVE) {
psDrivenDroid->sMove.Status = MOVEDRIVE;
ASSERT( (psDrivenDroid->droidType != DROID_TRANSPORTER),"Tried to control a transporter" );
driveDir = (int)psDrivenDroid->direction % 360;
driveDir = UNDEG(psDrivenDroid->rot.direction);
}
DoFollowRangeCheck = true;
@ -595,8 +595,7 @@ SDWORD driveGetMoveDir(void)
void driveSetDroidMove(DROID *psDroid)
{
// psDroid->sMove.speed = (float)driveSpeed;
// psDroid->sMove.dir = driveDir;
psDroid->direction = driveDir;
psDroid->rot.direction = DEG(driveDir);
}

View File

@ -727,8 +727,7 @@ void droidUpdate(DROID *psDroid)
psDroid->time = gameTime;
for (i = 0; i < MAX(1, psDroid->numWeaps); ++i)
{
psDroid->asWeaps[i].prevRotation = psDroid->asWeaps[i].rotation;
psDroid->asWeaps[i].prevPitch = psDroid->asWeaps[i].pitch;
psDroid->asWeaps[i].prevRot = psDroid->asWeaps[i].rot;
}
// update the cluster of the droid
@ -2459,8 +2458,10 @@ DROID* buildDroid(DROID_TEMPLATE *pTemplate, UDWORD x, UDWORD y, UDWORD player,
psDroid->asWeaps[i].nStat = 0;
psDroid->asWeaps[i].ammo = 0;
psDroid->asWeaps[i].recoilValue = 0;
psDroid->asWeaps[i].rotation = 0;
psDroid->asWeaps[i].pitch = 0;
psDroid->asWeaps[i].rot.direction = 0;
psDroid->asWeaps[i].rot.roll = 0;
psDroid->asWeaps[i].rot.pitch = 0;
psDroid->asWeaps[i].prevRot = psDroid->asWeaps[i].rot;
}
psDroid->listSize = 0;
@ -2506,9 +2507,6 @@ DROID* buildDroid(DROID_TEMPLATE *pTemplate, UDWORD x, UDWORD y, UDWORD player,
initDroidMovement(psDroid);
psDroid->direction = 0; // Redundant? (Is set in droidSetBits, too.)
psDroid->pitch = 0; // Redundant? (Is set in droidSetBits, too.)
psDroid->roll = 0; // Redundant? (Is set in droidSetBits, too.)
psDroid->selected = false;
psDroid->lastEmission = 0;
psDroid->bTargetted = false;
@ -2619,7 +2617,7 @@ void initDroidMovement(DROID *psDroid)
psDroid->sMove.fy = psDroid->pos.y;
psDroid->sMove.fz = psDroid->pos.z;
psDroid->sMove.speed = 0.0f;
psDroid->sMove.moveDir = 0.0f;
psDroid->sMove.moveDir = 0;
}
// Set the asBits in a DROID structure given it's template.
@ -2628,9 +2626,9 @@ void droidSetBits(DROID_TEMPLATE *pTemplate,DROID *psDroid)
UDWORD inc;
psDroid->droidType = droidTemplateType(pTemplate);
psDroid->direction = 0;
psDroid->pitch = 0;
psDroid->roll = 0;
psDroid->rot.direction = 0;
psDroid->rot.pitch = 0;
psDroid->rot.roll = 0;
psDroid->numWeaps = pTemplate->numWeaps;
psDroid->body = calcTemplateBody(pTemplate, psDroid->player);
psDroid->originalBody = psDroid->body;
@ -2648,10 +2646,10 @@ void droidSetBits(DROID_TEMPLATE *pTemplate,DROID *psDroid)
psDroid->asWeaps[inc].nStat = pTemplate->asWeaps[inc];
psDroid->asWeaps[inc].recoilValue = 0;
psDroid->asWeaps[inc].ammo = (asWeaponStats + psDroid->asWeaps[inc].nStat)->numRounds;
psDroid->asWeaps[inc].rotation = 0;
psDroid->asWeaps[inc].pitch = 0;
psDroid->asWeaps[inc].prevRotation = 0;
psDroid->asWeaps[inc].prevPitch = 0;
psDroid->asWeaps[inc].rot.direction = 0;
psDroid->asWeaps[inc].rot.pitch = 0;
psDroid->asWeaps[inc].rot.roll = 0;
psDroid->asWeaps[inc].prevRot = psDroid->asWeaps[inc].rot;
}
}
else
@ -3016,14 +3014,14 @@ BOOL calcDroidMuzzleLocation(DROID *psDroid, Vector3f *muzzle, int weapon_slot)
pie_TRANSLATE(psDroid->pos.x, -psDroid->pos.z, psDroid->pos.y);
//matrix = the center of droid
pie_MatRotY( DEG( psDroid->direction ) );
pie_MatRotX( DEG( psDroid->pitch ) );
pie_MatRotZ( DEG( -psDroid->roll ) );
pie_MatRotY(psDroid->rot.direction);
pie_MatRotX(psDroid->rot.pitch);
pie_MatRotZ(-psDroid->rot.roll);
pie_TRANSLATE(psBodyImd->connectors[weapon_slot].x, -psBodyImd->connectors[weapon_slot].z,
-psBodyImd->connectors[weapon_slot].y);//note y and z flipped
//matrix = the weapon[slot] mount on the body
pie_MatRotY(DEG(psDroid->asWeaps[weapon_slot].rotation)); // +ve anticlockwise
pie_MatRotY(psDroid->asWeaps[weapon_slot].rot.direction); // +ve anticlockwise
// process turret mount
if (psMountImd && psMountImd->nconnectors)
@ -3032,7 +3030,7 @@ BOOL calcDroidMuzzleLocation(DROID *psDroid, Vector3f *muzzle, int weapon_slot)
}
//matrix = the turret connector for the gun
pie_MatRotX(DEG(psDroid->asWeaps[weapon_slot].pitch)); // +ve up
pie_MatRotX(psDroid->asWeaps[weapon_slot].rot.pitch); // +ve up
//process the gun
if (psWeaponImd && psWeaponImd->nconnectors)
@ -4286,7 +4284,7 @@ DROID * giftSingleDroid(DROID *psD, UDWORD to)
armourH[impact_side] = psD->armour[impact_side][WC_HEAT];
}
numKills = psD->experience;
direction = psD->direction;
direction = psD->rot.direction;
// only play the sound if unit being taken over is selectedPlayer's but not going to the selectedPlayer
if (psD->player == selectedPlayer && to != selectedPlayer)
{
@ -4308,7 +4306,7 @@ DROID * giftSingleDroid(DROID *psD, UDWORD to)
psNewDroid->armour[impact_side][WC_HEAT] = armourH[impact_side];
}
psNewDroid->experience = (float) numKills;
psNewDroid->direction = direction;
psNewDroid->rot.direction = direction;
if (!(psNewDroid->droidType == DROID_PERSON || cyborgDroid(psNewDroid) || psNewDroid->droidType == DROID_TRANSPORTER))
{
updateDroidOrientation(psNewDroid);
@ -4601,7 +4599,6 @@ void checkDroid(const DROID *droid, const char *const location, const char *func
ASSERT_HELPER(droid != NULL, location, function, "CHECK_DROID: NULL pointer");
ASSERT_HELPER(droid->type == OBJ_DROID, location, function, "CHECK_DROID: Not droid (type %d)", (int)droid->type);
ASSERT_HELPER(droid->direction <= 360.0f && droid->direction >= 0.0f, location, function, "CHECK_DROID: Bad droid direction %f", droid->direction);
ASSERT_HELPER(droid->numWeaps <= DROID_MAXWEAPS, location, function, "CHECK_DROID: Bad number of droid weapons %d", (int)droid->numWeaps);
ASSERT_HELPER(droid->listSize <= ORDER_LIST_MAX, location, function, "CHECK_DROID: Bad number of droid orders %d", (int)droid->listSize);
ASSERT_HELPER(droid->player < MAX_PLAYERS, location, function, "CHECK_DROID: Bad droid owner %d", (int)droid->player);
@ -4610,12 +4607,7 @@ void checkDroid(const DROID *droid, const char *const location, const char *func
for (i = 0; i < DROID_MAXWEAPS; ++i)
{
ASSERT_HELPER(droid->asWeaps[i].rotation <= 360, location, function, "CHECK_DROID: Bad turret rotation of turret %u", i);
ASSERT_HELPER(droid->asWeaps[i].lastFired <= gameTime, location, function, "CHECK_DROID: Bad last fired time for turret %u", i);
if (droid->psActionTarget[i])
{
ASSERT_HELPER(droid->psActionTarget[i]->direction >= 0.0f, location, function, "CHECK_DROID: Bad direction of turret %u's target", i);
}
}
}

View File

@ -457,15 +457,9 @@ static inline WEAPON_STATS *getWeaponStats(DROID *psDroid, int weapon_slot)
return asWeaponStats + psDroid->asWeaps[weapon_slot].nStat;
}
static inline float getInterpolatedWeaponRotation(DROID *psDroid, int weaponSlot, uint32_t time)
static inline Rotation getInterpolatedWeaponRotation(DROID *psDroid, int weaponSlot, uint32_t time)
{
return interpolateDirection(psDroid->asWeaps[weaponSlot].prevRotation, psDroid->asWeaps[weaponSlot].rotation, psDroid->prevSpacetime.time, psDroid->time, time);
}
static inline float getInterpolatedWeaponPitch(DROID *psDroid, int weaponSlot, uint32_t time)
{
// Aaargh, Direction[sic]. Angles can be 16-bit (65536 "degrees" in circle), or can be floats (360.0f degrees). Except here, where they are _unsigned_ integers from 0 to 360. All hail consistency!
return interpolateDirection(psDroid->asWeaps[weaponSlot].prevPitch, psDroid->asWeaps[weaponSlot].pitch, psDroid->prevSpacetime.time, psDroid->time, time);
return interpolateRot(psDroid->asWeaps[weaponSlot].prevRot, psDroid->asWeaps[weaponSlot].rot, psDroid->prevSpacetime.time, psDroid->time, time);
}
/** helper functions for future refcount patch **/

View File

@ -2458,8 +2458,8 @@ static void effectDroidUpdates(void)
{
/* Present direction is important */
Vector2i behind = {
50.0f * sinf(psDroid->direction),
50.0f * cosf(psDroid->direction)
50.0f * sinf(UNDEG(psDroid->rot.direction)),
50.0f * cosf(UNDEG(psDroid->rot.direction))
};
Vector3i pos = {
clip(psDroid->pos.x - behind.x, 0, mapWidth),

View File

@ -302,17 +302,13 @@ FEATURE * buildFeature(FEATURE_STATS *psStats, UDWORD x, UDWORD y,BOOL FromSave)
}
/* Dump down the building wrecks at random angles - still looks shit though */
if(psStats->subType == FEAT_BUILD_WRECK)
if(psStats->subType == FEAT_BUILD_WRECK || psStats->subType == FEAT_TREE)
{
psFeature->direction = gameRand(360);
}
else if(psStats->subType == FEAT_TREE)
{
psFeature->direction = gameRand(360);
psFeature->rot.direction = gameRand(DEG_360);
}
else
{
psFeature->direction = 0;
psFeature->rot.direction = 0;
}
//psFeature->damage = featureDamage;
psFeature->selected = false;

View File

@ -94,7 +94,7 @@ void formationShutDown(void)
/** Create a new formation
*/
BOOL formationNew(FORMATION **ppsFormation, FORMATION_TYPE type,
SDWORD x, SDWORD y, SDWORD dir)
SDWORD x, SDWORD y, uint16_t dir)
{
SDWORD i;
FORMATION *psNew = malloc(sizeof(FORMATION));
@ -106,13 +106,11 @@ BOOL formationNew(FORMATION **ppsFormation, FORMATION_TYPE type,
return false;
}
// debug(LOG_NEVER, "type %d, at (%d,%d), dir %d", type, x, y, dir);
// initialise it
psNew->refCount = 0;
psNew->size = (SWORD)F_DEFLENGTH;
psNew->rankDist = (SWORD)RANK_DIST;
psNew->dir = (SWORD)dir;
psNew->direction = dir;
psNew->x = x;
psNew->y = y;
psNew->free = 0;
@ -132,12 +130,12 @@ BOOL formationNew(FORMATION **ppsFormation, FORMATION_TYPE type,
// line to the left
psNew->asLines[0].xoffset = 0;
psNew->asLines[0].yoffset = 0;
psNew->asLines[0].dir = (SWORD)adjustDirection(dir, -110);
psNew->asLines[0].direction = dir - DEG(110);
psNew->asLines[0].member = -1;
// line to the right
psNew->asLines[1].xoffset = 0;
psNew->asLines[1].yoffset = 0;
psNew->asLines[1].dir = (SWORD)adjustDirection(dir, 110);
psNew->asLines[1].direction = dir - DEG(110);
psNew->asLines[1].member = -1;
break;
case FT_COLUMN:
@ -145,7 +143,7 @@ BOOL formationNew(FORMATION **ppsFormation, FORMATION_TYPE type,
// line to the left
psNew->asLines[0].xoffset = 0;
psNew->asLines[0].yoffset = 0;
psNew->asLines[0].dir = (SWORD)adjustDirection(dir, 180);
psNew->asLines[0].direction = dir - DEG(180);
psNew->asLines[0].member = -1;
break;
default:
@ -343,14 +341,15 @@ static void formationCalcPos(FORMATION *psFormation, SDWORD line, SDWORD dist,
const int rank = dist / psFormation->size;
// calculate the offset of the line based on the rank
int dir = adjustDirection(psFormation->dir, 180);
uint16_t dir16 = psFormation->direction - DEG(180);
float dir = UNDEG(dir16);
const int xoffset = (int)(trigSin(dir) * (float)(psFormation->rankDist * rank))
+ psFormation->asLines[line].xoffset;
const int yoffset = (int)(trigCos(dir) * (float)(psFormation->rankDist * rank))
+ psFormation->asLines[line].yoffset;
// calculate the position of the gap
dir = psFormation->asLines[line].dir;
dir = UNDEG(psFormation->asLines[line].direction);
dist -= psFormation->size * rank;
*pX = (int)(trigSin(dir) * (float)dist)
+ xoffset + psFormation->x;

View File

@ -45,7 +45,7 @@ extern void formationShutDown(void);
// Create a new formation
extern BOOL formationNew(FORMATION **ppsFormation, FORMATION_TYPE type,
SDWORD x, SDWORD y, SDWORD dir);
SDWORD x, SDWORD y, uint16_t dir);
// Try and find a formation near to a location
extern FORMATION* formationFind(int x, int y);

View File

@ -43,7 +43,7 @@ extern "C"
typedef struct _f_line
{
SWORD xoffset,yoffset; // position relative to center
SWORD dir; // orientation of line
uint16_t direction; // orientation of line
SBYTE member; // first member in the 'linked list' of members
} F_LINE;
@ -63,7 +63,7 @@ typedef struct _formation
SWORD size; // maximum length of the lines
SWORD rankDist; // seperation between the ranks
SWORD dir; // direction of the formation
uint16_t direction; // direction of the formation
SDWORD x,y; // position of the front of the formation
// the lines that make up a formation

View File

@ -5070,7 +5070,7 @@ BOOL loadSaveDroidInitV2(char *pFileData, UDWORD filesize,UDWORD quantity)
if (psDroid)
{
psDroid->id = pDroidInit->id;
psDroid->direction = pDroidInit->direction;
psDroid->rot.direction = DEG(pDroidInit->direction);
addDroid(psDroid, apsDroidLists);
}
else
@ -5246,7 +5246,7 @@ static DROID* buildDroidFromSaveDroidV11(SAVE_DROID_V11* psSaveDroid)
//are these going to ever change from the values set up with?
// psDroid->pos.z = psSaveDroid->pos.z; // use the correct map height value
psDroid->direction = psSaveDroid->direction;
psDroid->rot.direction = DEG(psSaveDroid->direction);
psDroid->body = psSaveDroid->body;
if (psDroid->body > psDroid->originalBody)
{
@ -5262,8 +5262,8 @@ static DROID* buildDroidFromSaveDroidV11(SAVE_DROID_V11* psSaveDroid)
//version 11
for (i=0; i < psDroid->numWeaps; i++)
{
psDroid->asWeaps[i].rotation = psSaveDroid->turretRotation;
psDroid->asWeaps[i].pitch = psSaveDroid->turretPitch;
psDroid->asWeaps[i].rot.direction = DEG(psSaveDroid->turretRotation);
psDroid->asWeaps[i].rot.pitch = DEG(psSaveDroid->turretPitch);
}
@ -5366,7 +5366,7 @@ static DROID* buildDroidFromSaveDroidV19(SAVE_DROID_V18* psSaveDroid, UDWORD ver
//are these going to ever change from the values set up with?
// psDroid->pos.z = psSaveDroid->pos.z; // use the correct map height value
psDroid->direction = psSaveDroid->direction;
psDroid->rot.direction = DEG(psSaveDroid->direction);
psDroid->body = psSaveDroid->body;
if (psDroid->body > psDroid->originalBody)
{
@ -5387,8 +5387,8 @@ static DROID* buildDroidFromSaveDroidV19(SAVE_DROID_V18* psSaveDroid, UDWORD ver
//Watermelon:make it back-compatible with older versions of save
for (i=0; i < psDroid->numWeaps; i++)
{
psDroid->asWeaps[i].rotation = psSaveDroid->turretRotation;
psDroid->asWeaps[i].pitch = psSaveDroid->turretPitch;
psDroid->asWeaps[i].rot.direction = DEG(psSaveDroid->turretRotation);
psDroid->asWeaps[i].rot.pitch = DEG(psSaveDroid->turretPitch);
}
}
if (version >= VERSION_12)//version 12
@ -5541,7 +5541,7 @@ static void SaveDroidMoveControl(SAVE_DROID * const psSaveDroid, DROID const * c
if (psDroid->sMove.psFormation != NULL)
{
psSaveDroid->sMove.isInFormation = true;
psSaveDroid->formationDir = psDroid->sMove.psFormation->dir;
psSaveDroid->formationDir = UNDEG(psDroid->sMove.psFormation->direction);
psSaveDroid->formationX = psDroid->sMove.psFormation->x;
psSaveDroid->formationY = psDroid->sMove.psFormation->y;
}
@ -5581,7 +5581,7 @@ static void LoadDroidMoveControl(DROID * const psDroid, SAVE_DROID const * const
psDroid->sMove.fx = PHYSFS_swapSLE32(psSaveDroid->sMove.fx);
psDroid->sMove.fy = PHYSFS_swapSLE32(psSaveDroid->sMove.fy);
psDroid->sMove.speed = PHYSFS_swapSLE32(psSaveDroid->sMove.speed);
psDroid->sMove.moveDir = PHYSFS_swapSLE32(psSaveDroid->sMove.moveDir);
psDroid->sMove.moveDir = DEG(PHYSFS_swapSLE32(psSaveDroid->sMove.moveDir));
psDroid->sMove.fz = PHYSFS_swapSLE32(psSaveDroid->sMove.fz);
// Hack to fix bad droids in savegames
@ -5597,7 +5597,7 @@ static void LoadDroidMoveControl(DROID * const psDroid, SAVE_DROID const * const
// Little endian SWORDs
psDroid->sMove.boundX = PHYSFS_swapSLE16(psSaveDroid->sMove.boundX);
psDroid->sMove.boundY = PHYSFS_swapSLE16(psSaveDroid->sMove.boundY);
psDroid->sMove.bumpDir = PHYSFS_swapSLE16(psSaveDroid->sMove.bumpDir);
psDroid->sMove.bumpDir = DEG(PHYSFS_swapSLE16(psSaveDroid->sMove.bumpDir));
psDroid->sMove.iVertSpeed = PHYSFS_swapSLE16(psSaveDroid->sMove.iVertSpeed);
// Little endian UDWORDs
@ -5749,7 +5749,7 @@ static DROID* buildDroidFromSaveDroid(SAVE_DROID* psSaveDroid, UDWORD version)
//are these going to ever change from the values set up with?
// psDroid->pos.z = psSaveDroid->pos.z; // use the correct map height value
psDroid->direction = psSaveDroid->direction;
psDroid->rot.direction = DEG(psSaveDroid->direction);
psDroid->body = psSaveDroid->body;
if (psDroid->body > psDroid->originalBody)
{
@ -5771,13 +5771,13 @@ static DROID* buildDroidFromSaveDroid(SAVE_DROID* psSaveDroid, UDWORD version)
{
if (version >= VERSION_24)
{
psDroid->asWeaps[i].rotation = psSaveDroid->turretRotation[i];
psDroid->asWeaps[i].pitch = psSaveDroid->turretPitch[i];
psDroid->asWeaps[i].rot.direction = DEG(psSaveDroid->turretRotation[i]);
psDroid->asWeaps[i].rot.pitch = DEG(psSaveDroid->turretPitch[i]);
}
else
{
psDroid->asWeaps[i].rotation = psSaveDroid->turretRotation[0];
psDroid->asWeaps[i].pitch = psSaveDroid->turretPitch[0];
psDroid->asWeaps[i].rot.direction = DEG(psSaveDroid->turretRotation[0]);
psDroid->asWeaps[i].rot.pitch = DEG(psSaveDroid->turretPitch[0]);
}
}
//version 12
@ -6473,8 +6473,8 @@ static BOOL buildSaveDroidFromDroid(SAVE_DROID* psSaveDroid, DROID* psCurr, DROI
//Watermelon:endian_udword for new save format
for(i = 0;i < psCurr->numWeaps;i++)
{
psSaveDroid->turretRotation[i] = psCurr->asWeaps[i].rotation;
psSaveDroid->turretPitch[i] = psCurr->asWeaps[i].pitch;
psSaveDroid->turretRotation[i] = UNDEG(psCurr->asWeaps[i].rot.direction);
psSaveDroid->turretPitch[i] = UNDEG(psCurr->asWeaps[i].rot.pitch);
}
//version 12
psSaveDroid->order = psCurr->order;
@ -6558,7 +6558,7 @@ static BOOL buildSaveDroidFromDroid(SAVE_DROID* psSaveDroid, DROID* psCurr, DROI
psSaveDroid->x = psCurr->pos.x;
psSaveDroid->y = psCurr->pos.y;
psSaveDroid->z = psCurr->pos.z;
psSaveDroid->direction = psCurr->direction;
psSaveDroid->direction = UNDEG(psCurr->rot.direction);
psSaveDroid->player = psCurr->player;
psSaveDroid->inFire = psCurr->inFire;
psSaveDroid->burnStart = psCurr->burnStart;
@ -6930,7 +6930,7 @@ BOOL loadSaveStructureV7(char *pFileData, UDWORD filesize, UDWORD numStructures)
//copy the values across
psStructure->id = psSaveStructure->id;
//are these going to ever change from the values set up with?
psStructure->direction = psSaveStructure->direction;
psStructure->rot.direction = DEG(psSaveStructure->direction);
}
psStructure->inFire = psSaveStructure->inFire;
@ -7207,7 +7207,7 @@ BOOL loadSaveStructureV19(char *pFileData, UDWORD filesize, UDWORD numStructures
psStructure->id = psSaveStructure->id;
//are these going to ever change from the values set up with?
// psStructure->pos.z = (UWORD)psSaveStructure->pos.z;
psStructure->direction = psSaveStructure->direction;
psStructure->rot.direction = DEG(psSaveStructure->direction);
}
psStructure->inFire = psSaveStructure->inFire;
@ -7630,7 +7630,7 @@ BOOL loadSaveStructureV(char *pFileData, UDWORD filesize, UDWORD numStructures,
psStructure->id = psSaveStructure->id;
//are these going to ever change from the values set up with?
// psStructure->pos.z = (UWORD)psSaveStructure->pos.z;
psStructure->direction = psSaveStructure->direction;
psStructure->rot.direction = DEG(psSaveStructure->direction);
}
psStructure->inFire = psSaveStructure->inFire;
@ -7952,7 +7952,7 @@ BOOL writeStructFile(char *pFileName)
psSaveStruct->y = psCurr->pos.y;
psSaveStruct->z = psCurr->pos.z;
psSaveStruct->direction = psCurr->direction;
psSaveStruct->direction = UNDEG(psCurr->rot.direction);
psSaveStruct->player = psCurr->player;
psSaveStruct->inFire = psCurr->inFire;
psSaveStruct->burnStart = psCurr->burnStart;
@ -8416,7 +8416,7 @@ BOOL loadSaveFeatureV14(char *pFileData, UDWORD filesize, UDWORD numFeatures, UD
}
//restore values
pFeature->id = psSaveFeature->id;
pFeature->direction = psSaveFeature->direction;
pFeature->rot.direction = DEG(psSaveFeature->direction);
pFeature->inFire = psSaveFeature->inFire;
pFeature->burnDamage = psSaveFeature->burnDamage;
if (version >= VERSION_14)
@ -8515,7 +8515,7 @@ BOOL loadSaveFeatureV(char *pFileData, UDWORD filesize, UDWORD numFeatures, UDWO
}
//restore values
pFeature->id = psSaveFeature->id;
pFeature->direction = psSaveFeature->direction;
pFeature->rot.direction = DEG(psSaveFeature->direction);
pFeature->inFire = psSaveFeature->inFire;
pFeature->burnDamage = psSaveFeature->burnDamage;
for (i=0; i < MAX_PLAYERS; i++)
@ -8574,15 +8574,11 @@ BOOL writeFeatureFile(char *pFileName)
psSaveFeature->id = psCurr->id;
// psSaveFeature->pos.x = psCurr->pos.x - psCurr->psStats->baseWidth * TILE_UNITS / 2;
// psSaveFeature->pos.y = psCurr->pos.y - psCurr->psStats->baseBreadth * TILE_UNITS / 2;
// psSaveFeature->pos.z = psCurr->pos.z;
psSaveFeature->x = psCurr->pos.x;
psSaveFeature->y = psCurr->pos.y;
psSaveFeature->z = psCurr->pos.z;
psSaveFeature->direction = psCurr->direction;
psSaveFeature->direction = UNDEG(psCurr->rot.direction);
psSaveFeature->inFire = psCurr->inFire;
psSaveFeature->burnDamage = psCurr->burnDamage;
for (i=0; i < MAX_PLAYERS; i++)

View File

@ -53,7 +53,7 @@ void initBulletTable( void )
}
/* Angle returned is reflected in line x=0 */
SDWORD calcDirection(UDWORD x0, UDWORD y0, UDWORD x1, UDWORD y1)
uint16_t calcDirection(UDWORD x0, UDWORD y0, UDWORD x1, UDWORD y1)
{
/* Watch out here - should really be y1-y0, but coordinate system is reversed in Y */
SDWORD xDif = (x1-x0), yDif = (y0-y1);
@ -64,10 +64,9 @@ SDWORD calcDirection(UDWORD x0, UDWORD y0, UDWORD x1, UDWORD y1)
if (angleInt<0)
angleInt+=360;
ASSERT( angleInt >= 0 && angleInt < 360,
"calcDirection: droid direction out of range" );
ASSERT(angleInt >= 0 && angleInt < 360, "Droid direction out of range");
return(angleInt);
return DEG(angleInt);
}

View File

@ -35,7 +35,7 @@ typedef struct _t_quad
} QUAD;
extern UDWORD adjustDirection( SDWORD present, SDWORD difference );
extern SDWORD calcDirection( UDWORD x0, UDWORD y0, UDWORD x1, UDWORD y1 );
extern uint16_t calcDirection( UDWORD x0, UDWORD y0, UDWORD x1, UDWORD y1 );
extern void initBulletTable( void );
extern int inQuad( const Vector2i *pt, const QUAD *quad );
extern DROID *getNearestDroid( UDWORD x, UDWORD y, BOOL bSelected );

View File

@ -322,7 +322,7 @@ void kf_CloneSelected( void )
psNewDroid->armour[impact_side][WC_HEAT] = psDroid->armour[impact_side][WC_HEAT];
}
psNewDroid->experience = psDroid->experience;
psNewDroid->direction = psDroid->direction;
psNewDroid->rot.direction = psDroid->rot.direction;
if (!(psNewDroid->droidType == DROID_PERSON || cyborgDroid(psNewDroid) || psNewDroid->droidType == DROID_TRANSPORTER))
{
updateDroidOrientation(psNewDroid);

View File

@ -1006,34 +1006,9 @@ failure:
// Object macro group
static void objectSaveTagged(BASE_OBJECT *psObj)
{
uint16_t v[MAX_PLAYERS], i;
// not written: sDisplay
tagWriteEnter(0x01, 1);
tagWrite(0x01, psObj->type);
tagWrite(0x02, psObj->id);
v[0] = psObj->pos.x;
v[1] = psObj->pos.y;
v[2] = psObj->pos.z;
tagWrite16v(0x03, 3, v);
tagWritef(0x04, psObj->direction);
tagWrites(0x05, psObj->pitch);
tagWrites(0x06, psObj->roll);
tagWrite(0x07, psObj->player);
tagWrite(0x08, psObj->group);
tagWrite(0x09, psObj->selected);
tagWrite(0x0a, psObj->cluster);
for (i = 0; i < MAX_PLAYERS; i++)
{
v[i] = psObj->visible[i];
}
tagWrite16v(0x0b, MAX_PLAYERS, v);
tagWrite(0x0c, psObj->died);
tagWrite(0x0d, psObj->lastEmission);
tagWriteBool(0x0e, psObj->inFire);
tagWrite(0x0f, psObj->burnStart);
tagWrite(0x10, psObj->burnDamage);
tagWriteLeave(0x01);
}
@ -1068,23 +1043,7 @@ static void objectStatTagged(BASE_OBJECT *psObj, int body, int resistance)
static void objectWeaponTagged(int num, WEAPON *asWeaps, BASE_OBJECT **psTargets)
{
int i;
tagWriteEnter(0x04, num);
for (i = 0; i < num; i++)
{
tagWrite(0x01, asWeaps[i].nStat);
tagWrite(0x02, asWeaps[i].rotation);
tagWrite(0x03, asWeaps[i].pitch);
tagWrite(0x05, asWeaps[i].ammo);
tagWrite(0x06, asWeaps[i].lastFired);
tagWrite(0x07, asWeaps[i].recoilValue);
if (psTargets[i] != NULL)
{
tagWrites(0x08, psTargets[i]->id); // else default -1
}
tagWriteNext();
}
tagWriteLeave(0x04);
}
@ -1154,12 +1113,6 @@ static void droidSaveTagged(DROID *psDroid)
tagWriteNext();
}
tagWriteLeave(0x13);
if (psDroid->sMove.psFormation != NULL)
{
tagWrites(0x14, psDroid->sMove.psFormation->dir);
tagWrites(0x15, psDroid->sMove.psFormation->x);
tagWrites(0x16, psDroid->sMove.psFormation->y);
} // else these are zero as by default
// vtol ammo
for (i = 0; i < VTOL_MAXWEAPS; i++)
{
@ -1187,23 +1140,6 @@ static void droidSaveTagged(DROID *psDroid)
v[0] = psDroid->sMove.bumpX;
v[1] = psDroid->sMove.bumpY;
tagWrite16v(0x1e, 2, v);
tagWrites(0x1f, psDroid->sMove.moveDir);
tagWrites(0x20, psDroid->sMove.bumpDir);
tagWrite(0x21, psDroid->sMove.bumpTime);
tagWrite(0x22, psDroid->sMove.lastBump);
tagWrite(0x23, psDroid->sMove.pauseTime);
tagWrite(0x24, psDroid->sMove.iVertSpeed);
tagWriteEnter(0x25, psDroid->sMove.numPoints);
for (i = 0; i < psDroid->sMove.numPoints; i++)
{
v[0] = psDroid->sMove.asPath[i].x;
v[1] = psDroid->sMove.asPath[i].y;
tagWrite16v(0x01, 2, v);
tagWriteNext();
}
tagWriteLeave(0x25);
tagWrite(0x26, psDroid->sMove.Status);
tagWrite(0x27, psDroid->sMove.Position);
tagWriteLeave(0x0a);
}

View File

@ -682,8 +682,7 @@ void missionFlyTransportersIn( SDWORD iPlayer, BOOL bTrackTransporter )
{
fR += (double) (2 * M_PI);
}
psTransporter->direction = RAD_TO_DEG(fR);
psTransporter->rot.direction = DEG(RAD_TO_DEG(fR));
// Camera track requested and it's the selected player.
if ( ( bTrackTransporter == true ) && (iPlayer == (SDWORD)selectedPlayer) )

View File

@ -218,43 +218,7 @@ static void moveUpdatePersonModel(DROID *psDroid, SDWORD speed, SDWORD direction
// Calculate the boundary vector
static void moveCalcBoundary(DROID *psDroid);
/* Turn a vector into an angle - returns a float (!) */
static float vectorToAngle(float vx, float vy);
/* Return the difference in directions */
static UDWORD moveDirDiff(SDWORD start, SDWORD end)
{
SDWORD retval, diff;
diff = end - start;
if (diff > 0)
{
if (diff < 180)
{
retval = diff;
}
else
{
retval = 360 - diff;
}
}
else
{
if (diff > -180)
{
retval = - diff;
}
else
{
retval = 360 + diff;
}
}
ASSERT( retval >=0 && retval <=180,
"moveDirDiff: result out of range" );
return retval;
}
static uint16_t vectorToAngle(float vx, float vy);
/** Initialise the movement system
*/
@ -407,7 +371,7 @@ static BOOL moveDroidToBase(DROID *psDroid, UDWORD x, UDWORD y, BOOL bFormation)
// no formation so create a new one
if (formationNew(&psDroid->sMove.psFormation, FT_LINE, (SDWORD)x,(SDWORD)y,
(SDWORD)calcDirection(fmx1,fmy1, fmx2,fmy2)))
calcDirection(fmx1,fmy1, fmx2,fmy2)))
{
formationJoin(psDroid->sMove.psFormation, psDroid);
}
@ -476,9 +440,9 @@ void moveDroidToDirect(DROID* psDroid, UDWORD x, UDWORD y)
*/
void moveTurnDroid(DROID *psDroid, UDWORD x, UDWORD y)
{
SDWORD moveDir = (SDWORD)calcDirection(psDroid->pos.x, psDroid->pos.y, x, y);
uint16_t moveDir = calcDirection(psDroid->pos.x, psDroid->pos.y, x, y);
if ( (SDWORD)(psDroid->direction) != moveDir )
if (psDroid->rot.direction != moveDir)
{
psDroid->sMove.targetX = (SDWORD)x;
psDroid->sMove.targetY = (SDWORD)y;
@ -489,7 +453,7 @@ void moveTurnDroid(DROID *psDroid, UDWORD x, UDWORD y)
// Tell a droid to move out the way for a shuffle
static void moveShuffleDroid(DROID *psDroid, UDWORD shuffleStart, SDWORD sx, SDWORD sy)
{
float shuffleDir, droidDir;
uint16_t shuffleDir, droidDir;
DROID *psCurr;
SDWORD xdiff,ydiff, mx,my, shuffleMag, diff;
BOOL frontClear = true, leftClear = true, rightClear = true;
@ -546,7 +510,7 @@ static void moveShuffleDroid(DROID *psDroid, UDWORD shuffleStart, SDWORD sx, SDW
if (xdiff*xdiff + ydiff*ydiff < SHUFFLE_DIST*SHUFFLE_DIST)
{
droidDir = vectorToAngle(xdiff, ydiff);
diff = (SDWORD)moveDirDiff(shuffleDir, droidDir);
diff = UNDEG(shuffleDir - droidDir + UINT16_MAX / 2) - 180;
if ((diff > -135) && (diff < -45))
{
leftClear = false;
@ -681,8 +645,8 @@ void updateDroidOrientation(DROID *psDroid)
psDroid->pos.z = MAX(psDroid->pos.z, (hy0 + hy1)/2);
// Vector of length 65536 pointing in direction droid is facing.
vX = iSin(DEG(psDroid->direction));
vY = iCos(DEG(psDroid->direction));
vX = iSin(psDroid->rot.direction);
vY = iCos(psDroid->rot.direction);
// Calculate pitch of ground.
dzdx = hx1 - hx0; // 2*d*∂z(x, y)/∂x of ground
@ -690,32 +654,27 @@ void updateDroidOrientation(DROID *psDroid)
dzdv = dzdx*vX + dzdy*vY; // 2*d*∂z(x, y)/∂v << 16 of ground, where v is the direction the droid is facing.
newPitch = iAtan2(dzdv, (2*d) << 16); // pitch = atan(∂z(x, y)/∂v)/2π << 16
deltaPitch = (int16_t)(newPitch - DEG(psDroid->pitch)); // (int16_t) cast: wrapping behaviour intended.
deltaPitch = (int16_t)(newPitch - psDroid->rot.pitch); // (int16_t) cast: wrapping behaviour intended.
//limit the rate the front comes down to simulate momentum
// Limit the rate the front comes down to simulate momentum
pitchLimit = gameTimeAdjustedIncrement(DEG(PITCH_LIMIT));
deltaPitch = MAX(deltaPitch, -pitchLimit);
// Update pitch.
#define UNDEG(a) (a * 360/65536) // ************** DELETE THIS LINE WHEN CHANGING UNITS **************
psDroid->pitch += UNDEG(deltaPitch);
psDroid->rot.pitch += deltaPitch;
// Calculate and update roll of ground (not taking pitch into account, but good enough).
dzdw = dzdx*vY - dzdy*vX; // 2*d*∂z(x, y)/∂w << 16 of ground, where w is at right angles to the direction the droid is facing.
psDroid->roll = UNDEG(iAtan2(dzdw, (2*d) << 16)); // pitch = atan(∂z(x, y)/∂w)/2π << 16
dzdw = dzdx * vY - dzdy * vX; // 2*d*∂z(x, y)/∂w << 16 of ground, where w is at right angles to the direction the droid is facing.
psDroid->rot.roll = iAtan2(dzdw, (2*d) << 16); // pitch = atan(∂z(x, y)/∂w)/2π << 16
}
/** Turn a vector into an angle
* @return the vector expressed as an angle
*/
static float vectorToAngle(float vx, float vy)
static uint16_t vectorToAngle(float vx, float vy)
{
// Angle in degrees (0->360):
float angle = 360.0f * atan2f(-vy,vx) / (M_PI * 2.0f);
angle += 360.0f / 4.0f;
return wrapf(angle, 360.0f);
return (int)DEG((360.0 * atan2(-vy, vx) / (M_PI * 2.0)) + 360.0 / 4.0);
// return iAtan2(vx, vy);
}
@ -940,6 +899,7 @@ static BOOL moveBlocked(DROID *psDroid)
{
SDWORD xdiff,ydiff, diffSq;
UDWORD blockTime;
uint16_t direction;
if (psDroid->sMove.bumpTime == 0 || psDroid->sMove.bumpTime > gameTime)
{
@ -948,7 +908,9 @@ static BOOL moveBlocked(DROID *psDroid)
}
// See if the block can be cancelled
if (moveDirDiff(psDroid->direction, psDroid->sMove.bumpDir) > BLOCK_DIR)
direction = psDroid->rot.direction;
direction -= psDroid->sMove.bumpDir; // do controlled underflow
if (direction > DEG(BLOCK_DIR))
{
// Move on, clear the bump
psDroid->sMove.bumpTime = 0;
@ -1122,7 +1084,7 @@ static void moveCalcBlockingSlide(DROID *psDroid, float *pmx, float *pmy, SDWORD
psDroid->sMove.pauseTime = 0;
psDroid->sMove.bumpX = psDroid->pos.x;
psDroid->sMove.bumpY = psDroid->pos.y;
psDroid->sMove.bumpDir = (SWORD)psDroid->direction;
psDroid->sMove.bumpDir = psDroid->rot.direction;
}
if (tx != ntx && ty != nty)
@ -1306,7 +1268,7 @@ static void moveCalcBlockingSlide(DROID *psDroid, float *pmx, float *pmy, SDWORD
}
}
slideDir = vectorToAngle(*pmx,*pmy);
slideDir = UNDEG(vectorToAngle(*pmx,*pmy));
if (ntx != tx)
{
// hit a horizontal block
@ -1425,7 +1387,7 @@ static void moveCalcDroidSlide(DROID *psDroid, float *pmx, float *pmy)
psDroid->sMove.pauseTime = 0;
psDroid->sMove.bumpX = psDroid->pos.x;
psDroid->sMove.bumpY = psDroid->pos.y;
psDroid->sMove.bumpDir = (SWORD)psDroid->direction;
psDroid->sMove.bumpDir = psDroid->rot.direction;
}
else
{
@ -1809,9 +1771,10 @@ static BOOL moveFormationSpeedLimitingOn( void )
*/
SDWORD moveCalcDroidSpeed(DROID *psDroid)
{
const uint16_t maxPitch = DEG(MAX_SPEED_PITCH);
UDWORD mapX,mapY, damLevel;
SDWORD speed, pitch;
WEAPON_STATS *psWStats;
int speed, pitch;
WEAPON_STATS *psWStats;
CHECK_DROID(psDroid);
@ -1821,17 +1784,9 @@ SDWORD moveCalcDroidSpeed(DROID *psDroid)
psDroid->asBits[COMP_PROPULSION].nStat,
getDroidEffectiveLevel(psDroid));
pitch = psDroid->pitch;
if (pitch > MAX_SPEED_PITCH)
{
pitch = MAX_SPEED_PITCH;
}
else if (pitch < - MAX_SPEED_PITCH)
{
pitch = -MAX_SPEED_PITCH;
}
// now offset the speed for the slope of the droid
speed = (MAX_SPEED_PITCH - pitch) * speed / MAX_SPEED_PITCH;
pitch = (int16_t)psDroid->rot.pitch; // Wrapping when casting intended
speed = (maxPitch - pitch) * speed / maxPitch;
if (speed <= 10)
{
// Very nasty hack to deal with buggy maps, where some cliffs are
@ -1908,7 +1863,7 @@ static void moveUpdateDroidDirection( DROID *psDroid, SDWORD *pSpeed, SDWORD dir
float temp;
*pfSpeed = *pSpeed;
*pDroidDir = psDroid->direction;
*pDroidDir = UNDEG(psDroid->rot.direction);
// don't move if in MOVEPAUSE state
if (psDroid->sMove.Status == MOVEPAUSE)
@ -1944,7 +1899,7 @@ static float moveCalcPerpSpeed( DROID *psDroid, float iDroidDir, SDWORD iSkidDec
float adiff;
float perpSpeed;
adiff = fabsf(iDroidDir - psDroid->sMove.moveDir);
adiff = fabsf(iDroidDir - UNDEG(psDroid->sMove.moveDir));
perpSpeed = psDroid->sMove.speed * trigSin(adiff);
// decelerate the perpendicular speed
@ -1965,13 +1920,13 @@ static void moveCombineNormalAndPerpSpeeds( DROID *psDroid, float fNormalSpeed,
float finalSpeed;
/* set current direction */
psDroid->direction = iDroidDir;
psDroid->rot.direction = DEG(iDroidDir);
/* set normal speed and direction if perpendicular speed is zero */
if (fPerpSpeed == 0)
{
psDroid->sMove.speed = fNormalSpeed;
psDroid->sMove.moveDir = iDroidDir;
psDroid->sMove.moveDir = DEG(iDroidDir);
return;
}
@ -1981,10 +1936,10 @@ static void moveCombineNormalAndPerpSpeeds( DROID *psDroid, float fNormalSpeed,
finalDir = trigInvCos(fNormalSpeed / finalSpeed);
// choose the finalDir on the same side as the old movement direction
adiff = fabsf(iDroidDir - psDroid->sMove.moveDir);
adiff = fabsf(iDroidDir - UNDEG(psDroid->sMove.moveDir));
if (adiff < TRIG_DEGREES/2)
{
if (iDroidDir > psDroid->sMove.moveDir)
if (iDroidDir > UNDEG(psDroid->sMove.moveDir))
{
finalDir = iDroidDir - finalDir;
}
@ -1995,7 +1950,7 @@ static void moveCombineNormalAndPerpSpeeds( DROID *psDroid, float fNormalSpeed,
}
else
{
if (iDroidDir > psDroid->sMove.moveDir)
if (iDroidDir > UNDEG(psDroid->sMove.moveDir))
{
finalDir = iDroidDir + finalDir;
if (finalDir >= TRIG_DEGREES)
@ -2013,7 +1968,7 @@ static void moveCombineNormalAndPerpSpeeds( DROID *psDroid, float fNormalSpeed,
}
}
psDroid->sMove.moveDir = finalDir;
psDroid->sMove.moveDir = DEG(finalDir);
psDroid->sMove.speed = finalSpeed;
}
@ -2025,7 +1980,7 @@ static float moveCalcNormalSpeed( DROID *psDroid, float fSpeed, float iDroidDir,
float adiff;
float normalSpeed;
adiff = fabsf(iDroidDir - psDroid->sMove.moveDir);
adiff = fabsf(iDroidDir - UNDEG(psDroid->sMove.moveDir));
normalSpeed = psDroid->sMove.speed * trigCos(adiff);
if (normalSpeed < fSpeed)
@ -2057,8 +2012,8 @@ static void moveGetDroidPosDiffs( DROID *psDroid, float *pDX, float *pDY )
move = (float)psDroid->sMove.speed * (float)baseSpeed;
*pDX = move * trigSin(psDroid->sMove.moveDir);
*pDY = move * trigCos(psDroid->sMove.moveDir);
*pDX = move * trigSin(UNDEG(psDroid->sMove.moveDir));
*pDY = move * trigCos(UNDEG(psDroid->sMove.moveDir));
}
// see if the droid is close to the final way point
@ -2212,7 +2167,7 @@ static void moveUpdateGroundModel(DROID *psDroid, SDWORD speed, SDWORD direction
{
moveUpdateDroidDirection( psDroid, &speed, slideDir, TRACKED_SPIN_ANGLE,
psDroid->baseSpeed, psDroid->baseSpeed/3, &iDroidDir, &fSpeed );
psDroid->direction = iDroidDir;
psDroid->rot.direction = DEG(iDroidDir);
}
moveUpdateDroidPos( psDroid, bx, by );
@ -2428,8 +2383,8 @@ static void moveUpdateVtolModel(DROID *psDroid, SDWORD speed, SDWORD direction)
moveUpdateDroidPos( psDroid, dx, dy );
/* update vtol orientation */
targetRoll = MIN(MAX((psDroid->sMove.moveDir - psDroid->direction)*4, -60), 60);
currentRoll = psDroid->roll;
targetRoll = MIN(MAX((UNDEG(psDroid->sMove.moveDir) - UNDEG(psDroid->rot.direction)) * 4, -60), 60);
currentRoll = UNDEG(psDroid->rot.roll);
if (currentRoll > 180)
{
currentRoll -= 360;
@ -2439,7 +2394,7 @@ static void moveUpdateVtolModel(DROID *psDroid, SDWORD speed, SDWORD direction)
{
newRoll += 360;
}
psDroid->roll = newRoll;
psDroid->rot.roll = DEG(newRoll);
iMapZ = map_Height(psDroid->pos.x, psDroid->pos.y);
@ -2660,8 +2615,8 @@ moveUpdateCyborgModel( DROID *psDroid, SDWORD moveSpeed, SDWORD moveDir, UBYTE o
}
}
psDroid->pitch = 0;
psDroid->roll = 0;
psDroid->rot.pitch = 0;
psDroid->rot.roll = 0;
}
static void moveDescending( DROID *psDroid )
@ -2908,12 +2863,10 @@ static void checkLocalFeatures(DROID *psDroid)
/* Frame update for the movement of a tracked droid */
void moveUpdateDroid(DROID *psDroid)
{
float tangle; // thats DROID angle and TARGET angle - not some bizzare pun :-)
// doesn't matter - they're still shit names...! :-)
UDWORD oldx, oldy;
UBYTE oldStatus = psDroid->sMove.Status;
SDWORD moveSpeed;
float moveDir;
uint16_t moveDir;
PROPULSION_STATS *psPropStats;
Vector3i pos;
BOOL bStarted = false, bStopped;
@ -2942,7 +2895,7 @@ void moveUpdateDroid(DROID *psDroid)
bStopped = moveDroidStopped( psDroid, 0 );
moveSpeed = 0;
moveDir = psDroid->direction;
moveDir = psDroid->rot.direction;
switch (psDroid->sMove.Status)
{
@ -2972,11 +2925,9 @@ void moveUpdateDroid(DROID *psDroid)
Vector2f target = moveGetDirection(psDroid);
// Turn the droid if necessary
tangle = vectorToAngle(target.x, target.y);
moveDir = vectorToAngle(target.x, target.y);
moveSpeed = moveCalcDroidSpeed(psDroid);
moveDir = tangle;
ASSERT(moveDir >= 0 && moveDir <= 360, "Illegal movement direction");
}
break;
case MOVEWAITROUTE:
@ -2999,7 +2950,7 @@ void moveUpdateDroid(DROID *psDroid)
}
// Calculate the direction vector
// psDroid->direction = calcDirection(psDroid->pos.x,psDroid->pos.y, tarX,tarY);
// psDroid->rot.direction = calcDirection(psDroid->pos.x,psDroid->pos.y, tarX,tarY);
psDroid->sMove.fx = psDroid->pos.x;
psDroid->sMove.fy = psDroid->pos.y;
psDroid->sMove.fz = psDroid->pos.z;
@ -3008,7 +2959,7 @@ void moveUpdateDroid(DROID *psDroid)
if (isVtolDroid(psDroid))
{
psDroid->pitch = 0;
psDroid->rot.pitch = 0;
}
psDroid->sMove.Status = MOVEPOINTTOPOINT;
@ -3062,13 +3013,10 @@ void moveUpdateDroid(DROID *psDroid)
target = moveGetDirection(psDroid);
// Turn the droid if necessary
tangle = vectorToAngle(target.x, target.y);
moveDir = vectorToAngle(target.x, target.y);
moveSpeed = moveCalcDroidSpeed(psDroid);
moveDir = tangle;
ASSERT(moveDir >= 0 && moveDir <= 360, "Illegal movement direction");
if ((psDroid->sMove.bumpTime != 0) &&
(psDroid->sMove.pauseTime + psDroid->sMove.bumpTime + BLOCK_PAUSETIME < gameTime))
{
@ -3094,13 +3042,12 @@ void moveUpdateDroid(DROID *psDroid)
break;
case MOVETURN:
// Turn the droid to it's final facing
if (psDroid->sMove.psFormation &&
psDroid->sMove.psFormation->refCount > 1 &&
(SDWORD)psDroid->direction != (SDWORD)psDroid->sMove.psFormation->dir)
if (psDroid->sMove.psFormation
&& psDroid->sMove.psFormation->refCount > 1
&& psDroid->rot.direction != psDroid->sMove.psFormation->direction)
{
moveSpeed = 0;
moveDir = psDroid->sMove.psFormation->dir;
ASSERT(moveDir >= 0 && moveDir <= 360, "Illegal movement direction");
moveDir = psDroid->sMove.psFormation->direction;
}
else
{
@ -3116,8 +3063,8 @@ void moveUpdateDroid(DROID *psDroid)
break;
case MOVETURNTOTARGET:
moveSpeed = 0;
moveDir = calcDirection( psDroid->pos.x, psDroid->pos.y, psDroid->sMove.targetX, psDroid->sMove.targetY );
if ((int)psDroid->direction == (int)moveDir)
moveDir = calcDirection(psDroid->pos.x, psDroid->pos.y, psDroid->sMove.targetX, psDroid->sMove.targetY);
if (psDroid->rot.direction == moveDir)
{
if ( psPropStats->propulsionType == PROPULSION_TYPE_LIFT )
{
@ -3128,7 +3075,6 @@ void moveUpdateDroid(DROID *psDroid)
psDroid->sMove.Status = MOVEINACTIVE;
}
}
ASSERT(moveDir >= 0 && moveDir <= 360, "Illegal movement direction");
break;
case MOVEHOVER:
moveDescending(psDroid);
@ -3137,8 +3083,7 @@ void moveUpdateDroid(DROID *psDroid)
case MOVEDRIVE:
driveSetDroidMove(psDroid);
moveSpeed = driveGetMoveSpeed(); //psDroid->sMove.speed;
moveDir = driveGetMoveDir(); //psDroid->sMove.dir;
ASSERT(moveDir >= 0 && moveDir <= 360, "Illegal movement direction");
moveDir = DEG(driveGetMoveDir()); //psDroid->sMove.dir;
break;
default:
@ -3146,27 +3091,25 @@ void moveUpdateDroid(DROID *psDroid)
break;
}
ASSERT(moveDir >= 0 && moveDir <= 360, "Illegal movement direction");
// Update the movement model for the droid
oldx = psDroid->pos.x;
oldy = psDroid->pos.y;
if ( psDroid->droidType == DROID_PERSON )
{
moveUpdatePersonModel(psDroid, moveSpeed, moveDir);
moveUpdatePersonModel(psDroid, moveSpeed, UNDEG(moveDir));
}
else if (cyborgDroid(psDroid))
{
moveUpdateCyborgModel(psDroid, moveSpeed, moveDir, oldStatus);
moveUpdateCyborgModel(psDroid, moveSpeed, UNDEG(moveDir), oldStatus);
}
else if ( psPropStats->propulsionType == PROPULSION_TYPE_LIFT )
{
moveUpdateVtolModel(psDroid, moveSpeed, moveDir);
moveUpdateVtolModel(psDroid, moveSpeed, UNDEG(moveDir));
}
else
{
moveUpdateGroundModel(psDroid, moveSpeed, moveDir);
moveUpdateGroundModel(psDroid, moveSpeed, UNDEG(moveDir));
}
if (map_coord(oldx) != map_coord(psDroid->pos.x)

View File

@ -62,8 +62,8 @@ typedef struct _move_control
float speed; // Speed of motion
SWORD boundX,boundY; // Vector for the end of path boundary
float moveDir; // direction of motion (not the direction the droid is facing)
SWORD bumpDir; // direction at last bump
uint16_t moveDir; // direction of motion (not the direction the droid is facing)
uint16_t bumpDir; // direction at last bump
UDWORD bumpTime; // time of first bump with something
UWORD lastBump; // time of last bump with a droid - relative to bumpTime
UWORD pauseTime; // when MOVEPAUSE started - relative to bumpTime

View File

@ -201,7 +201,7 @@ extern BOOL sendCheck (void); //send/recv check info
extern BOOL sendScoreCheck (void); //score check only(frontend)
extern BOOL sendPing (void); // allow game to request pings.
extern BOOL ForceDroidSync(const DROID* droidToSend);
extern BOOL ForceDroidSync(DROID* droidToSend);
// multijoin
extern BOOL sendReseachStatus (STRUCTURE *psBuilding ,UDWORD index, UBYTE player, BOOL bStart);

View File

@ -56,7 +56,7 @@
// function definitions
static BOOL sendStructureCheck (void); //Structure
static void packageCheck (const DROID* pD);
static void packageCheck(DROID* pD);
static BOOL sendDroidCheck (void); //droids
static void highLevelDroidUpdate(DROID *psDroid,
@ -69,12 +69,12 @@ static void highLevelDroidUpdate(DROID *psDroid,
static void onscreenUpdate (DROID *pDroid,UDWORD dam, // the droid and its damage
UWORD dir, // direction it should facing
Rotation rot, // direction it should facing
DROID_ORDER order); // what it should be doing
static void offscreenUpdate (DROID *pDroid,UDWORD dam,
float fx,float fy,
UWORD dir,
Rotation rot,
DROID_ORDER order);
static BOOL sendPowerCheck(void);
@ -250,7 +250,7 @@ static DROID* pickADroid(void)
*
* Call this when you need to update the given droid right now.
*/
BOOL ForceDroidSync(const DROID* droidToSend)
BOOL ForceDroidSync(DROID* droidToSend)
{
uint8_t count = 1; // *always* one
@ -322,7 +322,7 @@ static BOOL sendDroidCheck(void)
// ////////////////////////////////////////////////////////////////////////////
// Send a Single Droid Check message
static void packageCheck(const DROID* pD)
static void packageCheck(DROID* pD)
{
// Copy these variables so that we don't have to violate pD's constness
uint8_t player = pD->player;
@ -330,7 +330,6 @@ static void packageCheck(const DROID* pD)
int32_t order = pD->order;
uint32_t secondaryOrder = pD->secondaryOrder;
uint32_t body = pD->body;
float direction = pD->direction;
float experience = pD->experience;
float sMoveX = pD->sMove.fx;
float sMoveY = pD->sMove.fy;
@ -351,7 +350,7 @@ static void packageCheck(const DROID* pD)
NETuint32_t(&body);
// Direction it is going in
NETfloat(&direction);
NETRotation(&pD->rot);
NETfloat(&sMoveX);
NETfloat(&sMoveY);
@ -396,9 +395,10 @@ BOOL recvDroidCheck()
DROID_ORDER order = 0;
BOOL onscreen;
uint8_t player;
float direction, experience;
float experience;
uint16_t tx, ty;
uint32_t ref, body, target = 0, secondaryOrder;
Rotation rot;
// Fetch the player
NETuint8_t(&player);
@ -416,7 +416,7 @@ BOOL recvDroidCheck()
NETuint32_t(&body);
// Direction
NETfloat(&direction);
NETRotation(&rot);
// Fractional move
NETfloat(&fx);
@ -473,11 +473,11 @@ BOOL recvDroidCheck()
// Update the droid
if (onscreen || isVtolDroid(pD))
{
onscreenUpdate(pD, body, direction, order);
onscreenUpdate(pD, body, rot, order);
}
else
{
offscreenUpdate(pD, body, fx, fy, direction, order);
offscreenUpdate(pD, body, fx, fy, rot, order);
}
// debug(LOG_SYNC, "difference in position for droid %d; was (%g, %g); did %s update", (int)pD->id,
@ -541,7 +541,7 @@ static void highLevelDroidUpdate(DROID *psDroid, float fx, float fy,
// droid on screen needs modifying
static void onscreenUpdate(DROID *psDroid,
UDWORD dam,
UWORD dir,
Rotation rot,
DROID_ORDER order)
{
BASE_OBJECT *psClickedOn;
@ -563,7 +563,7 @@ static void onscreenUpdate(DROID *psDroid,
// if(psDroid->order == DORDER_NONE || (psDroid->order == DORDER_GUARD && psDroid->action == DACTION_NONE) )
// {
// psDroid->direction = dir %360; //update rotation
// psDroid->rot.direction = rot.direction; //update rotation
// }
return;
@ -575,7 +575,7 @@ static void offscreenUpdate(DROID *psDroid,
UDWORD dam,
float fx,
float fy,
UWORD dir,
Rotation rot,
DROID_ORDER order)
{
PROPULSION_STATS *psPropStats;
@ -590,7 +590,7 @@ static void offscreenUpdate(DROID *psDroid,
psDroid->pos.y = fy; // update y
psDroid->sMove.fx = fx;
psDroid->sMove.fy = fy;
psDroid->direction = dir % 360; // update rotation
psDroid->rot.direction = rot.direction; // update rotation
psDroid->body = dam; // update damage
// stage one, update the droid's position & info, LOW LEVEL STUFF.
@ -715,7 +715,7 @@ static BOOL sendStructureCheck(void)
NETuint32_t(&pS->body);
NETuint32_t(&pS->pStructureType->ref);
NETPosition(&pS->pos);
NETfloat(&pS->direction);
NETRotation(&pS->rot);
switch (pS->pStructureType->type)
{
@ -749,7 +749,7 @@ BOOL recvStructureCheck()
STRUCTURE_STATS *psStats;
BOOL hasCapacity = true;
int i, j;
float direction;
Rotation rot;
uint8_t player, ourCapacity;
uint32_t body;
uint16_t x, y, z;
@ -763,7 +763,7 @@ BOOL recvStructureCheck()
NETuint16_t(&x);
NETuint16_t(&y);
NETuint16_t(&z);
NETfloat(&direction);
NETRotation(&rot);
if (player >= MAX_PLAYERS)
{
@ -777,7 +777,7 @@ BOOL recvStructureCheck()
if (pS)
{
pS->body = body;
pS->direction = direction;
pS->rot = rot;
}
// Structure was not found - build it
else
@ -799,7 +799,7 @@ BOOL recvStructureCheck()
&& pS->pStructureType->type == type
&& pS->player == player)
{
pS->direction = direction;
pS->rot = rot;
pS->id = ref;
if (pS->status != SS_BUILT)
@ -855,7 +855,7 @@ BOOL recvStructureCheck()
// Check its finished
if (pS->status != SS_BUILT)
{
pS->direction = direction;
pS->rot = rot;
pS->id = ref;
pS->status = SS_BUILT;
buildingComplete(pS);

View File

@ -50,7 +50,7 @@ static void printBaseObjInfo(const BASE_OBJECT* psObj)
break;
}
CONPRINTF( ConsoleString, (ConsoleString, "%s id %d at (%d,%d,%d) dpr (%f,%d,%d)\n", pType, psObj->id, psObj->pos.x, psObj->pos.y, psObj->pos.z, psObj->direction, psObj->pitch, psObj->roll) );
CONPRINTF( ConsoleString, (ConsoleString, "%s id %d at (%d,%d,%d) dpr (%hu,%hu,%hu)\n", pType, psObj->id, psObj->pos.x, psObj->pos.y, psObj->pos.z, psObj->rot.direction, psObj->rot.pitch, psObj->rot.roll));
}
/** print out information about a general component

View File

@ -427,14 +427,14 @@ BOOL proj_SendProjectile(WEAPON *psWeap, BASE_OBJECT *psAttacker, int player, Ve
dz = tarHeight - muzzle.z;
/* roll never set */
psProj->roll = 0;
psProj->rot.roll = 0;
fR = atan2(dx, dy);
if ( fR < 0.0 )
{
fR += 2.0 * M_PI;
}
psProj->direction = RAD_TO_DEG(fR);
psProj->rot.direction = DEG(RAD_TO_DEG(fR));
/* get target distance */
@ -450,7 +450,7 @@ BOOL proj_SendProjectile(WEAPON *psWeap, BASE_OBJECT *psAttacker, int player, Ve
{
fR += 2.0 * M_PI;
}
psProj->pitch = (SWORD)( RAD_TO_DEG(fR) );
psProj->rot.pitch = DEG(RAD_TO_DEG(fR));
psProj->state = PROJ_INFLIGHTDIRECT;
}
else
@ -466,7 +466,7 @@ BOOL proj_SendProjectile(WEAPON *psWeap, BASE_OBJECT *psAttacker, int player, Ve
if ( fS < 0.0 )
{
/* set optimal pitch */
psProj->pitch = PROJ_MAX_PITCH;
psProj->rot.pitch = DEG(PROJ_MAX_PITCH);
fS = trigSin(PROJ_MAX_PITCH);
fC = trigCos(PROJ_MAX_PITCH);
@ -513,11 +513,11 @@ BOOL proj_SendProjectile(WEAPON *psWeap, BASE_OBJECT *psAttacker, int player, Ve
/* chooselow pitch unless -ve */
if ( iPitchLow > 0 )
{
psProj->pitch = (SWORD)iPitchLow;
psProj->rot.pitch = DEG(iPitchLow);
}
else
{
psProj->pitch = (SWORD)iPitchHigh;
psProj->rot.pitch = DEG(iPitchHigh);
}
}
@ -526,16 +526,16 @@ BOOL proj_SendProjectile(WEAPON *psWeap, BASE_OBJECT *psAttacker, int player, Ve
{
if (psAttacker->type == OBJ_DROID)
{
((DROID *) psAttacker)->asWeaps[weapon_slot].pitch = psProj->pitch;
((DROID *) psAttacker)->asWeaps[weapon_slot].rot.pitch = psProj->rot.pitch;
}
else if (psAttacker->type == OBJ_STRUCTURE)
{
((STRUCTURE *) psAttacker)->asWeaps[weapon_slot].pitch = psProj->pitch;
((STRUCTURE *) psAttacker)->asWeaps[weapon_slot].rot.pitch = psProj->rot.pitch;
}
}
psProj->vXY = iVel * trigCos(psProj->pitch);
psProj->vZ = iVel * trigSin(psProj->pitch);
psProj->vXY = iVel * trigCos(UNDEG(psProj->rot.pitch));
psProj->vZ = iVel * trigSin(UNDEG(psProj->rot.pitch));
psProj->state = PROJ_INFLIGHTINDIRECT;
}
@ -827,7 +827,7 @@ static void proj_InFlightFunc(PROJECTILE *psProj, bool bIndirect)
if (bIndirect)
{
/* Update pitch */
psProj->pitch = rad2degf(atan2f(psProj->vZ - (timeSoFar * ACC_GRAVITY / GAME_TICKS_PER_SEC), psProj->vXY));
psProj->rot.pitch = DEG(rad2degf(atan2f(psProj->vZ - (timeSoFar * ACC_GRAVITY / GAME_TICKS_PER_SEC), psProj->vXY)));
}
closestCollisionSpacetime.time = 0xFFFFFFFF;
@ -930,7 +930,7 @@ static void proj_InFlightFunc(PROJECTILE *psProj, bool bIndirect)
/* Buildings cannot be penetrated and we need a penetrating weapon */
if (closestCollisionObject->type == OBJ_DROID && psStats->penetrate)
{
WEAPON asWeap = {psStats - asWeaponStats, 0, 0, 0, 0, 0, 0, 0, 0};
WEAPON asWeap;
// Determine position to fire a missile at
// (must be at least 0 because we don't use signed integers
// this shouldn't be larger than the height and width of the map either)
@ -939,6 +939,8 @@ static void proj_InFlightFunc(PROJECTILE *psProj, bool bIndirect)
psProj->startY + move.y * distanceExtensionFactor,
psProj->srcHeight + move.z * distanceExtensionFactor
};
memset(&asWeap, 0, sizeof(asWeap));
asWeap.nStat = psStats - asWeaponStats;
ASSERT(distanceExtensionFactor != 0.f, "Unitialized variable used! distanceExtensionFactor is not initialized.");
@ -1791,7 +1793,7 @@ static HIT_SIDE getHitSide(PROJECTILE *psObj, BASE_OBJECT *psTarget)
* Work out the impact angle. It is easiest to understand if you
* model the target droid as a circle, divided up into 360 pieces.
*/
impactAngle = abs(psTarget->direction - (180 * atan2f(deltaX, deltaY) / M_PI));
impactAngle = abs(UNDEG(psTarget->rot.direction) - (180 * atan2f(deltaX, deltaY) / M_PI));
impactAngle = wrap(impactAngle, 360);
@ -1991,7 +1993,6 @@ void checkProjectile(const PROJECTILE* psProjectile, const char * const location
|| psProjectile->state == PROJ_INFLIGHTINDIRECT
|| psProjectile->state == PROJ_IMPACT
|| psProjectile->state == PROJ_POSTIMPACT, location_description, function, "CHECK_PROJECTILE: invalid projectile state: %u", (unsigned int)psProjectile->state);
ASSERT_HELPER(psProjectile->direction <= 360.0f && psProjectile->direction >= 0.0f, location_description, function, "CHECK_PROJECTILE: out of range direction (%f)", psProjectile->direction);
if (psProjectile->psDest)
checkObject(psProjectile->psDest, location_description, function, recurse - 1);

View File

@ -6365,8 +6365,9 @@ BOOL scrFireWeaponAtObj(void)
{
Vector3i target;
BASE_OBJECT *psTarget;
WEAPON sWeapon = {0, 0, 0, 0, 0, 0, 0, 0, 0};
WEAPON sWeapon;
memset(&sWeapon, 0, sizeof(sWeapon));
if (!stackPopParams(2, ST_WEAPON, &sWeapon.nStat, ST_BASEOBJECT, &psTarget))
{
return false;
@ -6390,8 +6391,9 @@ BOOL scrFireWeaponAtObj(void)
BOOL scrFireWeaponAtLoc(void)
{
Vector3i target;
WEAPON sWeapon = {0, 0, 0, 0, 0, 0, 0, 0, 0};
WEAPON sWeapon;
memset(&sWeapon, 0, sizeof(sWeapon));
if (!stackPopParams(3, ST_WEAPON, &sWeapon.nStat, VAL_INT, &target.x, VAL_INT, &target.y))
{
return false;

View File

@ -1428,7 +1428,7 @@ static SDWORD structChooseWallType(UDWORD player, UDWORD mapX, UDWORD mapY)
psStruct = apsStructs[x][y];
if (psStruct->pStructureType->type == REF_WALL || psStruct->pStructureType->type == REF_GATE)
{
if ( (int)psStruct->direction == 90 )
if (psStruct->rot.direction == DEG(90))
{
neighbourType = WALL_VERT;
}
@ -1493,12 +1493,12 @@ static SDWORD structChooseWallType(UDWORD player, UDWORD mapX, UDWORD mapY)
else if (scanType == WALL_HORIZ)
{
// change to a horizontal wall
psStruct->direction = 0;
psStruct->rot.direction = 0;
}
else
{
// change to a vertical wall
psStruct->direction = 90;
psStruct->rot.direction = DEG(90);
}
}
}
@ -1723,10 +1723,10 @@ STRUCTURE* buildStructure(STRUCTURE_STATS* pStructureType, UDWORD x, UDWORD y, U
//set up the rest of the data
for (i = 0;i < STRUCT_MAXWEAPS;i++)
{
psBuilding->asWeaps[i].rotation = 0;
psBuilding->asWeaps[i].pitch = 0;
psBuilding->asWeaps[i].prevRotation = 0;
psBuilding->asWeaps[i].prevPitch = 0;
psBuilding->asWeaps[i].rot.direction = 0;
psBuilding->asWeaps[i].rot.pitch = 0;
psBuilding->asWeaps[i].rot.roll = 0;
psBuilding->asWeaps[i].prevRot = psBuilding->asWeaps[i].rot;
psBuilding->psTarget[i] = NULL;
psBuilding->targetOrigin[i] = ORIGIN_UNKNOWN;
}
@ -1740,9 +1740,9 @@ STRUCTURE* buildStructure(STRUCTURE_STATS* pStructureType, UDWORD x, UDWORD y, U
psBuilding->burnStart = 0;
psBuilding->burnDamage = 0;
psBuilding->direction = 0;
psBuilding->pitch = 0;
psBuilding->roll = 0;
psBuilding->rot.direction = 0;
psBuilding->rot.pitch = 0;
psBuilding->rot.roll = 0;
psBuilding->selected = false;
psBuilding->status = SS_BEING_BUILT;
psBuilding->currentBuildPts = 0;
@ -1752,7 +1752,7 @@ STRUCTURE* buildStructure(STRUCTURE_STATS* pStructureType, UDWORD x, UDWORD y, U
// rotate a wall if necessary
if (!FromSave && (pStructureType->type == REF_WALL || pStructureType->type == REF_GATE ) && wallType == WALL_VERT)
{
psBuilding->direction = 90;
psBuilding->rot.direction = DEG(90);
}
//set up the sensor stats
@ -2092,7 +2092,7 @@ STRUCTURE *buildBlueprint(STRUCTURE_STATS *psStats, float x, float y, STRUCT_STA
blueprint->pos.x = x;
blueprint->pos.y = y;
blueprint->pos.z = map_Height(blueprint->pos.x, blueprint->pos.y) + world_coord(1)/10;
blueprint->direction = 0;
blueprint->rot.direction = 0;
blueprint->selected = false;
blueprint->timeLastHit = 0;
@ -2109,10 +2109,10 @@ STRUCTURE *buildBlueprint(STRUCTURE_STATS *psStats, float x, float y, STRUCT_STA
// things with sensors or ecm (or repair facilities) need these set, even if they have no official weapon
blueprint->numWeaps = 0;
blueprint->asWeaps[0].recoilValue = 0;
blueprint->asWeaps[0].pitch = 0;
blueprint->asWeaps[0].rotation = 0;
blueprint->asWeaps[0].prevPitch = 0;
blueprint->asWeaps[0].prevRotation = 0;
blueprint->asWeaps[0].rot.pitch = 0;
blueprint->asWeaps[0].rot.direction = 0;
blueprint->asWeaps[0].rot.roll = 0;
blueprint->asWeaps[0].prevRot = blueprint->asWeaps[0].rot;
blueprint->expectedDamage = 0;
@ -2878,8 +2878,7 @@ static void aiUpdateStructure(STRUCTURE *psStructure, bool mission)
psStructure->time = gameTime;
for (i = 0; i < MAX(1, psStructure->numWeaps); ++i)
{
psStructure->asWeaps[i].prevRotation = psStructure->asWeaps[i].rotation;
psStructure->asWeaps[i].prevPitch = psStructure->asWeaps[i].pitch;
psStructure->asWeaps[i].prevRot = psStructure->asWeaps[i].rot;
}
if (mission)
@ -2907,8 +2906,8 @@ static void aiUpdateStructure(STRUCTURE *psStructure, bool mission)
//////
// - radar should rotate every three seconds ... 'cause we timed it at Heathrow !
// gameTime is in milliseconds - one rotation every 3 seconds = 1 rotation event 3000 millisecs
psStructure->asWeaps[0].rotation = (UWORD)(((gameTime*360)/3000)%360);
psStructure->asWeaps[0].pitch = 0;
psStructure->asWeaps[0].rot.direction = DEG(((gameTime * 360) / 3000) % 360);
psStructure->asWeaps[0].rot.pitch = 0;
}
}
@ -2961,8 +2960,7 @@ static void aiUpdateStructure(STRUCTURE *psStructure, bool mission)
//if were going to shoot at something move the turret first then fire when locked on
if (psWStats->pMountGraphic == NULL)//no turret so lock on whatever
{
psStructure->asWeaps[i].rotation = (UWORD)calcDirection(psStructure->pos.x,
psStructure->pos.y, psChosenObjs[i]->pos.x, psChosenObjs[i]->pos.y);
psStructure->asWeaps[i].rot.direction = calcDirection(psStructure->pos.x, psStructure->pos.y, psChosenObjs[i]->pos.x, psChosenObjs[i]->pos.y);
combFire(&psStructure->asWeaps[i], (BASE_OBJECT *)psStructure, psChosenObjs[i], i);
}
else if (actionTargetTurret((BASE_OBJECT*)psStructure, psChosenObjs[i], &psStructure->asWeaps[i]))
@ -2973,7 +2971,7 @@ static void aiUpdateStructure(STRUCTURE *psStructure, bool mission)
else
{
// realign the turret
if ((psStructure->asWeaps[i].rotation % 90) != 0 || psStructure->asWeaps[i].pitch != 0)
if ((psStructure->asWeaps[i].rot.direction % DEG(90)) != 0 || psStructure->asWeaps[i].rot.pitch != 0)
{
actionAlignTurret((BASE_OBJECT *)psStructure, i);
}
@ -3261,7 +3259,7 @@ static void aiUpdateStructure(STRUCTURE *psStructure, bool mission)
{
actionTargetTurret((BASE_OBJECT*)psStructure, psChosenObj, &psStructure->asWeaps[0]);
}
else if ((psStructure->asWeaps[0].rotation % 90) != 0 || psStructure->asWeaps[0].pitch != 0)
else if ((psStructure->asWeaps[0].rot.direction % DEG(90)) != 0 || psStructure->asWeaps[0].rot.pitch != 0)
{
// realign the turret
actionAlignTurret((BASE_OBJECT *)psStructure, 0);
@ -5699,14 +5697,14 @@ BOOL calcStructureMuzzleLocation(STRUCTURE *psStructure, Vector3f *muzzle, int w
pie_TRANSLATE(psStructure->pos.x, -psStructure->pos.z, psStructure->pos.y);
//matrix = the center of droid
pie_MatRotY( DEG( psStructure->direction ) );
pie_MatRotX( DEG( psStructure->pitch ) );
pie_MatRotZ( DEG( -psStructure->roll ) );
pie_MatRotY(psStructure->rot.direction);
pie_MatRotX(psStructure->rot.pitch);
pie_MatRotZ(-psStructure->rot.roll);
pie_TRANSLATE( psShape->connectors[weapon_slot].x, -psShape->connectors[weapon_slot].z,
-psShape->connectors[weapon_slot].y);//note y and z flipped
//matrix = the weapon[slot] mount on the body
pie_MatRotY(DEG(psStructure->asWeaps[weapon_slot].rotation)); // +ve anticlockwise
pie_MatRotY(psStructure->asWeaps[weapon_slot].rot.direction); // +ve anticlockwise
// process turret mount
if (psMountImd && psMountImd->nconnectors)
@ -5715,7 +5713,7 @@ BOOL calcStructureMuzzleLocation(STRUCTURE *psStructure, Vector3f *muzzle, int w
}
//matrix = the turret connector for the gun
pie_MatRotX(DEG(psStructure->asWeaps[weapon_slot].pitch)); // +ve up
pie_MatRotX(psStructure->asWeaps[weapon_slot].rot.pitch); // +ve up
//process the gun
if (psWeaponImd && psWeaponImd->nconnectors)
@ -7837,7 +7835,7 @@ STRUCTURE * giftSingleStructure(STRUCTURE *psStructure, UBYTE attackPlayer, BOOL
psType = psStructure->pStructureType;
x = psStructure->pos.x;
y = psStructure->pos.y;
direction = psStructure->direction;
direction = psStructure->rot.direction;
originalPlayer = psStructure->player;
//save how complete the build process is
if (psStructure->status == SS_BEING_BUILT)
@ -7874,7 +7872,7 @@ STRUCTURE * giftSingleStructure(STRUCTURE *psStructure, UBYTE attackPlayer, BOOL
psNewStruct = buildStructure(psType, x, y, attackPlayer, true);
if (psNewStruct)
{
psNewStruct->direction = direction;
psNewStruct->rot.direction = direction;
if (capacity)
{
switch(psType->type)
@ -8203,7 +8201,6 @@ void checkStructure(const STRUCTURE* psStructure, const char * const location_de
for (i = 0; i < ARRAY_SIZE(psStructure->asWeaps); ++i)
{
ASSERT_HELPER(psStructure->asWeaps[i].rotation <= 360, location_description, function, "CHECK_STRUCTURE: Out of range turret rotation (turret %u; rotation: %u)", i, (unsigned int)psStructure->asWeaps[i].rotation);
if (psStructure->psTarget[i])
{
checkObject(psStructure->psTarget[i], location_description, function, recurse - 1);

View File

@ -29,6 +29,7 @@
#include "objectdef.h"
#include "structuredef.h"
#include "visibility.h"
#include "baseobject.h"
#ifdef __cplusplus
extern "C"
@ -437,15 +438,9 @@ static inline int structConcealment(const STRUCTURE* psObj)
return objConcealment((const BASE_OBJECT*)psObj);
}
static inline float structureGetInterpolatedWeaponRotation(STRUCTURE *psStructure, int weaponSlot, uint32_t time)
static inline Rotation structureGetInterpolatedWeaponRotation(STRUCTURE *psStructure, int weaponSlot, uint32_t time)
{
return interpolateDirection(psStructure->asWeaps[weaponSlot].prevRotation, psStructure->asWeaps[weaponSlot].rotation, psStructure->prevTime, psStructure->time, time);
}
static inline float structureGetInterpolatedWeaponPitch(STRUCTURE *psStructure, int weaponSlot, uint32_t time)
{
// Aaargh, Direction[sic]. Angles can be 16-bit (65536 "degrees" in circle), or can be floats (360.0f degrees). Except here, where they are _unsigned_ integers from 0 to 360. All hail consistency!
return interpolateDirection(psStructure->asWeaps[weaponSlot].prevPitch, psStructure->asWeaps[weaponSlot].pitch, psStructure->prevTime, psStructure->time, time);
return interpolateRot(psStructure->asWeaps[weaponSlot].prevRot, psStructure->asWeaps[weaponSlot].rot, psStructure->prevTime, psStructure->time, time);
}
#define setStructureTarget(_psBuilding, _psNewTarget, _idx, _targetOrigin) _setStructureTarget(_psBuilding, _psNewTarget, _idx, _targetOrigin, __LINE__, __FUNCTION__)

View File

@ -304,9 +304,9 @@ static void setUpRadarTarget(SDWORD x, SDWORD y)
{
radarTarget.pos.z = map_Height(x,y) + CAMERA_PIVOT_HEIGHT;
}
radarTarget.direction = calcDirection(player.p.x, player.p.z, x, y);
radarTarget.pitch = 0;
radarTarget.roll = 0;
radarTarget.rot.direction = calcDirection(player.p.x, player.p.z, x, y);
radarTarget.rot.pitch = 0;
radarTarget.rot.roll = 0;
radarTarget.type = OBJ_TARGET;
radarTarget.died = 0;
}
@ -547,9 +547,9 @@ static SDWORD getAverageTrackAngle( BOOL bCheckOnScreen )
if (bCheckOnScreen ? droidOnScreen(psDroid, pie_GetVideoBufferWidth() / 6) : true)
{
droidCount++;
averageAngle += psDroid->direction;
xShift = trigSin(psDroid->direction);
yShift = trigCos(psDroid->direction);
averageAngle += UNDEG(psDroid->rot.direction);
xShift = trigSin(UNDEG(psDroid->rot.direction));
yShift = trigCos(UNDEG(psDroid->rot.direction));
xTotal += xShift;
yTotal += yShift;
}
@ -589,9 +589,9 @@ static SDWORD getGroupAverageTrackAngle(UDWORD groupNumber, BOOL bCheckOnScreen)
if (bCheckOnScreen ? droidOnScreen(psDroid, pie_GetVideoBufferWidth() / 6) : true)
{
droidCount++;
averageAngle += psDroid->direction;
xShift = trigSin(psDroid->direction);
yShift = trigCos(psDroid->direction);
averageAngle += UNDEG(psDroid->rot.direction);
xShift = trigSin(UNDEG(psDroid->rot.direction));
yShift = trigCos(UNDEG(psDroid->rot.direction));
xTotal += xShift;
yTotal += yShift;
}
@ -766,8 +766,8 @@ static void updateCameraAcceleration(UBYTE update)
}
else
{
behind.x = ( CAM_DEFAULT_Y_OFFSET * SIN( DEG( trackingCamera.target->direction ) ) ) >> FP12_SHIFT;
behind.y = ( CAM_DEFAULT_X_OFFSET * COS( DEG( trackingCamera.target->direction ) ) ) >> FP12_SHIFT;
behind.x = ( CAM_DEFAULT_Y_OFFSET * SIN(trackingCamera.target->rot.direction ) ) >> FP12_SHIFT;
behind.y = ( CAM_DEFAULT_X_OFFSET * COS(trackingCamera.target->rot.direction) ) >> FP12_SHIFT;
}
concern.y += angle*5;
@ -931,7 +931,7 @@ static void updateCameraRotationAcceleration( UBYTE update )
}
else
{
yConcern = DEG( (int)trackingCamera.target->direction );
yConcern = trackingCamera.target->rot.direction;
}
yConcern += DEG(180);
@ -973,7 +973,7 @@ static void updateCameraRotationAcceleration( UBYTE update )
}
else
{
xConcern = DEG(trackingCamera.target->pitch);
xConcern = trackingCamera.target->rot.pitch;
xConcern += DEG(-16);
}
@ -1015,7 +1015,7 @@ static void updateCameraRotationAcceleration( UBYTE update )
}
else
{
zConcern = DEG(trackingCamera.target->roll);
zConcern = trackingCamera.target->rot.roll;
}
while(trackingCamera.rotation.z<0)
{

View File

@ -36,10 +36,8 @@ typedef struct _weapon
uint32_t lastFired; ///< The gametime when this weapon last fired
uint32_t shotsFired;
uint32_t recoilValue;
uint16_t pitch;
uint16_t rotation;
uint16_t prevPitch;
uint16_t prevRotation;
Rotation rot;
Rotation prevRot;
} WEAPON;
#ifdef __cplusplus