Example #1
0
//	-----------------------------------------------------------------------------
//extract angles from a m_data.matrix
const CAngleVector CFixMatrix::ExtractAnglesVec (void) const 
{
	CAngleVector a;
	fix sinh, cosh, cosp;

if (m_data.mat [FVEC][X] == 0 && m_data.mat [FVEC][Z] == 0)		//zero head
	a [HA] = 0;
else
	a [HA] = FixAtan2 (m_data.mat [FVEC][Z], m_data.mat [FVEC][X]);
FixSinCos (a [HA], &sinh, &cosh);
if (abs (sinh) > abs (cosh))				//sine is larger, so use it
	cosp = FixDiv (m_data.mat [FVEC][X], sinh);
else											//cosine is larger, so use it
	cosp = FixDiv (m_data.mat [FVEC][Z], cosh);
if (cosp==0 && m_data.mat [FVEC][Y]==0)
	a [PA] = 0;
else
	a [PA] = FixAtan2 (cosp, -m_data.mat [FVEC][Y]);
if (cosp == 0)	//the cosine of pitch is zero.  we're pitched straight up. say no bank
	a [BA] = 0;
else {
	fix sinb, cosb;

	sinb = FixDiv (m_data.mat [RVEC][Y], cosp);
	cosb = FixDiv (m_data.mat [UVEC][Y], cosp);
	if (sinb==0 && cosb==0)
		a [BA] = 0;
	else
		a [BA] = FixAtan2 (cosb, sinb);
	}
return a;
}
Example #2
0
File: rod.cpp Project: paud/d2x-xl
//------------------------------------------------------------------------------
//compute the corners of a rod.  fills in vertbuf.
int CalcRodCorners (g3sPoint *btmPoint, fix xBtmWidth, g3sPoint *topPoint, fix xTopWidth)
{
	vmsVector	vDelta, vTop, vTemp, vRodNorm;
	ubyte			andCodes;
	int			i;

//compute vector from one point to other, do cross product with vector
//from eye to get perpendicular
vDelta = btmPoint->p3_vec - topPoint->p3_vec;
//unscale for aspect
#if RESCALE_ROD
vDelta.p.x = FixDiv (vDelta.p.x, viewInfo.scale.p.x);
vDelta.p.y = FixDiv (vDelta.p.y, viewInfo.scale.p.y);
#endif
//calc Perp vector
//do lots of normalizing to prevent overflowing.  When this code works,
//it should be optimized
vmsVector::Normalize(vDelta);
vTop = topPoint->p3_vec;
vmsVector::Normalize(vTop);
vRodNorm = vmsVector::Cross(vDelta, vTop);
vmsVector::Normalize(vRodNorm);
//scale for aspect
#if RESCALE_ROD
vRodNorm.p.x = FixMul (vRodNorm.p.x, viewInfo.scale.p.x);
vRodNorm.p.y = FixMul (vRodNorm.p.y, viewInfo.scale.p.y);
#endif
//now we have the usable edge.  generate four points
//vTop points
vTemp = vRodNorm * xTopWidth;
vTemp[Z] = 0;
rodPoints [0].p3_vec = topPoint->p3_vec + vTemp;
rodPoints [1].p3_vec = topPoint->p3_vec - vTemp;
vTemp = vRodNorm * xBtmWidth;
vTemp[Z] = 0;
rodPoints [2].p3_vec = btmPoint->p3_vec - vTemp;
rodPoints [3].p3_vec = btmPoint->p3_vec + vTemp;

//now code the four points
for (i = 0, andCodes = 0xff; i < 4; i++)
	andCodes &= G3EncodePoint (rodPoints + i);
if (andCodes)
	return 1;		//1 means off screen
//clear flags for new points (not projected)
for (i = 0; i < 4; i++) {
	rodPoints [i].p3_flags = 0;
	rodPoints [i].p3_index = -1;
	}
return 0;
}
Example #3
0
File: med.c Project: paud/d2x-xl
//sets the tPlayer facing curseg/curside, normal to face0 of curside, and
//far enough away to see all of curside
int SetPlayerFromCursegMinusOne()
{
	vmsVector view_vec,view_vec2,side_center;
	vmsVector corner_v[4];
	vmsVector	upvec;
	g3sPoint corner_p[4];
	int i;
	fix max,viewDist=f1_0*10;
        static int edgenum=0;
	int newseg;

	view_vec = Cursegp->sides[Curside].normals[0];
	VmVecNegate(&view_vec);

	COMPUTE_SIDE_CENTER(&side_center,Cursegp,Curside);
	VmVecCopyScale(&view_vec2,&view_vec,viewDist);
	VmVecSub(&gameData.objs.console->position.vPos,&side_center,&view_vec2);

	VmVecSub(&upvec, &gameData.segs.vertices[Cursegp->verts[sideToVerts[Curside][edgenum%4]]], &gameData.segs.vertices[Cursegp->verts[sideToVerts[Curside][(edgenum+3)%4]]]);
	edgenum++;

	VmVector2Matrix(&gameData.objs.console->position.mOrient,&view_vec,&upvec,NULL);

	GrSetCurrentCanvas(Canv_editor_game);
	G3StartFrame();
	G3SetViewMatrix(&gameData.objs.console->position.vPos,&gameData.objs.console->position.mOrient,gameStates.render.xZoom, 1);

	for (i=max=0;i<4;i++) {
		corner_v[i] = gameData.segs.vertices[Cursegp->verts[sideToVerts[Curside][i]]];
		G3TransformAndEncodePoint(&corner_p[i],&corner_v[i]);
		if (labs(corner_p[i].p3_x) > max) max = labs(corner_p[i].p3_x);
		if (labs(corner_p[i].p3_y) > max) max = labs(corner_p[i].p3_y);
	}

	viewDist = FixMul(viewDist,FixDiv(FixDiv(max,SIDE_VIEW_FRAC),corner_p[0].p3_z);
	VmVecCopyScale(&view_vec2,&view_vec,viewDist);
	VmVecSub(&gameData.objs.console->position.vPos,&side_center,&view_vec2);

	//RelinkObject(OBJ_IDX (gameData.objs.console), SEG_IDX(Cursegp) );
	//UpdateObjectSeg(gameData.objs.console);		//might have backed right out of curseg

	newseg = FindSegByPoint(&gameData.objs.console->position.vPos, SEG_IDX(Cursegp), 1, 0);
	if (newseg != -1)
		RelinkObject(OBJ_IDX (gameData.objs.console),newseg);

	UpdateFlags |= UF_ED_STATE_CHANGED | UF_GAME_VIEW_CHANGED;
	return 1;
}
Example #4
0
void CShrapnel::Move (void)
{
	fix			xSpeed = FixDiv (m_info.xSpeed, I2X (25) / 1000);
	CFixVector	vOffs;
	time_t		nTicks;

if ((nTicks = gameStates.app.nSDLTicks - m_info.tUpdate) < 25)
	return;
xSpeed = (fix) (xSpeed / gameStates.gameplay.slowmo [0].fSpeed);
for (; nTicks >= 25; nTicks -= 25) {
	if (--(m_info.nTurn))
		vOffs = m_info.vOffs;
	else {
		m_info.nTurn = ((m_info.xTTL > I2X (1) / 2) ? 2 : 4) + d_rand () % 4;
		vOffs = m_info.vDir;
		vOffs [X] = FixMul (vOffs [X], 2 * d_rand ());
		vOffs [Y] = FixMul (vOffs [Y], 2 * d_rand ());
		vOffs [Z] = FixMul (vOffs [Z], 2 * d_rand ());
		CFixVector::Normalize (vOffs);
		m_info.vOffs = vOffs;
		}
	vOffs *= xSpeed;
	m_info.vPos += vOffs;
	}
if (m_info.nSmoke >= 0)
	particleManager.SetPos (m_info.nSmoke, &m_info.vPos, NULL, -1);
m_info.tUpdate = gameStates.app.nSDLTicks - nTicks;
}
Example #5
0
void DigiGetSoundLoc (
	vmsMatrix * mListener, vmsVector * vListenerPos, short nListenerSeg, vmsVector * vSoundPos, 
	short nSoundSeg, fix maxVolume, int *volume, int *pan, fix maxDistance)	
{	  
	vmsVector	vecToSound;
	fix 			angleFromEar, cosang,sinang;
	fix 			distance;
	fix 			pathDistance;

*volume = 0;
*pan = 0;
maxDistance = (5 * maxDistance) / 4;	// Make all sounds travel 1.25 times as far.
//	Warning: Made the VmVecNormalizedDir be VmVecNormalizedDirQuick and got illegal values to acos in the fang computation.
distance = VmVecNormalizedDirQuick (&vecToSound, vSoundPos, vListenerPos);
if (distance < maxDistance) {
	int nSearchSegs = f2i (maxDistance / 20);
	if (nSearchSegs < 1)
		nSearchSegs = 1;
	pathDistance = FindConnectedDistance (vListenerPos, nListenerSeg, vSoundPos, nSoundSeg, nSearchSegs, WID_RENDPAST_FLAG + WID_FLY_FLAG);
	if (pathDistance > -1) {
		*volume = maxVolume - FixDiv (pathDistance, maxDistance);
		if (*volume <= 0) 
			*volume = 0;
		else {
			angleFromEar = VmVecDeltaAngNorm (&mListener->rVec, &vecToSound, &mListener->uVec);
			FixSinCos (angleFromEar, &sinang, &cosang);
			if (gameConfig.bReverseChannels) 
				cosang = -cosang;
			*pan = (cosang + F1_0) / 2;
			}
		}
	}																					  
}
Example #6
0
//------------------------------------------------------------------------------
//performs aspect scaling on global view matrix
void ScaleMatrix (int bOglScale)
{
	viewInfo.view [1] = viewInfo.view [0];		//so we can use unscaled if we want
	viewInfo.viewf [1] = viewInfo.viewf [0];		//so we can use unscaled if we want

viewInfo.scale = viewInfo.windowScale;
if (viewInfo.zoom <= f1_0) 		//xZoom in by scaling z
	viewInfo.scale.p.z = FixMul (viewInfo.scale.p.z, viewInfo.zoom);
else {			//xZoom out by scaling x&y
	fix s = FixDiv (f1_0, viewInfo.zoom);

	viewInfo.scale.p.x = FixMul (viewInfo.scale.p.x, s);
	viewInfo.scale.p.y = FixMul (viewInfo.scale.p.y, s);
	}
//viewInfo.scale.p.x = viewInfo.scale.p.y = viewInfo.scale.p.z = F1_0;
//now scale matrix elements
if (bOglScale)
	//glScalef (f2fl (viewInfo.scale.p.x), f2fl (viewInfo.scale.p.y), -f2fl (viewInfo.scale.p.z));
	glScalef (1, 1, -1);
else {
	//VmVecScale (&viewInfo.view [0].rVec, viewInfo.scale.p.x);
	//VmVecScale (&viewInfo.view [0].uVec, viewInfo.scale.p.y);
	//viewInfo.scale.p.x = viewInfo.scale.p.y = viewInfo.scale.p.z = F1_0;
	VmVecScale (&viewInfo.view [0].fVec, -viewInfo.scale.p.z);
	glScalef (1, 1, 1);
	}
VmsMatToFloat (viewInfo.viewf, viewInfo.view);
}
Example #7
0
//------------------------------------------------------------------------------
//performs aspect scaling on global view matrix
void ScaleMatrix (int bOglScale)
{
	viewInfo.view [1] = viewInfo.view [0];		//so we can use unscaled if we want
	viewInfo.viewf [1] = viewInfo.viewf [0];		//so we can use unscaled if we want

viewInfo.scale = viewInfo.windowScale;
if (viewInfo.zoom <= f1_0) 		//xZoom in by scaling z
	viewInfo.scale[Z] = FixMul (viewInfo.scale[Z], viewInfo.zoom);
else {			//xZoom out by scaling x&y
	fix s = FixDiv (f1_0, viewInfo.zoom);

	viewInfo.scale[X] = FixMul (viewInfo.scale[X], s);
	viewInfo.scale[Y] = FixMul (viewInfo.scale[Y], s);
	}
viewInfo.scalef = viewInfo.scale.ToFloat();
//viewInfo.scale[X] = viewInfo.scale[Y] = viewInfo.scale[Z] = F1_0;
//now scale matrix elements
if (bOglScale) {
	//glScalef (X2F (viewInfo.scale[X]), X2F (viewInfo.scale[Y]), -X2F (viewInfo.scale[Z]));
	glScalef (1, 1, -1);
	}
else {
	//VmVecScale (&viewInfo.view [0].rVec, viewInfo.scale[X]);
	//VmVecScale (&viewInfo.view [0].uVec, viewInfo.scale[Y]);
	//viewInfo.scale[X] = viewInfo.scale[Y] = viewInfo.scale[Z] = F1_0;
	viewInfo.view [0][FVEC] *= (-viewInfo.scale[Z]);
	glScalef (1, 1, 1);
	}
viewInfo.viewf[0] = viewInfo.view[0].ToFloat();
}
Example #8
0
fix ComputeHeadlightLightOnObject (tObject *objP)
{
	int	i;
	fix	light;
	//	Let's just illuminate players and robots for speed reasons, ok?
	if ((objP->nType != OBJ_ROBOT) && (objP->nType	!= OBJ_PLAYER))
		return 0;
	light = 0;
	for (i = 0; i < nHeadLights; i++) {
		fix			dot, dist;
		vmsVector	vecToObj;
		tObject		*lightObjP;
		lightObjP = Headlights [i];
		VmVecSub (&vecToObj, &objP->position.vPos, &lightObjP->position.vPos);
		dist = VmVecNormalize (&vecToObj);
		if (dist > 0) {
			dot = VmVecDot (&lightObjP->position.mOrient.fVec, &vecToObj);
			if (dot < F1_0/2)
				light += FixDiv (HEADLIGHT_SCALE, FixMul (HEADLIGHT_SCALE, dist));	//	Do the normal thing, but darken around headlight.
			else
				light += FixMul (FixMul (dot, dot), HEADLIGHT_SCALE)/8;
		}
	}
	return light;
}
Example #9
0
int FindLineQuadIntersectionSub (CFixVector& intersection, CFixVector *vPlanePoint, CFixVector *vPlaneNorm,
										   CFixVector *p0, CFixVector *p1, fix rad)
{
	CFixVector	d, w;
	double		num, den;

w = *vPlanePoint - *p0;
d = *p1 - *p0;
num = double (CFixVector::Dot (*vPlaneNorm, w) - rad) / 65536.0;
den = double (CFixVector::Dot (*vPlaneNorm, d)) / 65536.0;
if (fabs (den) < 1e-10)
	return 0;
if (fabs (num) > fabs (den))
	return 0;
#if 0
//do check for potential overflow
if (labs (num) / (I2X (1) / 2) >= labs (den))
return 0;
#endif
#if 0
d *= FixDiv (num, den);
intersection = (*p0) + d;
#else
num /= den;
intersection [0] = fix (double ((*p0) [0]) + double (d [0]) * num);
intersection [1] = fix (double ((*p0) [1]) + double (d [1]) * num);
intersection [2] = fix (double ((*p0) [2]) + double (d [2]) * num);
#endif
return 1;
}
Example #10
0
File: gr.cpp Project: paud/d2x-xl
int GrSetMode (u_int32_t mode)
{
	uint w, h;
	//int bForce = (nCurrentVGAMode < 0);

if (mode <= 0)
	return 0;
w = SM_W (mode);
h = SM_H (mode);
nCurrentVGAMode = mode;
screen.Destroy ();
screen.Init ();
screen.SetMode (mode);
screen.SetWidth (w);
screen.SetHeight (h);
//screen.Aspect () = FixDiv(screen.Width ()*3,screen.Height ()*4);
screen.SetAspect (FixDiv (screen.Width (), (fix) (screen.Height () * ((double) w / (double) h))));
screen.Canvas ()->CBitmap::Init (BM_OGL, 0, 0, w, h, 1, NULL);
screen.Canvas ()->CreateBuffer ();
screen.Canvas ()->SetPalette (paletteManager.Default ()); //just need some valid palette here
//screen.Canvas ()->props.rowSize = screen->pitch;
//screen.Canvas ()->Buffer () = reinterpret_cast<ubyte*> (screen->pixels);
CCanvas::SetCurrent (NULL);
CCanvas::Current ()->SetFont (fontManager.Current ());
/***/PrintLog ("   initializing OpenGL window\n");
if (!SdlGlInitWindow (w, h, 0))	//platform specific code
	return 0;
/***/PrintLog ("   initializing OpenGL view port\n");
ogl.Viewport (0, 0, w, h);
/***/PrintLog ("   initializing OpenGL screen mode\n");
ogl.SetScreenMode ();
ogl.GetVerInfo ();
GrUpdate (0);
return 0;
}
Example #11
0
File: rod.c Project: paud/d2x-xl
//------------------------------------------------------------------------------
//compute the corners of a rod.  fills in vertbuf.
int CalcRodCorners (g3sPoint *bot_point, fix bot_width, g3sPoint *top_point, fix top_width)
{
	vmsVector	delta_vec, top, tempv, rod_norm;
	ubyte			codes_and;
	int			i;

//compute vector from one point to other, do cross product with vector
//from eye to get perpendiclar
VmVecSub (&delta_vec, &bot_point->p3_vec, &top_point->p3_vec);
//unscale for aspect
delta_vec.x = FixDiv (delta_vec.x, viewInfo.scale.x);
delta_vec.y = FixDiv (delta_vec.y, viewInfo.scale.y);
//calc perp vector
//do lots of normalizing to prevent overflowing.  When this code works, 
//it should be optimized
VmVecNormalize (&delta_vec);
VmVecCopyNormalize (&top, &top_point->p3_vec);
VmVecCross (&rod_norm, &delta_vec, &top);
VmVecNormalize (&rod_norm);
//scale for aspect
rod_norm.x = FixMul (rod_norm.x, viewInfo.scale.x);
rod_norm.y = FixMul (rod_norm.y, viewInfo.scale.y);
//now we have the usable edge.  generate four points
//top points
VmVecCopyScale (&tempv, &rod_norm, top_width);
tempv.z = 0;
VmVecAdd (&rodPoints [0].p3_vec, &top_point->p3_vec, &tempv);
VmVecSub (&rodPoints [1].p3_vec, &top_point->p3_vec, &tempv);
VmVecCopyScale (&tempv, &rod_norm, bot_width);
tempv.z = 0;
VmVecSub (&rodPoints [2].p3_vec, &bot_point->p3_vec, &tempv);
VmVecAdd (&rodPoints [3].p3_vec, &bot_point->p3_vec, &tempv);

//now code the four points
for (i = 0, codes_and = 0xff; i < 4; i++)
	codes_and &= G3EncodePoint (rodPoints + i);
if (codes_and)
	return 1;		//1 means off screen
//clear flags for new points (not projected)
for (i = 0; i < 4; i++) {
	rodPoints [i].p3Flags = 0;
	rodPoints [i].p3_index = -1;
	}
return 0;
}
Example #12
0
//	----------------------------------------------------------------------
//	General purpose robot-dies-with-death-roll-and-groan code.
//	Return true if CObject just died.
//	scale: I2X (4) for boss, much smaller for much smaller guys
int DoRobotDyingFrame (CObject *objP, fix StartTime, fix xRollDuration, sbyte *bDyingSoundPlaying, short deathSound, fix xExplScale, fix xSoundScale)
{
	fix	xRollVal, temp;
	fix	xSoundDuration;
	CSoundSample *soundP;

if (!xRollDuration)
	xRollDuration = I2X (1)/4;

xRollVal = FixDiv (gameData.time.xGame - StartTime, xRollDuration);

FixSinCos (FixMul (xRollVal, xRollVal), &temp, &objP->mType.physInfo.rotVel[X]);
FixSinCos (xRollVal, &temp, &objP->mType.physInfo.rotVel[Y]);
FixSinCos (xRollVal-I2X (1)/8, &temp, &objP->mType.physInfo.rotVel[Z]);

temp = gameData.time.xGame - StartTime;
objP->mType.physInfo.rotVel[X] = temp / 9;
objP->mType.physInfo.rotVel[Y] = temp / 5;
objP->mType.physInfo.rotVel[Z] = temp / 7;

if (gameOpts->sound.digiSampleRate) {
	soundP = gameData.pig.sound.soundP + audio.XlatSound (deathSound);
	xSoundDuration = FixDiv (soundP->nLength [soundP->bHires], gameOpts->sound.digiSampleRate);
	}
else
	xSoundDuration = I2X (1);

if (StartTime + xRollDuration - xSoundDuration < gameData.time.xGame) {
	if (!*bDyingSoundPlaying) {
#if TRACE
		console.printf (CON_DBG, "Starting death sound!\n");
#endif
		*bDyingSoundPlaying = 1;
		audio.CreateObjectSound (deathSound, SOUNDCLASS_ROBOT, objP->Index (), 0, xSoundScale, xSoundScale * 256);	//	I2X (5)12 means play twice as loud
		}
	else if (d_rand () < gameData.time.xFrame*16)
		CreateSmallFireballOnObject (objP, (I2X (1) + d_rand ()) * (16 * xExplScale/I2X (1)) / 8, 0);
	}
else if (d_rand () < gameData.time.xFrame * 8)
	CreateSmallFireballOnObject (objP, (I2X (1)/2 + d_rand ()) * (16 * xExplScale / I2X (1)) / 8, 1);

return (StartTime + xRollDuration < gameData.time.xGame);
}
Example #13
0
//	----------------------------------------------------------------------
//	General purpose robot-dies-with-death-roll-and-groan code.
//	Return true if tObject just died.
//	scale: F1_0*4 for boss, much smaller for much smaller guys
int DoRobotDyingFrame (tObject *objP, fix StartTime, fix xRollDuration, sbyte *bDyingSoundPlaying, short deathSound, fix xExplScale, fix xSoundScale)
{
	fix	xRollVal, temp;
	fix	xSoundDuration;
	tDigiSound *soundP;

if (!xRollDuration)
	xRollDuration = F1_0/4;

xRollVal = FixDiv (gameData.time.xGame - StartTime, xRollDuration);

FixSinCos (FixMul (xRollVal, xRollVal), &temp, &objP->mType.physInfo.rotVel.p.x);
FixSinCos (xRollVal, &temp, &objP->mType.physInfo.rotVel.p.y);
FixSinCos (xRollVal-F1_0/8, &temp, &objP->mType.physInfo.rotVel.p.z);

temp = gameData.time.xGame - StartTime;
objP->mType.physInfo.rotVel.p.x = temp / 9;
objP->mType.physInfo.rotVel.p.y = temp / 5;
objP->mType.physInfo.rotVel.p.z = temp / 7;

if (gameOpts->sound.digiSampleRate) {
	soundP = gameData.pig.sound.pSounds + DigiXlatSound (deathSound);
	xSoundDuration = FixDiv (soundP->nLength [soundP->bHires], gameOpts->sound.digiSampleRate);
	}
else
	xSoundDuration = F1_0;

if (StartTime + xRollDuration - xSoundDuration < gameData.time.xGame) {
	if (!*bDyingSoundPlaying) {
#if TRACE
		con_printf (CONDBG, "Starting death sound!\n");
#endif
		*bDyingSoundPlaying = 1;
		DigiLinkSoundToObject2 (deathSound, OBJ_IDX (objP), 0, xSoundScale, xSoundScale * 256, SOUNDCLASS_ROBOT);	//	F1_0*512 means play twice as loud
		}
	else if (d_rand () < gameData.time.xFrame*16)
		CreateSmallFireballOnObject (objP, (F1_0 + d_rand ()) * (16 * xExplScale/F1_0) / 8, 0);
	}
else if (d_rand () < gameData.time.xFrame * 8)
	CreateSmallFireballOnObject (objP, (F1_0/2 + d_rand ()) * (16 * xExplScale / F1_0) / 8, 1);

return (StartTime + xRollDuration < gameData.time.xGame);
}
Example #14
0
const CFixMatrix CFixMatrix::Inverse (void) 
{
	fix xDet = Det ();
	CFixMatrix m;

m.m_data.mat [RVEC][X] = FixDiv (FixMul (m_data.mat [UVEC][Y], m_data.mat [FVEC][Z]) - FixMul (m_data.mat [UVEC][Z], m_data.mat [FVEC][Y]), xDet);
m.m_data.mat [RVEC][Y] = FixDiv (FixMul (m_data.mat [RVEC][Z], m_data.mat [FVEC][Y]) - FixMul (m_data.mat [RVEC][Y], m_data.mat [FVEC][Z]), xDet);
m.m_data.mat [RVEC][Z] = FixDiv (FixMul (m_data.mat [RVEC][Y], m_data.mat [UVEC][Z]) - FixMul (m_data.mat [RVEC][Z], m_data.mat [UVEC][Y]), xDet);
m.m_data.mat [UVEC][X] = FixDiv (FixMul (m_data.mat [UVEC][Z], m_data.mat [FVEC][X]) - FixMul (m_data.mat [UVEC][X], m_data.mat [FVEC][Z]), xDet);
m.m_data.mat [UVEC][Y] = FixDiv (FixMul (m_data.mat [RVEC][X], m_data.mat [FVEC][Z]) - FixMul (m_data.mat [RVEC][Z], m_data.mat [FVEC][X]), xDet);
m.m_data.mat [UVEC][Z] = FixDiv (FixMul (m_data.mat [RVEC][Z], m_data.mat [UVEC][X]) - FixMul (m_data.mat [RVEC][X], m_data.mat [UVEC][Z]), xDet);
m.m_data.mat [FVEC][X] = FixDiv (FixMul (m_data.mat [UVEC][X], m_data.mat [FVEC][Y]) - FixMul (m_data.mat [UVEC][Y], m_data.mat [FVEC][X]), xDet);
m.m_data.mat [FVEC][Y] = FixDiv (FixMul (m_data.mat [RVEC][Y], m_data.mat [FVEC][X]) - FixMul (m_data.mat [RVEC][X], m_data.mat [FVEC][Y]), xDet);
m.m_data.mat [FVEC][Z] = FixDiv (FixMul (m_data.mat [RVEC][X], m_data.mat [UVEC][Y]) - FixMul (m_data.mat [RVEC][Y], m_data.mat [UVEC][X]), xDet);
return m;
}
Example #15
0
// --------------------------------------------------------------------------------------------------------------------
//	Lead the CPlayerData, returning point to fire at in vFirePoint.
//	Rules:
//		Player not cloaked
//		Player must be moving at a speed >= MIN_LEAD_SPEED
//		Player not farther away than MAX_LEAD_DISTANCE
//		dot (vector_to_player, player_direction) must be in -LEAD_RANGE,LEAD_RANGE
//		if firing a matter weapon, less leading, based on skill level.
int LeadPlayer (CObject *objP, CFixVector *vFirePoint, CFixVector *vBelievedPlayerPos, int nGuns, CFixVector *vFire)
{
	fix			dot, xPlayerSpeed, xDistToPlayer, xMaxWeaponSpeed, xProjectedTime;
	CFixVector	vPlayerMovementDir, vVecToPlayer;
	int			nWeaponType;
	CWeaponInfo	*wiP;
	tRobotInfo	*botInfoP;

if (LOCALPLAYER.flags & PLAYER_FLAGS_CLOAKED)
	return 0;
vPlayerMovementDir = gameData.objs.consoleP->mType.physInfo.velocity;
xPlayerSpeed = CFixVector::Normalize(vPlayerMovementDir);
if (xPlayerSpeed < MIN_LEAD_SPEED)
	return 0;
vVecToPlayer = *vBelievedPlayerPos - *vFirePoint;
xDistToPlayer = CFixVector::Normalize(vVecToPlayer);
if (xDistToPlayer > MAX_LEAD_DISTANCE)
	return 0;
dot = CFixVector::Dot (vVecToPlayer, vPlayerMovementDir);
if ((dot < -LEAD_RANGE) || (dot > LEAD_RANGE))
	return 0;
//	Looks like it might be worth trying to lead the player.
botInfoP = &ROBOTINFO (objP->info.nId);
nWeaponType = botInfoP->nWeaponType;
if ((nGuns == 0) && (botInfoP->nSecWeaponType != -1))
	nWeaponType = botInfoP->nSecWeaponType;
wiP = gameData.weapons.info + nWeaponType;
xMaxWeaponSpeed = wiP->speed [gameStates.app.nDifficultyLevel];
if (xMaxWeaponSpeed < I2X (1))
	return 0;
//	Matter weapons:
//	At Rookie or Trainee, don't lead at all.
//	At higher skill levels, don't lead as well.  Accomplish this by screwing up xMaxWeaponSpeed.
if (wiP->matter) {
	if (gameStates.app.nDifficultyLevel <= 1)
		return 0;
	else
		xMaxWeaponSpeed *= (NDL-gameStates.app.nDifficultyLevel);
   }
xProjectedTime = FixDiv (xDistToPlayer, xMaxWeaponSpeed);
(*vFire)[X] = ComputeLeadComponent ((*vBelievedPlayerPos)[X], (*vFirePoint)[X], gameData.objs.consoleP->mType.physInfo.velocity[X], xProjectedTime);
(*vFire)[Y] = ComputeLeadComponent ((*vBelievedPlayerPos)[Y], (*vFirePoint)[Y], gameData.objs.consoleP->mType.physInfo.velocity[Y], xProjectedTime);
(*vFire)[Z] = ComputeLeadComponent ((*vBelievedPlayerPos)[Z], (*vFirePoint)[Z], gameData.objs.consoleP->mType.physInfo.velocity[Z], xProjectedTime);
CFixVector::Normalize(*vFire);
Assert (CFixVector::Dot (*vFire, objP->info.position.mOrient.FVec ()) < I2X (3)/2);
//	Make sure not firing at especially strange angle.  If so, try to correct.  If still bad, give up after one try.
if (CFixVector::Dot (*vFire, objP->info.position.mOrient.FVec ()) < I2X (1)/2) {
	*vFire += vVecToPlayer;
	*vFire *= I2X (1)/2;
	if (CFixVector::Dot (*vFire, objP->info.position.mOrient.FVec ()) < I2X (1)/2) {
		return 0;
		}
	}
return 1;
}
Example #16
0
void CObject::CheckAfterburnerBlobDrop (void)
{
if (gameStates.render.bDropAfterburnerBlob) {
	Assert (this == gameData.objs.consoleP);
	DropAfterburnerBlobs (this, 2, I2X (5) / 2, -1, NULL, 0);	//	-1 means use default lifetime
	if (IsMultiGame)
		MultiSendDropBlobs ((char) gameData.multiplayer.nLocalPlayer);
	gameStates.render.bDropAfterburnerBlob = 0;
	}

if ((info.nType == OBJ_WEAPON) && (gameData.weapons.info [info.nId].nAfterburnerSize)) {
	int	nObject, bSmoke;
	fix	vel;
	fix	delay, lifetime, nSize;

#if 1
	if ((info.nType == OBJ_WEAPON) && gameData.objs.bIsMissile [info.nId]) {
		if (SHOW_SMOKE && gameOpts->render.particles.bMissiles)
			return;
		if ((gameStates.app.bNostalgia || EGI_FLAG (bThrusterFlames, 1, 1, 0)) &&
			 (info.nId != MERCURYMSL_ID))
			return;
		}
#endif
	if ((vel = mType.physInfo.velocity.Mag()) > I2X (200))
		delay = I2X (1) / 16;
	else if (vel > I2X (40))
		delay = FixDiv (I2X (13), vel);
	else
		delay = DEG90;

	if ((bSmoke = SHOW_SMOKE && gameOpts->render.particles.bMissiles)) {
		nSize = I2X (3);
		lifetime = I2X (1) / 12;
		delay = 0;
		}
	else {
		nSize = I2X (gameData.weapons.info [info.nId].nAfterburnerSize) / 16;
		lifetime = 3 * delay / 2;
		if (!IsMultiGame) {
			delay /= 2;
			lifetime *= 2;
			}
		}

	nObject = OBJ_IDX (this);
	if (bSmoke ||
		 (gameData.objs.xLastAfterburnerTime [nObject] + delay < gameData.time.xGame) ||
		 (gameData.objs.xLastAfterburnerTime [nObject] > gameData.time.xGame)) {
		DropAfterburnerBlobs (this, 1, nSize, lifetime, NULL, bSmoke);
		gameData.objs.xLastAfterburnerTime [nObject] = gameData.time.xGame;
		}
	}
}
Example #17
0
//	-----------------------------------------------------------------------------
//	Applies an instantaneous whack on an tObject, resulting in an instantaneous
//	change in orientation.
void PhysApplyRot (tObject *objP, vmsVector *vForce)
{
	fix	rate, vecmag;

	if (objP->movementType != MT_PHYSICS)
		return;

	vecmag = VmVecMag (vForce)/8;
	if (vecmag < F1_0/256)
		rate = 4*F1_0;
	else if (vecmag < objP->mType.physInfo.mass >> 14)
		rate = 4*F1_0;
	else {
		rate = FixDiv (objP->mType.physInfo.mass, vecmag);
		if (objP->nType == OBJ_ROBOT) {
			if (rate < F1_0/4)
				rate = F1_0/4;
			//	Changed by mk, 10/24/95, claw guys should not slow down when attacking!
			if (!gameData.bots.pInfo [objP->id].thief && !gameData.bots.pInfo [objP->id].attackType) {
				if (objP->cType.aiInfo.SKIP_AI_COUNT * gameData.time.xFrame < 3*F1_0/4) {
					fix	tval = FixDiv (F1_0, 8*gameData.time.xFrame);
					int	addval;

					addval = f2i (tval);

					if ((d_rand () * 2) < (tval & 0xffff))
						addval++;
					objP->cType.aiInfo.SKIP_AI_COUNT += addval;
				}
			}
		} else {
			if (rate < F1_0/2)
				rate = F1_0/2;
		}
	}

	//	Turn amount inversely proportional to mass.  Third parameter is seconds to do 360 turn.
	physics_turn_towards_vector (vForce, objP, rate);


}
Example #18
0
//------------------------------------------------------------------------------
//compute aspect ratio for this canvas
void CTransformation::ComputeAspect (void)
{
fix s = FixMulDiv (screen.Aspect (), CCanvas::Current ()->Height (), CCanvas::Current ()->Width ());
if (s <= I2X (1)) {	   //scale x
	m_info.aspect [X] = s;
	m_info.aspect [Y] = I2X (1);
	}
else {
	m_info.aspect [Y] = FixDiv (I2X (1), s);
	m_info.aspect [X] = I2X (1);
	}
m_info.aspect [Z] = I2X (1);		//always 1
}
Example #19
0
//	------------------------------------------------------------------------------------------------------
//	Note: This is the old AITurnTowardsVector code.
//	PhysApplyRot used to call AITurnTowardsVector until I fixed it, which broke PhysApplyRot.
void physics_turn_towards_vector (vmsVector *goal_vector, tObject *objP, fix rate)
{
	vmsAngVec	dest_angles, cur_angles;
	fix			delta_p, delta_h;
	vmsVector	*rotvel_ptr = &objP->mType.physInfo.rotVel;

	// Make this tObject turn towards the goal_vector.  Changes orientation, doesn't change direction of movement.
	// If no one moves, will be facing goal_vector in 1 second.

	//	Detect null vector.
	if ((goal_vector->x == 0) && (goal_vector->y == 0) && (goal_vector->z == 0))
		return;

	//	Make morph gameData.objs.objects turn more slowly.
	if (objP->controlType == CT_MORPH)
		rate *= 2;

	VmExtractAnglesVector (&dest_angles, goal_vector);
	VmExtractAnglesVector (&cur_angles, &objP->orient.fVec);

	delta_p = (dest_angles.p - cur_angles.p);
	delta_h = (dest_angles.h - cur_angles.h);

	if (delta_p > F1_0/2) delta_p = dest_angles.p - cur_angles.p - F1_0;
	if (delta_p < -F1_0/2) delta_p = dest_angles.p - cur_angles.p + F1_0;
	if (delta_h > F1_0/2) delta_h = dest_angles.h - cur_angles.h - F1_0;
	if (delta_h < -F1_0/2) delta_h = dest_angles.h - cur_angles.h + F1_0;

	delta_p = FixDiv (delta_p, rate);
	delta_h = FixDiv (delta_h, rate);

	if (abs (delta_p) < F1_0/16) delta_p *= 4;
	if (abs (delta_h) < F1_0/16) delta_h *= 4;

	PhysicsSetRotVelAndSaturate (&rotvel_ptr->x, delta_p);
	PhysicsSetRotVelAndSaturate (&rotvel_ptr->y, delta_h);
	rotvel_ptr->z = 0;
}
Example #20
0
void DigiGetSoundLoc (
	vmsMatrix *mListener, vmsVector *vListenerPos, short nListenerSeg, vmsVector *vSoundPos, 
	short nSoundSeg, fix maxVolume, int *volume, int *pan, fix maxDistance, int nDecay)
{	  
	vmsVector	vecToSound;
	fix 			angleFromEar, cosang, sinang;
	fix			distance, pathDistance;
	float			fDecay;

*volume = 0;
*pan = 0;
if (nDecay)
	maxDistance *= 2;
else
	maxDistance = (5 * maxDistance) / 4;	// Make all sounds travel 1.25 times as far.
distance = VmVecNormalizedDir (&vecToSound, vSoundPos, vListenerPos);
if (distance < maxDistance) {
	int nSearchSegs = f2i (maxDistance / 10);
	if (nSearchSegs < 1)
		nSearchSegs = 1;
	pathDistance = FindConnectedDistance (vListenerPos, nListenerSeg, vSoundPos, nSoundSeg, nSearchSegs, WID_RENDPAST_FLAG | WID_FLY_FLAG, 0);
	if (pathDistance > -1) {
		if (!nDecay) 
			*volume = maxVolume - FixDiv (pathDistance, maxDistance);
		else if (nDecay == 1) { 
			fDecay = (float) exp (-log (2.0f) * 4.0f * f2fl (pathDistance) / f2fl (maxDistance / 2));
			*volume = (int) (maxVolume * fDecay);
			}
		else {
			fDecay = 1.0f - f2fl (pathDistance) / f2fl (maxDistance);
			*volume = (int) (maxVolume * fDecay * fDecay * fDecay);
			}

		if (*volume <= 0) 
			*volume = 0;
		else {
			angleFromEar = VmVecDeltaAngNorm (&mListener->rVec, &vecToSound, &mListener->uVec);
			FixSinCos (angleFromEar, &sinang, &cosang);
			if (gameConfig.bReverseChannels || gameOpts->sound.bHires) 
				cosang = -cosang;
			*pan = (cosang + F1_0) / 2;
			}
		}
	}																					  
}
Example #21
0
void PhysApplyForce (tObject *objP, vmsVector *vForce)
{

	//	Put in by MK on 2/13/96 for force getting applied to Omega blobs, which have 0 mass, 
	//	in collision with crazy reactor robot thing on d2levf-s.
if (objP->mType.physInfo.mass == 0)
	return;
if (objP->movementType != MT_PHYSICS)
	return;
#ifdef TACTILE
  if (TactileStick && obj==&gameData.objs.objects [gameData.multi.players [gameData.multi.nLocalPlayer].nObject])
	Tactile_apply_force (vForce, &objP->orient);
#endif
//Add in acceleration due to force
if (!gameData.objs.speedBoost [OBJ_IDX (objP)].bBoosted || (objP != gameData.objs.console))
	VmVecScaleInc (&objP->mType.physInfo.velocity, 
						vForce, 
						FixDiv (f1_0, objP->mType.physInfo.mass));
}
Example #22
0
File: win32.c Project: paud/d2x-xl
int GrSetMode(int mode)
{
	unsigned int w,h,t,r;

	if (mode == SM_ORIGINAL)
		return 0;

	switch (mode)
	{
	case SM(320,200):
		w = 320; r = 320; h = 200; t=BM_LINEAR;//BM_DIRECTX;;
		break;
	default:
		return 1;
	}

	GrPaletteStepClear();

	memset( grdCurScreen, 0, sizeof(grs_screen);
	grdCurScreen->sc_mode = mode;
	grdCurScreen->sc_w = w;
	grdCurScreen->sc_h = h;
	grdCurScreen->sc_aspect = FixDiv(grdCurScreen->sc_w*3,grdCurScreen->sc_h*4);
	GrInitCanvas(&grdCurScreen->sc_canvas, (unsigned char *)BM_D3D_DISPLAY, t, w, h);
	GrSetCurrentCanvas(NULL);


	if (!(backbuffer = createdib()))
		return 1;

	grdCurScreen->sc_canvas.cv_bitmap.bm_texBuf = backbuffer;
	grdCurScreen->sc_canvas.cv_bitmap.bm_props.type = BM_LINEAR;
	grdCurScreen->sc_canvas.cv_bitmap.bm_props.x = 0;
	grdCurScreen->sc_canvas.cv_bitmap.bm_props.y = 0;
	grdCurScreen->sc_canvas.cv_bitmap.bm_props.w = w;
	grdCurScreen->sc_canvas.cv_bitmap.bm_props.h = h;
	grdCurScreen->sc_canvas.cv_bitmap.bm_props.rowsize = w;
	
	gamefont_choose_game_font(w,h);
	
	return 0;
}
Example #23
0
void RenderFastShadows (fix nEyeOffset, int nWindow, short nStartSeg)
{
#if 0//OOF_TEST_CUBE
#	if 1
for (bShadowTest = 1; bShadowTest >= 0; bShadowTest--) 
#	else
for (bShadowTest = 0; bShadowTest < 2; bShadowTest++) 
#	endif
#endif
	{
	gameStates.render.nShadowPass = 2;
	OglStartFrame (0, 0);
	gameData.render.shadows.nFrame = !gameData.render.shadows.nFrame;
	//RenderObjectShadows ();
	RenderMine (nStartSeg, nEyeOffset, nWindow);
	}
#if DBG
if (!bShadowTest) 
#endif
	{
	gameStates.render.nShadowPass = 3;
	OglStartFrame (0, 0);
	if	(gameStates.render.bShadowMaps) {
#if DBG
		if (gameStates.render.bExternalView)
#else	
		if (gameStates.render.bExternalView && (!IsMultiGame || IsCoopGame || EGI_FLAG (bEnableCheats, 0, 0, 0)))
#endif			 
			G3SetViewMatrix(gameData.render.mine.viewerEye, externalView.pPos ? externalView.pPos->mOrient : 
								  gameData.objs.viewerP->info.position.mOrient, gameStates.render.xZoom, 1);
		else
			G3SetViewMatrix(gameData.render.mine.viewerEye, gameData.objs.viewerP->info.position.mOrient, 
								  FixDiv (gameStates.render.xZoom, gameStates.render.nZoomFactor), 1);
		ApplyShadowMaps (nStartSeg, nEyeOffset, nWindow);
		}
	else {
		RenderShadowQuad (0);
		}
	}
}
Example #24
0
void BuildTerrainLightMap ()
{
	int i, j;
	fix l, l2, lMin = 0x7fffffff, lMax = 0;


if (gameData.render.terrain.pLightMap)
	D2_FREE (gameData.render.terrain.pLightMap)
else
	atexit (FreeTerrainLightMap);		//first time

gameData.render.terrain.pPoints = (vmsVector *) D2_ALLOC (GRID_SIZE * sizeof (vmsVector));
gameData.render.terrain.pLightMap = (fix *) D2_ALLOC (GRID_SIZE * sizeof (fix));
ComputeTerrainPoints ();
for (i = 0; i < gameData.render.terrain.nGridW; i++) {
	for (j = 0; j < gameData.render.terrain.nGridH; j++) {
		l = GetAvgTerrainLight (i, j);
		if (l > lMax)
			lMax = l;
		if (l < lMin)
			lMin = l;
		if (lMin < 0)
			l = GetAvgTerrainLight (i, j);
		}
	}
for (i = 0; i < gameData.render.terrain.nGridW; i++) {
	for (j = 0; j < gameData.render.terrain.nGridH; j++) {
		l = GetAvgTerrainLight (i, j);
		if (lMin == lMax)
			LIGHT (i, j) = l;// >> 8;
		else {
			l2 = FixDiv ((l - lMin), (lMax - lMin));
			if (l2 == f1_0)
				l2--;
			LIGHT (i, j) = l2;// >> 8;
			}
		}
	}
D2_FREE (gameData.render.terrain.pPoints);
}
Example #25
0
void BuildTerrainLightmap ()
{
    int i, j;
    fix l, l2, lMin = 0x7fffffff, lMax = 0;


    if (gameData.render.terrain.lightmap.Buffer ())
        gameData.render.terrain.lightmap.Destroy ();
    else
        atexit (FreeTerrainLightmap);		//first time

    gameData.render.terrain.points.Create (GRID_SIZE);
    gameData.render.terrain.lightmap.Create (GRID_SIZE);
    ComputeTerrainPoints ();
    for (i = 0; i < gameData.render.terrain.nGridW; i++) {
        for (j = 0; j < gameData.render.terrain.nGridH; j++) {
            l = GetAvgTerrainLight (i, j);
            if (l > lMax)
                lMax = l;
            if (l < lMin)
                lMin = l;
            if (lMin < 0)
                l = GetAvgTerrainLight (i, j);
        }
    }
    for (i = 0; i < gameData.render.terrain.nGridW; i++) {
        for (j = 0; j < gameData.render.terrain.nGridH; j++) {
            l = GetAvgTerrainLight (i, j);
            if (lMin == lMax)
                LIGHT (i, j) = l;// >> 8;
            else {
                l2 = FixDiv ((l - lMin), (lMax - lMin));
                if (l2 == I2X (1))
                    l2--;
                LIGHT (i, j) = l2;// >> 8;
            }
        }
    }
    gameData.render.terrain.points.Destroy ();
}
Example #26
0
void DigiGetSoundLoc (
	vms_matrix * listener, vms_vector * listener_pos, short listener_seg, vms_vector * sound_pos, 
	short sound_seg, fix max_volume, int *volume, int *pan, fix max_distance)	
{	  

	vms_vector	vector_to_sound;
	fix angle_from_ear, cosang,sinang;
	fix distance;
	fix path_distance;

	*volume = 0;
	*pan = 0;

	max_distance = (max_distance*5)/4;		// Make all sounds travel 1.25 times as far.

	//	Warning: Made the VmVecNormalizedDir be VmVecNormalizedDirQuick and got illegal values to acos in the fang computation.
	distance = VmVecNormalizedDirQuick (&vector_to_sound, sound_pos, listener_pos);
		
	if (distance < max_distance)	{
		int num_search_segs = f2i (max_distance/20);
		if (num_search_segs < 1) num_search_segs = 1;

		path_distance = FindConnectedDistance (listener_pos, listener_seg, sound_pos, sound_seg, num_search_segs, WID_RENDPAST_FLAG+WID_FLY_FLAG);
		if (path_distance > -1)	{
			*volume = max_volume - FixDiv (path_distance,max_distance);
			////mprintf ((0, "Sound path distance %.2f, volume is %d / %d\n", f2fl (distance), *volume, max_volume));
			if (*volume > 0)	{
				angle_from_ear = VmVecDeltaAngNorm (&listener->rvec,&vector_to_sound,&listener->uvec);
				fix_sincos (angle_from_ear,&sinang,&cosang);
				////mprintf ((0, "volume is %.2f\n", f2fl (*volume)));
				if (gameConfig.bReverseChannels) cosang *= -1;
				*pan = (cosang + F1_0)/2;
			} else {
				*volume = 0;
			}
		}
	}																					  

}
Example #27
0
// --------------------------------------------------------------------------------------------------------------------
//	Note: Parameter gameData.ai.vVecToPlayer is only passed now because guns which aren't on the forward vector from the
//	center of the robot will not fire right at the player.  We need to aim the guns at the player.  Barring that, we cheat.
//	When this routine is complete, the parameter gameData.ai.vVecToPlayer should not be necessary.
void AIFireLaserAtPlayer (CObject *objP, CFixVector *vFirePoint, int nGun, CFixVector *vBelievedPlayerPos)
{
	short				nShot, nObject = objP->Index ();
	tAILocalInfo	*ailP = gameData.ai.localInfo + nObject;
	tRobotInfo		*botInfoP = &ROBOTINFO (objP->info.nId);
	CFixVector		vFire;
	CFixVector		bpp_diff;
	short				nWeaponType;
	fix				aim, dot;
	int				count, i;

Assert (nObject >= 0);
//	If this robot is only awake because a camera woke it up, don't fire.
if (objP->cType.aiInfo.SUB_FLAGS & SUB_FLAGS_CAMERA_AWAKE)
	return;
if (!gameStates.app.cheats.bRobotsFiring)
	return;
if (objP->info.controlType == CT_MORPH)
	return;
//	If player is exploded, stop firing.
if (gameStates.app.bPlayerExploded)
	return;
if (objP->cType.aiInfo.xDyingStartTime)
	return;		//	No firing while in death roll.
//	Don't let the boss fire while in death roll.  Sorry, this is the easiest way to do this.
//	If you try to key the boss off objP->cType.aiInfo.xDyingStartTime, it will hose the endlevel stuff.
if (ROBOTINFO (objP->info.nId).bossFlag) {
	i = gameData.bosses.Find (nObject);
	if ((i < 0) || (gameData.bosses [i].m_nDyingStartTime))
		return;
	}
//	If CPlayerData is cloaked, maybe don't fire based on how long cloaked and randomness.
if (LOCALPLAYER.flags & PLAYER_FLAGS_CLOAKED) {
	fix	xCloakTime = gameData.ai.cloakInfo [nObject % MAX_AI_CLOAK_INFO].lastTime;
	if ((gameData.time.xGame - xCloakTime > CLOAK_TIME_MAX/4) &&
		 (d_rand () > FixDiv (gameData.time.xGame - xCloakTime, CLOAK_TIME_MAX)/2)) {
		SetNextFireTime (objP, ailP, botInfoP, nGun);
		return;
		}
	}
//	Handle problem of a robot firing through a CWall because its gun tip is on the other
//	CSide of the CWall than the robot's center.  For speed reasons, we normally only compute
//	the vector from the gun point to the player.  But we need to know whether the gun point
//	is separated from the robot's center by a CWall.  If so, don't fire!
if (objP->cType.aiInfo.SUB_FLAGS & SUB_FLAGS_GUNSEG) {
	//	Well, the gun point is in a different CSegment than the robot's center.
	//	This is almost always ok, but it is not ok if something solid is in between.
	int	nGunSeg = FindSegByPos (*vFirePoint, objP->info.nSegment, 1, 0);
	//	See if these segments are connected, which should almost always be the case.
	short nConnSide = SEGMENTS [nGunSeg].ConnectedSide (&SEGMENTS [objP->info.nSegment]);
	if (nConnSide != -1) {
		//	They are connected via nConnSide in CSegment objP->info.nSegment.
		//	See if they are unobstructed.
		if (!(SEGMENTS [objP->info.nSegment].IsDoorWay (nConnSide, NULL) & WID_FLY_FLAG)) {
			//	Can't fly through, so don't let this bot fire through!
			return;
			}
		}
	else {
		//	Well, they are not directly connected, so use FindVectorIntersection to see if they are unobstructed.
		tFVIQuery	fq;
		tFVIData		hit_data;
		int			fate;

		fq.startSeg			= objP->info.nSegment;
		fq.p0					= &objP->info.position.vPos;
		fq.p1					= vFirePoint;
		fq.radP0				=
		fq.radP1				= 0;
		fq.thisObjNum		= objP->Index ();
		fq.ignoreObjList	= NULL;
		fq.flags				= FQ_TRANSWALL;

		fate = FindVectorIntersection (&fq, &hit_data);
		if (fate != HIT_NONE) {
			Int3 ();		//	This bot's gun is poking through a CWall, so don't fire.
			MoveTowardsSegmentCenter (objP);		//	And decrease chances it will happen again.
			return;
			}
		}
	}
//	Set position to fire at based on difficulty level and robot's aiming ability
aim = I2X (FIRE_K) - (FIRE_K-1)* (botInfoP->aim << 8);	//	I2X (1) in bitmaps.tbl = same as used to be.  Worst is 50% more error.
//	Robots aim more poorly during seismic disturbance.
if (gameStates.gameplay.seismic.nMagnitude) {
	fix temp = I2X (1) - abs (gameStates.gameplay.seismic.nMagnitude);
	if (temp < I2X (1)/2)
		temp = I2X (1)/2;
	aim = FixMul (aim, temp);
	}
//	Lead the CPlayerData half the time.
//	Note that when leading the CPlayerData, aim is perfect.  This is probably acceptable since leading is so hacked in.
//	Problem is all robots will lead equally badly.
if (d_rand () < 16384) {
	if (LeadPlayer (objP, vFirePoint, vBelievedPlayerPos, nGun, &vFire))		//	Stuff direction to fire at in vFirePoint.
		goto player_led;
}

dot = 0;
count = 0;			//	Don't want to sit in this loop foreverd:\temp\dm_test.
i = (NDL - gameStates.app.nDifficultyLevel - 1) * 4;
while ((count < 4) && (dot < I2X (1)/4)) {
	bpp_diff[X] = (*vBelievedPlayerPos)[X] + FixMul ((d_rand ()-16384) * i, aim);
	bpp_diff[Y] = (*vBelievedPlayerPos)[Y] + FixMul ((d_rand ()-16384) * i, aim);
	bpp_diff[Z] = (*vBelievedPlayerPos)[Z] + FixMul ((d_rand ()-16384) * i, aim);
	CFixVector::NormalizedDir(vFire, bpp_diff, *vFirePoint);
	dot = CFixVector::Dot (objP->info.position.mOrient.FVec (), vFire);
	count++;
	}

player_led:

nWeaponType = botInfoP->nWeaponType;
if ((botInfoP->nSecWeaponType != -1) && ((nWeaponType < 0) || !nGun))
	nWeaponType = botInfoP->nSecWeaponType;
if (nWeaponType < 0)
	return;
if (0 > (nShot = CreateNewLaserEasy (&vFire, vFirePoint, objP->Index (), (ubyte) nWeaponType, 1)))
	return;

lightClusterManager.AddForAI (objP, nObject, nShot);
objP->Shots ().nObject = nShot;
objP->Shots ().nSignature = OBJECTS [nShot].info.nSignature;

if (IsMultiGame) {
	AIMultiSendRobotPos (nObject, -1);
	MultiSendRobotFire (nObject, objP->cType.aiInfo.CURRENT_GUN, &vFire);
	}
#if 1
if (++(objP->cType.aiInfo.CURRENT_GUN) >= botInfoP->nGuns) {
	if ((botInfoP->nGuns == 1) || (botInfoP->nSecWeaponType == -1))
		objP->cType.aiInfo.CURRENT_GUN = 0;
	else
		objP->cType.aiInfo.CURRENT_GUN = 1;
	}
#endif
CreateAwarenessEvent (objP, PA_NEARBY_ROBOT_FIRED);
SetNextFireTime (objP, ailP, botInfoP, nGun);
}
Example #28
0
void ReadFlyingControls (CObject *objP)
{
	fix		forwardThrustTime;
	CObject*	gmObjP;
	int		bMulti;

if (gameData.time.xFrame <= 0)
	return;

if (gameStates.app.bPlayerIsDead || gameStates.app.bEnterGame) {
	StopPlayerMovement ();
	FlushInput ();
/*
	VmVecZero(&objP->mType.physInfo.rotThrust);
	VmVecZero(&objP->mType.physInfo.thrust);
	VmVecZero(&objP->mType.physInfo.velocity);
*/
	gameStates.app.bEnterGame--;
	return;
	}

if ((objP->info.nType != OBJ_PLAYER) || (objP->info.nId != gameData.multiplayer.nLocalPlayer))
	return;	//references to CPlayerShip require that this obj be the CPlayerData

tGuidedMissileInfo *gmiP = gameData.objs.guidedMissile + gameData.multiplayer.nLocalPlayer;
gmObjP = gmiP->objP;
if (gmObjP && (gmObjP->info.nSignature == gmiP->nSignature)) {
	CAngleVector	vRotAngs;
	CFixMatrix		mRot, mOrient;
	fix				speed;

	//this is a horrible hack.  guided missile stuff should not be
	//handled in the middle of a routine that is dealing with the CPlayerData
	objP->mType.physInfo.rotThrust.SetZero ();
	vRotAngs [PA] = Controls [0].pitchTime / 2 + gameStates.gameplay.seismic.nMagnitude / 64;
	vRotAngs [BA] = Controls [0].bankTime / 2 + gameStates.gameplay.seismic.nMagnitude / 16;
	vRotAngs [HA] = Controls [0].headingTime / 2 + gameStates.gameplay.seismic.nMagnitude / 64;
	mRot = CFixMatrix::Create (vRotAngs);
	mOrient = gmObjP->info.position.mOrient * mRot;
	gmObjP->info.position.mOrient = mOrient;
	speed = WI_speed (gmObjP->info.nId, gameStates.app.nDifficultyLevel);
	gmObjP->mType.physInfo.velocity = gmObjP->info.position.mOrient.FVec () * speed;
	if(IsMultiGame)
		MultiSendGuidedInfo (gmObjP, 0);
	}
else {
#if DBG
	if (Controls [0].headingTime)
		Controls [0].headingTime = Controls [0].headingTime;
#endif
	objP->mType.physInfo.rotThrust = CFixVector::Create (Controls [0].pitchTime,
	                                                     Controls [0].headingTime, //Controls [0].headingTime ? I2X (1) / 4 : 0; //Controls [0].headingTime;
	                                                     Controls [0].bankTime);
	}
forwardThrustTime = Controls [0].forwardThrustTime;
if ((LOCALPLAYER.flags & PLAYER_FLAGS_AFTERBURNER) && (d_rand () < OBJECTS [gameData.multiplayer.nLocalPlayer].DriveDamage ())) {
	if (Controls [0].afterburnerState) {			//CPlayerData has key down
		fix afterburner_scale;
		int oldCount,newCount;

		//add in value from 0..1
		afterburner_scale = I2X (1) + min (I2X (1) / 2, gameData.physics.xAfterburnerCharge) * 2;
		forwardThrustTime = FixMul (gameData.time.xFrame, afterburner_scale);	//based on full thrust
		oldCount = (gameData.physics.xAfterburnerCharge / (DROP_DELTA_TIME / AFTERBURNER_USE_SECS));
		if (!gameStates.gameplay.bAfterburnerCheat)
			gameData.physics.xAfterburnerCharge -= gameData.time.xFrame / AFTERBURNER_USE_SECS;
		if (gameData.physics.xAfterburnerCharge < 0)
			gameData.physics.xAfterburnerCharge = 0;
		newCount = (gameData.physics.xAfterburnerCharge / (DROP_DELTA_TIME / AFTERBURNER_USE_SECS));
		if (gameStates.app.bNostalgia && (oldCount != newCount))
			gameStates.render.bDropAfterburnerBlob = 1;	//drop blob (after physics called)
		}
	else {
		fix xChargeUp = min (gameData.time.xFrame / 8, I2X (1) - gameData.physics.xAfterburnerCharge);	//recharge over 8 seconds
		if (xChargeUp > 0) {
			fix xCurEnergy = LOCALPLAYER.energy - I2X (10);
			xCurEnergy = max (xCurEnergy, 0) / 10;	//don't drop below 10
			if (xCurEnergy > 0) {	//maybe limit charge up by energy
				xChargeUp = min (xChargeUp, xCurEnergy / 10);
				if (xChargeUp > 0) {
					gameData.physics.xAfterburnerCharge += xChargeUp;
					LOCALPLAYER.energy -= xChargeUp * 100 / 10;	//full charge uses 10% of energy
					}
				}
			}
		}
	}
// Set CObject's thrust vector for forward/backward
objP->mType.physInfo.thrust = objP->info.position.mOrient.FVec () * forwardThrustTime;
// slide left/right
objP->mType.physInfo.thrust += objP->info.position.mOrient.RVec () * Controls [0].sidewaysThrustTime;
// slide up/down
objP->mType.physInfo.thrust += objP->info.position.mOrient.UVec () * Controls [0].verticalThrustTime;
objP->mType.physInfo.thrust *= 2 * objP->DriveDamage ();
if (!gameStates.input.bSkipControls)
	memcpy (&gameData.physics.playerThrust, &objP->mType.physInfo.thrust, sizeof (gameData.physics.playerThrust));
bMulti = IsMultiGame;
if ((objP->mType.physInfo.flags & PF_WIGGLE) && !gameData.objs.speedBoost [objP->Index ()].bBoosted) {
#if 1//!DBG
	WiggleObject (objP);
#endif
	}
	// As of now, objP->mType.physInfo.thrust & objP->mType.physInfo.rotThrust are
	// in units of time... In other words, if thrust==gameData.time.xFrame, that
	// means that the user was holding down the MaxThrust key for the
	// whole frame.  So we just scale them up by the max, and divide by
	// gameData.time.xFrame to make them independant of framerate

	//	Prevent divide overflows on high frame rates.
	//	In a signed divide, you get an overflow if num >= div<<15
fix	ft = gameData.time.xFrame;

//	Note, you must check for ft < I2X (1)/2, else you can get an overflow  on the << 15.
if ((ft < I2X (1)/2) && ((ft << 15) <= gameData.pig.ship.player->maxThrust))
	ft = (gameData.pig.ship.player->maxThrust >> 15) + 1;
objP->mType.physInfo.thrust *= FixDiv (gameData.pig.ship.player->maxThrust, ft);
if ((ft < I2X (1)/2) && ((ft << 15) <= gameData.pig.ship.player->maxRotThrust))
	ft = (gameData.pig.ship.player->maxThrust >> 15) + 1;
objP->mType.physInfo.rotThrust *= FixDiv (gameData.pig.ship.player->maxRotThrust, ft);
}
Example #29
0
// --------------------------------------------------------------------------------------------------------------------
//	Computes point at which projectile fired by robot can hit CPlayerData given positions, CPlayerData vel, elapsed time
inline fix ComputeLeadComponent (fix player_pos, fix robot_pos, fix player_vel, fix elapsedTime)
{
return FixDiv (player_pos - robot_pos, elapsedTime) + player_vel;
}
Example #30
0
int GetCloakInfo (CObject *objP, fix xCloakStartTime, fix xCloakEndTime, tCloakInfo *ciP)
{
	tCloakInfo	ci = {0, CLOAKED_FADE_LEVEL, I2X (1), I2X (1), I2X (1), 0, 0};
	int			i;

if (!(xCloakStartTime || xCloakEndTime)) {
	if (objP->info.nType == OBJ_PLAYER) {
		xCloakStartTime = gameData.multiplayer.players [objP->info.nId].cloakTime;
		xCloakEndTime = gameData.multiplayer.players [objP->info.nId].cloakTime + CLOAK_TIME_MAX;
		}
	else if (objP->info.nType == OBJ_ROBOT) {
		if (!ROBOTINFO (objP->info.nId).bossFlag) {
			xCloakStartTime = gameData.time.xGame - I2X (10);
			xCloakEndTime = gameData.time.xGame + I2X (10);
			}
		else if (0 <= (i = gameData.bosses.Find (objP->Index ()))) {
			xCloakStartTime = gameData.bosses [i].m_nCloakStartTime;
			xCloakEndTime = gameData.bosses [i].m_nCloakEndTime;
			}
		}
	}
if (xCloakStartTime != 0x7fffffff)
	ci.xTotalTime = xCloakEndTime - xCloakStartTime;
else
	ci.xTotalTime = gameData.time.xGame;
if (objP->info.nType == OBJ_PLAYER) {
	ci.xFadeinDuration = CLOAK_FADEIN_DURATION_PLAYER;
	ci.xFadeoutDuration = CLOAK_FADEOUT_DURATION_PLAYER;
	}
else if (objP->info.nType == OBJ_ROBOT) {
	ci.xFadeinDuration = CLOAK_FADEIN_DURATION_ROBOT;
	ci.xFadeoutDuration = CLOAK_FADEOUT_DURATION_ROBOT;
	}
else
	return 0;

ci.xDeltaTime = gameData.time.xGame - ((xCloakStartTime == 0x7fffffff) ? 0 : xCloakStartTime);
#if 0
if (ci.xDeltaTime < ci.xFadeinDuration) {	// make object transparent during second half
	ci.nFadeValue = X2I (FixDiv (ci.xFadeinDuration - ci.xDeltaTime, ci.xFadeinDuration) * CLOAKED_FADE_LEVEL);
	ci.bFading = 1;
	}
#else
// only decrease light during first half of cloak initiation time
if (ci.xDeltaTime < ci.xFadeinDuration / 2) {
	ci.xLightScale = FixDiv (ci.xFadeinDuration / 2 - ci.xDeltaTime, ci.xFadeinDuration / 2);
	ci.bFading = -1;
	}
else if (ci.xDeltaTime < ci.xFadeinDuration) {	// make object transparent during second half
	ci.nFadeValue = X2I (FixDiv (ci.xDeltaTime - ci.xFadeinDuration / 2, ci.xFadeinDuration / 2) * CLOAKED_FADE_LEVEL);
	ci.bFading = 1;
	}
#endif
else if ((xCloakStartTime == 0x7fffffff) || (gameData.time.xGame < xCloakEndTime - ci.xFadeoutDuration)) {
	static int nCloakDelta = 0, nCloakDir = 1;
	static fix xCloakTimer = 0;

	//note, if more than one cloaked CObject is visible at once, the
	//pulse rate will change!
	xCloakTimer -= gameData.time.xFrame;
	while (xCloakTimer < 0) {
		xCloakTimer += ci.xFadeoutDuration / 12;
		nCloakDelta += nCloakDir;
		if (nCloakDelta == 0 || nCloakDelta == 4)
			nCloakDir = -nCloakDir;
		}
	ci.nFadeValue = CLOAKED_FADE_LEVEL - nCloakDelta;
	}
else if (gameData.time.xGame < xCloakEndTime - ci.xFadeoutDuration / 2) {
	ci.nFadeValue = X2I (FixDiv (ci.xTotalTime - ci.xFadeoutDuration / 2 - ci.xDeltaTime, ci.xFadeoutDuration / 2) * CLOAKED_FADE_LEVEL);
	ci.bFading = -1;
	}
else {
	ci.xLightScale = (fix) ((float) (ci.xFadeoutDuration / 2 - (ci.xTotalTime - ci.xDeltaTime) / (float) (ci.xFadeoutDuration / 2)));
	ci.bFading = 1;
	}
if (ciP)
	*ciP = ci;
return ci.bFading;
}