mirror of
https://github.com/ZDoom/qzdoom.git
synced 2024-11-11 15:22:16 +00:00
-floatified P_ExplodeMissile and P_XYMovement
This commit is contained in:
parent
7b256dda3d
commit
217414cb1c
3 changed files with 85 additions and 118 deletions
|
@ -84,7 +84,6 @@ inline int GetSafeBlockY(long long blocky)
|
|||
}
|
||||
|
||||
//#define GRAVITY FRACUNIT
|
||||
#define _f_MAXMOVE (30*FRACUNIT)
|
||||
#define MAXMOVE (30.)
|
||||
|
||||
#define TALKRANGE (128.)
|
||||
|
|
197
src/p_mobj.cpp
197
src/p_mobj.cpp
|
@ -1,5 +1,4 @@
|
|||
// Emacs style mode select -*- C++ -*-
|
||||
// Emacs style mode select -*- C++ -*-
|
||||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
// $Id:$
|
||||
|
@ -1386,8 +1385,8 @@ void P_ExplodeMissile (AActor *mo, line_t *line, AActor *target)
|
|||
|
||||
if (line != NULL && cl_missiledecals)
|
||||
{
|
||||
fixedvec3 pos = mo->_f_PosRelative(line);
|
||||
int side = P_PointOnLineSidePrecise (pos.x, pos.y, line);
|
||||
DVector3 pos = mo->PosRelative(line);
|
||||
int side = P_PointOnLineSidePrecise (pos, line);
|
||||
if (line->sidedef[side] == NULL)
|
||||
side ^= 1;
|
||||
if (line->sidedef[side] != NULL)
|
||||
|
@ -1396,31 +1395,15 @@ void P_ExplodeMissile (AActor *mo, line_t *line, AActor *target)
|
|||
if (base != NULL)
|
||||
{
|
||||
// Find the nearest point on the line, and stick a decal there
|
||||
fixed_t x, y, z;
|
||||
SQWORD num, den;
|
||||
DVector3 linepos;
|
||||
double num, den, frac;
|
||||
|
||||
den = (SQWORD)line->dx*line->dx + (SQWORD)line->dy*line->dy;
|
||||
den = line->Delta().LengthSquared();
|
||||
if (den != 0)
|
||||
{
|
||||
SDWORD frac;
|
||||
frac = clamp<double>((mo->Pos() - line->v1->fPos()) | line->Delta(), 0, den) / den;
|
||||
|
||||
num = (SQWORD)(pos.x-line->v1->x)*line->dx+(SQWORD)(pos.y-line->v1->y)*line->dy;
|
||||
if (num <= 0)
|
||||
{
|
||||
frac = 0;
|
||||
}
|
||||
else if (num >= den)
|
||||
{
|
||||
frac = 1<<30;
|
||||
}
|
||||
else
|
||||
{
|
||||
frac = (SDWORD)(num / (den>>30));
|
||||
}
|
||||
|
||||
x = line->v1->x + MulScale30 (line->dx, frac);
|
||||
y = line->v1->y + MulScale30 (line->dy, frac);
|
||||
z = pos.z;
|
||||
linepos = DVector3(line->v1->fPos() + line->Delta() * frac, pos.Z);
|
||||
|
||||
F3DFloor * ffloor=NULL;
|
||||
if (line->sidedef[side^1] != NULL)
|
||||
|
@ -1434,16 +1417,16 @@ void P_ExplodeMissile (AActor *mo, line_t *line, AActor *target)
|
|||
|
||||
if ((rover->flags&(FF_EXISTS|FF_SOLID|FF_RENDERSIDES))==(FF_EXISTS|FF_SOLID|FF_RENDERSIDES))
|
||||
{
|
||||
if (z<=rover->top.plane->ZatPoint(x, y) && z>=rover->bottom.plane->ZatPoint( x, y))
|
||||
if (pos.Z <= rover->top.plane->ZatPoint(linepos) && pos.Z >= rover->bottom.plane->ZatPoint(linepos))
|
||||
{
|
||||
ffloor=rover;
|
||||
ffloor = rover;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
DImpactDecal::StaticCreate(base->GetDecal(), DVector3(FIXED2DBL(x), FIXED2DBL(y), FIXED2DBL(z)), line->sidedef[side], ffloor);
|
||||
DImpactDecal::StaticCreate(base->GetDecal(), linepos, line->sidedef[side], ffloor);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1529,7 +1512,7 @@ void AActor::PlayBounceSound(bool onfloor)
|
|||
|
||||
bool AActor::FloorBounceMissile (secplane_t &plane)
|
||||
{
|
||||
if (_f_Z() <= _f_floorz() && P_HitFloor (this))
|
||||
if (Z() <= floorz && P_HitFloor (this))
|
||||
{
|
||||
// Landed in some sort of liquid
|
||||
if (BounceFlags & BOUNCE_ExplodeOnWater)
|
||||
|
@ -1760,22 +1743,22 @@ bool P_SeekerMissile (AActor *actor, double thresh, double turnMax, bool precise
|
|||
// Returns the actor's old floorz.
|
||||
//
|
||||
#define STOPSPEED (0x1000/65536.)
|
||||
#define CARRYSTOPSPEED (0x1000*32/3)
|
||||
#define CARRYSTOPSPEED ((0x1000*32/3)/65536.)
|
||||
|
||||
fixed_t P_XYMovement (AActor *mo, fixed_t scrollx, fixed_t scrolly)
|
||||
double P_XYMovement (AActor *mo, DVector2 scroll)
|
||||
{
|
||||
static int pushtime = 0;
|
||||
bool bForceSlide = scrollx || scrolly;
|
||||
bool bForceSlide = !scroll.isZero();
|
||||
DAngle Angle;
|
||||
fixed_t ptryx, ptryy;
|
||||
DVector2 ptry;
|
||||
player_t *player;
|
||||
fixed_t xmove, ymove;
|
||||
DVector2 move;
|
||||
const secplane_t * walkplane;
|
||||
static const double windTab[3] = { 5 / 32., 10 / 32., 25 / 32. };
|
||||
int steps, step, totalsteps;
|
||||
fixed_t startx, starty;
|
||||
fixed_t oldfloorz = mo->_f_floorz();
|
||||
fixed_t oldz = mo->_f_Z();
|
||||
DVector2 start;
|
||||
double Oldfloorz = mo->floorz;
|
||||
double oldz = mo->Z();
|
||||
|
||||
double maxmove = (mo->waterlevel < 1) || (mo->flags & MF_MISSILE) ||
|
||||
(mo->player && mo->player->crouchoffset<-10) ? MAXMOVE : MAXMOVE/4;
|
||||
|
@ -1815,29 +1798,27 @@ fixed_t P_XYMovement (AActor *mo, fixed_t scrollx, fixed_t scrolly)
|
|||
mo->Vel.X *= fac;
|
||||
mo->Vel.Y *= fac;
|
||||
}
|
||||
xmove = mo->_f_velx();
|
||||
ymove = mo->_f_vely();
|
||||
move = mo->Vel;
|
||||
// [RH] Carrying sectors didn't work with low speeds in BOOM. This is
|
||||
// because BOOM relied on the speed being fast enough to accumulate
|
||||
// despite friction. If the speed is too low, then its movement will get
|
||||
// cancelled, and it won't accumulate to the desired speed.
|
||||
mo->flags4 &= ~MF4_SCROLLMOVE;
|
||||
if (abs(scrollx) > CARRYSTOPSPEED)
|
||||
if (fabs(scroll.X) > CARRYSTOPSPEED)
|
||||
{
|
||||
scrollx = FixedMul (scrollx, _f_CARRYFACTOR);
|
||||
mo->Vel.X += FIXED2DBL(scrollx);
|
||||
scroll.X *= CARRYFACTOR;
|
||||
mo->Vel.X += scroll.X;
|
||||
mo->flags4 |= MF4_SCROLLMOVE;
|
||||
}
|
||||
if (abs(scrolly) > CARRYSTOPSPEED)
|
||||
if (fabs(scroll.Y) > CARRYSTOPSPEED)
|
||||
{
|
||||
scrolly = FixedMul (scrolly, _f_CARRYFACTOR);
|
||||
mo->Vel.Y += FIXED2DBL(scrolly);
|
||||
scroll.Y *= CARRYFACTOR;
|
||||
mo->Vel.Y += scroll.Y;
|
||||
mo->flags4 |= MF4_SCROLLMOVE;
|
||||
}
|
||||
xmove += scrollx;
|
||||
ymove += scrolly;
|
||||
move += scroll;
|
||||
|
||||
if ((xmove | ymove) == 0)
|
||||
if (move.isZero())
|
||||
{
|
||||
if (mo->flags & MF_SKULLFLY)
|
||||
{
|
||||
|
@ -1855,15 +1836,14 @@ fixed_t P_XYMovement (AActor *mo, fixed_t scrollx, fixed_t scrolly)
|
|||
mo->tics = -1;
|
||||
}
|
||||
}
|
||||
return oldfloorz;
|
||||
return Oldfloorz;
|
||||
}
|
||||
|
||||
player = mo->player;
|
||||
|
||||
// [RH] Adjust player movement on sloped floors
|
||||
fixed_t startxmove = xmove;
|
||||
fixed_t startymove = ymove;
|
||||
walkplane = P_CheckSlopeWalk (mo, xmove, ymove);
|
||||
DVector2 startmove = move;
|
||||
walkplane = P_CheckSlopeWalk (mo, move);
|
||||
|
||||
// [RH] Take smaller steps when moving faster than the object's size permits.
|
||||
// Moving as fast as the object's "diameter" is bad because it could skip
|
||||
|
@ -1872,15 +1852,15 @@ fixed_t P_XYMovement (AActor *mo, fixed_t scrollx, fixed_t scrolly)
|
|||
// through the actor.
|
||||
|
||||
{
|
||||
fixed_t maxmove = mo->_f_radius() - FRACUNIT;
|
||||
double maxmove = mo->radius - 1;
|
||||
|
||||
if (maxmove <= 0)
|
||||
{ // gibs can have _f_radius() 0, so don't divide by zero below!
|
||||
maxmove = _f_MAXMOVE;
|
||||
{ // gibs can have radius 0, so don't divide by zero below!
|
||||
maxmove = MAXMOVE;
|
||||
}
|
||||
|
||||
const fixed_t xspeed = abs (xmove);
|
||||
const fixed_t yspeed = abs (ymove);
|
||||
const double xspeed = fabs (move.X);
|
||||
const double yspeed = fabs (move.Y);
|
||||
|
||||
steps = 1;
|
||||
|
||||
|
@ -1888,25 +1868,23 @@ fixed_t P_XYMovement (AActor *mo, fixed_t scrollx, fixed_t scrolly)
|
|||
{
|
||||
if (xspeed > maxmove)
|
||||
{
|
||||
steps = 1 + xspeed / maxmove;
|
||||
steps = int(1 + xspeed / maxmove);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (yspeed > maxmove)
|
||||
{
|
||||
steps = 1 + yspeed / maxmove;
|
||||
steps = int(1 + yspeed / maxmove);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// P_SlideMove needs to know the step size before P_CheckSlopeWalk
|
||||
// because it also calls P_CheckSlopeWalk on its clipped steps.
|
||||
fixed_t onestepx = startxmove / steps;
|
||||
fixed_t onestepy = startymove / steps;
|
||||
DVector2 onestep = startmove / steps;
|
||||
|
||||
startx = mo->_f_X();
|
||||
starty = mo->_f_Y();
|
||||
start = mo->Pos();
|
||||
step = 1;
|
||||
totalsteps = steps;
|
||||
|
||||
|
@ -1923,23 +1901,19 @@ fixed_t P_XYMovement (AActor *mo, fixed_t scrollx, fixed_t scrolly)
|
|||
|
||||
FCheckPosition tm(!!(mo->flags2 & MF2_RIP));
|
||||
|
||||
angle_t oldangle = mo->_f_angle();
|
||||
DAngle oldangle = mo->Angles.Yaw;
|
||||
do
|
||||
{
|
||||
if (i_compatflags & COMPATF_WALLRUN) pushtime++;
|
||||
tm.PushTime = pushtime;
|
||||
|
||||
ptryx = startx + Scale (xmove, step, steps);
|
||||
ptryy = starty + Scale (ymove, step, steps);
|
||||
ptry = start + move * step / steps;
|
||||
|
||||
DVector2 startvel = mo->Vel;
|
||||
|
||||
/* if (mo->player)
|
||||
Printf ("%d,%d/%d: %d %d %d %d %d %d %d\n", level.time, step, steps, startxmove, Scale(xmove,step,steps), startymove, Scale(ymove,step,steps), mo->x, mo->y, mo->z);
|
||||
*/
|
||||
// [RH] If walking on a slope, stay on the slope
|
||||
// killough 3/15/98: Allow objects to drop off
|
||||
fixed_t startvelx = mo->_f_velx(), startvely = mo->_f_vely();
|
||||
|
||||
if (!P_TryMove (mo, DVector2(FIXED2DBL(ptryx), FIXED2DBL(ptryy)), true, walkplane, tm))
|
||||
// [RH] If walking on a slope, stay on the slope
|
||||
if (!P_TryMove (mo, ptry, true, walkplane, tm))
|
||||
{
|
||||
// blocked move
|
||||
AActor *BlockingMobj = mo->BlockingMobj;
|
||||
|
@ -1964,7 +1938,7 @@ fixed_t P_XYMovement (AActor *mo, fixed_t scrollx, fixed_t scrolly)
|
|||
}
|
||||
// If the blocked move executed any push specials that changed the
|
||||
// actor's velocity, do not attempt to slide.
|
||||
if (mo->_f_velx() == startvelx && mo->_f_vely() == startvely)
|
||||
if (mo->Vel.XY() == startvel)
|
||||
{
|
||||
if (player && (i_compatflags & COMPATF_WALLRUN))
|
||||
{
|
||||
|
@ -1976,9 +1950,9 @@ fixed_t P_XYMovement (AActor *mo, fixed_t scrollx, fixed_t scrolly)
|
|||
}
|
||||
else
|
||||
{
|
||||
P_SlideMove (mo, DVector2(FIXED2DBL(onestepx), FIXED2DBL(onestepy)), totalsteps);
|
||||
P_SlideMove (mo, onestep, totalsteps);
|
||||
}
|
||||
if ((mo->_f_velx() | mo->_f_vely()) == 0)
|
||||
if (mo->Vel.XY().isZero())
|
||||
{
|
||||
steps = 0;
|
||||
}
|
||||
|
@ -1986,14 +1960,11 @@ fixed_t P_XYMovement (AActor *mo, fixed_t scrollx, fixed_t scrolly)
|
|||
{
|
||||
if (!player || !(i_compatflags & COMPATF_WALLRUN))
|
||||
{
|
||||
xmove = mo->_f_velx();
|
||||
ymove = mo->_f_vely();
|
||||
onestepx = xmove / steps;
|
||||
onestepy = ymove / steps;
|
||||
P_CheckSlopeWalk (mo, xmove, ymove);
|
||||
move = mo->Vel;
|
||||
onestep = move / steps;
|
||||
P_CheckSlopeWalk (mo, move);
|
||||
}
|
||||
startx = mo->_f_X() - Scale (xmove, step, steps);
|
||||
starty = mo->_f_Y() - Scale (ymove, step, steps);
|
||||
start = mo->Pos().XY() - move * step / steps;
|
||||
}
|
||||
}
|
||||
else
|
||||
|
@ -2003,18 +1974,18 @@ fixed_t P_XYMovement (AActor *mo, fixed_t scrollx, fixed_t scrolly)
|
|||
}
|
||||
else
|
||||
{ // slide against another actor
|
||||
fixed_t tx, ty;
|
||||
tx = 0, ty = onestepy;
|
||||
walkplane = P_CheckSlopeWalk (mo, tx, ty);
|
||||
if (P_TryMove (mo, mo->Pos() + DVector2(FIXED2DBL(tx), FIXED2DBL(ty)), true, walkplane, tm))
|
||||
DVector2 t;
|
||||
t.X = 0, t.Y = onestep.Y;
|
||||
walkplane = P_CheckSlopeWalk (mo, t);
|
||||
if (P_TryMove (mo, mo->Pos() + t, true, walkplane, tm))
|
||||
{
|
||||
mo->Vel.X = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
tx = onestepx, ty = 0;
|
||||
walkplane = P_CheckSlopeWalk (mo, tx, ty);
|
||||
if (P_TryMove (mo, mo->Pos() + DVector2(FIXED2DBL(tx), FIXED2DBL(ty)), true, walkplane, tm))
|
||||
t.X = onestep.X, t.Y = 0;
|
||||
walkplane = P_CheckSlopeWalk (mo, t);
|
||||
if (P_TryMove (mo, mo->Pos() + t, true, walkplane, tm))
|
||||
{
|
||||
mo->Vel.Y = 0;
|
||||
}
|
||||
|
@ -2045,7 +2016,7 @@ fixed_t P_XYMovement (AActor *mo, fixed_t scrollx, fixed_t scrolly)
|
|||
{ // Struck a player/creature
|
||||
P_ExplodeMissile (mo, NULL, BlockingMobj);
|
||||
}
|
||||
return oldfloorz;
|
||||
return Oldfloorz;
|
||||
}
|
||||
}
|
||||
else
|
||||
|
@ -2054,7 +2025,7 @@ fixed_t P_XYMovement (AActor *mo, fixed_t scrollx, fixed_t scrolly)
|
|||
if (P_BounceWall (mo))
|
||||
{
|
||||
mo->PlayBounceSound(false);
|
||||
return oldfloorz;
|
||||
return Oldfloorz;
|
||||
}
|
||||
}
|
||||
if (BlockingMobj && (BlockingMobj->flags2 & MF2_REFLECTIVE))
|
||||
|
@ -2105,7 +2076,7 @@ fixed_t P_XYMovement (AActor *mo, fixed_t scrollx, fixed_t scrolly)
|
|||
mo->tracer = mo->target;
|
||||
}
|
||||
mo->target = BlockingMobj;
|
||||
return oldfloorz;
|
||||
return Oldfloorz;
|
||||
}
|
||||
explode:
|
||||
// explode a missile
|
||||
|
@ -2114,22 +2085,22 @@ explode:
|
|||
if (tm.ceilingline &&
|
||||
tm.ceilingline->backsector &&
|
||||
tm.ceilingline->backsector->GetTexture(sector_t::ceiling) == skyflatnum &&
|
||||
mo->_f_Z() >= tm.ceilingline->backsector->ceilingplane.ZatPoint(mo->_f_PosRelative(tm.ceilingline)))
|
||||
mo->Z() >= tm.ceilingline->backsector->ceilingplane.ZatPoint(mo->PosRelative(tm.ceilingline)))
|
||||
{
|
||||
// Hack to prevent missiles exploding against the sky.
|
||||
// Does not handle sky floors.
|
||||
mo->Destroy ();
|
||||
return oldfloorz;
|
||||
return Oldfloorz;
|
||||
}
|
||||
// [RH] Don't explode on horizon lines.
|
||||
if (mo->BlockingLine != NULL && mo->BlockingLine->special == Line_Horizon)
|
||||
{
|
||||
mo->Destroy ();
|
||||
return oldfloorz;
|
||||
return Oldfloorz;
|
||||
}
|
||||
}
|
||||
P_ExplodeMissile (mo, mo->BlockingLine, BlockingMobj);
|
||||
return oldfloorz;
|
||||
return Oldfloorz;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -2139,32 +2110,26 @@ explode:
|
|||
}
|
||||
else
|
||||
{
|
||||
if (mo->_f_X() != ptryx || mo->_f_Y() != ptryy)
|
||||
if (mo->Pos().XY() != ptry)
|
||||
{
|
||||
// If the new position does not match the desired position, the player
|
||||
// must have gone through a teleporter, so stop moving right now if it
|
||||
// was a regular teleporter. If it was a line-to-line or fogless teleporter,
|
||||
// the move should continue, but startx, starty and xmove, ymove need to change.
|
||||
// the move should continue, but start and move need to change.
|
||||
if (mo->Vel.X == 0 && mo->Vel.Y == 0)
|
||||
{
|
||||
step = steps;
|
||||
}
|
||||
else
|
||||
{
|
||||
angle_t anglediff = (mo->_f_angle() - oldangle) >> ANGLETOFINESHIFT;
|
||||
DAngle anglediff = deltaangle(oldangle, mo->Angles.Yaw);
|
||||
|
||||
if (anglediff != 0)
|
||||
{
|
||||
fixed_t xnew = FixedMul(xmove, finecosine[anglediff]) - FixedMul(ymove, finesine[anglediff]);
|
||||
fixed_t ynew = FixedMul(xmove, finesine[anglediff]) + FixedMul(ymove, finecosine[anglediff]);
|
||||
|
||||
xmove = xnew;
|
||||
ymove = ynew;
|
||||
oldangle = mo->_f_angle(); // in case more moves are needed this needs to be updated.
|
||||
move = move.Rotated(anglediff);
|
||||
oldangle = mo->Angles.Yaw; // in case more moves are needed this needs to be updated.
|
||||
}
|
||||
|
||||
startx = mo->_f_X() - Scale (xmove, step, steps);
|
||||
starty = mo->_f_Y() - Scale (ymove, step, steps);
|
||||
start = mo->Pos() - move * step / steps;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -2176,12 +2141,12 @@ explode:
|
|||
{ // debug option for no sliding at all
|
||||
mo->Vel.X = mo->Vel.Y = 0;
|
||||
player->Vel.X = player->Vel.Y = 0;
|
||||
return oldfloorz;
|
||||
return Oldfloorz;
|
||||
}
|
||||
|
||||
if (mo->flags & (MF_MISSILE | MF_SKULLFLY))
|
||||
{ // no friction for missiles
|
||||
return oldfloorz;
|
||||
return Oldfloorz;
|
||||
}
|
||||
|
||||
if (mo->Z() > mo->floorz && !(mo->flags2 & MF2_ONMOBJ) &&
|
||||
|
@ -2200,7 +2165,7 @@ explode:
|
|||
player->Vel.Y *= level.airfriction;
|
||||
}
|
||||
}
|
||||
return oldfloorz;
|
||||
return Oldfloorz;
|
||||
}
|
||||
|
||||
// killough 8/11/98: add bouncers
|
||||
|
@ -2221,10 +2186,10 @@ explode:
|
|||
// if the floor comes from one in the current sector stop sliding the corpse!
|
||||
F3DFloor * rover=mo->Sector->e->XFloor.ffloors[i];
|
||||
if (!(rover->flags&FF_EXISTS)) continue;
|
||||
if (rover->flags&FF_SOLID && rover->top.plane->ZatPoint(mo) == mo->_f_floorz()) break;
|
||||
if (rover->flags&FF_SOLID && rover->top.plane->ZatPointF(mo) == mo->floorz) break;
|
||||
}
|
||||
if (i==mo->Sector->e->XFloor.ffloors.Size())
|
||||
return oldfloorz;
|
||||
return Oldfloorz;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -2291,7 +2256,7 @@ explode:
|
|||
if (fabs(player->Vel.Y) < MinVel) player->Vel.Y = 0;
|
||||
}
|
||||
}
|
||||
return oldfloorz;
|
||||
return Oldfloorz;
|
||||
}
|
||||
|
||||
// Move this to p_inter ***
|
||||
|
@ -3724,9 +3689,7 @@ void AActor::Tick ()
|
|||
|
||||
// Handle X and Y velocities
|
||||
BlockingMobj = NULL;
|
||||
assert(!player || !isnan(Vel.X));
|
||||
fixed_t oldfloorz = P_XYMovement (this, cummx, cummy);
|
||||
assert(!player || !isnan(Vel.X));
|
||||
fixed_t oldfloorz = FLOAT2FIXED(P_XYMovement (this, DVector2(FIXED2DBL(cummx), FIXED2DBL(cummy))));
|
||||
if (ObjectFlags & OF_EuthanizeMe)
|
||||
{ // actor was destroyed
|
||||
return;
|
||||
|
|
|
@ -86,6 +86,11 @@ struct TVector2
|
|||
Y = X = 0;
|
||||
}
|
||||
|
||||
bool isZero() const
|
||||
{
|
||||
return X == 0 && Y == 0;
|
||||
}
|
||||
|
||||
TVector2 &operator= (const TVector2 &other)
|
||||
{
|
||||
// This might seem backwards, but this helps produce smaller code when a newly
|
||||
|
|
Loading…
Reference in a new issue