int G3BuildModelFromOOF (tObject *objP, int nModel) { tOOFObject *po = gameData.models.modelToOOF [1][nModel]; tG3Model *pm; if (!po) { po = gameData.models.modelToOOF [0][nModel]; if (!po) return 0; } #ifdef _DEBUG HUDMessage (0, "optimizing model"); #endif PrintLog (" optimizing OOF model %d\n", nModel); pm = gameData.models.g3Models [1] + nModel; G3CountOOFModelItems (po, pm); if (!G3AllocModel (pm)) return 0; G3GetOOFModelItems (nModel, po, pm, /*((nModel == 108) || (nModel == 110)) ? 0.805f :*/ 1.0f); pm->pTextures = po->textures.pBitmaps; memset (pm->teamTextures, 0xFF, sizeof (pm->teamTextures)); gameData.models.polyModels [nModel].rad = G3ModelSize (objP, pm, nModel, 1); G3SetupModel (pm, 1, 1); #if 1 G3SetGunPoints (objP, pm, nModel, 0); #endif return -1; }
int G3BuildModelFromPOF (tObject *objP, int nModel, tPolyModel *pp, grsBitmap **modelBitmaps, tRgbaColorf *pObjColor) { tG3Model *pm = gameData.models.g3Models [0] + nModel; if (!pp->modelData) return 0; pm->nSubModels = 1; #if DBG HUDMessage (0, "optimizing model"); if (nModel == nDbgModel) nDbgModel = nDbgModel; #endif PrintLog (" optimizing POF model %d\n", nModel); if (!G3CountPOFModelItems (pp->modelData, &pm->nSubModels, &pm->nVerts, &pm->nFaces, &pm->nFaceVerts)) return 0; if (!G3AllocModel (pm)) return 0; G3InitSubModelMinMax (pm->pSubModels); #if TRACE_TAGS PrintLog ("building model for object type %d, id %d\n", objP->info.nType, objP->info.nId); #endif if (!G3GetPOFModelItems (pp->modelData, NULL, pm, 0, -1, 1, modelBitmaps, pObjColor)) return 0; G3SortModelFaces (pm->pFaces, 0, pm->nFaces - 1); G3AssignModelFaces (pm); memset (pm->teamTextures, 0xFF, sizeof (pm->teamTextures)); pm->nType = pp->nType; gameData.models.polyModels [nModel].rad = G3ModelSize (objP, pm, nModel, 0); G3SetupModel (pm, 0, 1); pm->iSubModel = 0; return -1; }
int CmpNetPlayers (char *callsign1, char *callsign2, tNetworkInfo *network1, tNetworkInfo *network2) { if ((gameStates.multi.nGameType == IPX_GAME) || ((gameStates.multi.nGameType == UDP_GAME) && gameStates.multi.bCheckPorts)) { if (memcmp (network1, network2, sizeof (tNetworkInfo))) return 1; } else if (gameStates.multi.nGameType == UDP_GAME) { if (memcmp (network1, network2, extraGameInfo [1].bCheckUDPPort ? sizeof (tNetworkInfo) : sizeof (tNetworkInfo) - 2)) //bCheck the port too return 1; } #ifdef MACINTOSH else { if (network1->appletalk.node != network2->appletalk.node) return 1; if (network1->appletalk.net == network2->appletalk.net) return 1; } #endif if (callsign1 && callsign2 && stricmp (callsign1, callsign2)) return 1; #ifdef _DEBUG HUDMessage (0, "'%s' not recognized", callsign1); #endif return 0; }
int ToggleChaseCam (void) { #if !DBG if (IsMultiGame && !IsCoopGame && (!EGI_FLAG (bEnableCheats, 0, 0, 0) || COMPETITION)) { HUDMessage (0, "Chase camera is not available"); return 0; } #endif return SetChaseCam (!gameStates.render.bChaseCam); }
int ToggleFreeCam (void) { #if !DBG if ((IsMultiGame && !(IsCoopGame || EGI_FLAG (bEnableCheats, 0, 0, 0)))) { HUDMessage (0, "Free camera is not available"); return 0; } #endif return SetFreeCam (!gameStates.render.bFreeCam); }
inline int DeltaAxis (int v) { #if DBG int a = gameOpts->input.joystick.bLinearSens ? joyAxis [v] * 16 / joy_sens_mod [v % 4] : joyAxis [v]; if (a) HUDMessage (0, "%d", a); return a; #else return gameOpts->input.joystick.bLinearSens ? joyAxis [v] * 16 / joy_sens_mod [v % 4] : joyAxis [v]; #endif }
int GrToggleFullScreenGame (void) { static char szFullscreen [2][30] = {"toggling fullscreen mode off", "toggling fullscreen mode on"}; int i = GrToggleFullScreen (); FlushInput (); if (gameStates.app.bGameRunning) { HUDMessage (MSGC_GAME_FEEDBACK, szFullscreen [i]); StopPlayerMovement (); } return i; }
int NetworkBadPacketSize (int nLength, int nExpectedLength, const char *pszId) { if (!nExpectedLength || (nLength == nExpectedLength)) return 0; console.printf (CON_DBG, "WARNING! Received invalid size for %s\n", pszId); PrintLog ("Networking: Bad size for %s\n", pszId); #if DBG HUDMessage (0, "invalid %s", pszId); #endif if (nLength == nExpectedLength - 4) PrintLog (" (Probably due to mismatched UDP/IP connection quality improvement settings)\n"); return 1; }
int ControlsReadTrackIR (void) { viewInfo.bUsePlayerHeadAngles = 0; if (!(gameStates.input.bHaveTrackIR && gameOpts->input.trackIR.bUse)) return 0; if (!pfnTIRQuery (&tirInfo)) { pfnTIRExit (); if ((gameStates.input.bHaveTrackIR = pfnTIRInit ((HWND) SDL_GetWindowHandle ()))) pfnTIRStart (); return 0; } #if 0//def _DEBUG HUDMessage (0, "%1.0f %1.0f %1.0f", tirInfo.fvTrans.x, tirInfo.fvTrans.y, tirInfo.fvTrans.z); #endif return 1; }
void UnstickObject (tObject *objP) { fvi_info hi; fvi_query fq; int fate; short nSegment; fix xSideDist, xSideDists [6]; if ((objP->nType == OBJ_PLAYER) && (objP->id == gameData.multi.nLocalPlayer) && (gameStates.app.cheats.bPhysics == 0xBADA55)) return; fq.p0 = fq.p1 = &objP->pos; fq.startSeg = objP->nSegment; fq.rad = objP->size; fq.thisObjNum = OBJ_IDX (objP); fq.ignoreObjList = NULL; fq.flags = 0; fate = FindVectorIntersection (&fq, &hi); if (fate != HIT_WALL) return; GetSideDistsAll (&objP->pos, hi.hit.nSideSegment, xSideDists); if ((xSideDist = xSideDists [hi.hit.nSide]) && (xSideDist < objP->size - objP->size / 100)) { #if 1 float r = 0.25f; #else float r; xSideDist = objP->size - xSideDist; r = ((float) xSideDist / (float) objP->size) * f2fl (objP->size); #endif objP->pos.x += (fix) ((float) hi.hit.vNormal.x * r); objP->pos.y += (fix) ((float) hi.hit.vNormal.y * r); objP->pos.z += (fix) ((float) hi.hit.vNormal.z * r); nSegment = FindSegByPoint (&objP->pos, objP->nSegment); if (nSegment != objP->nSegment) RelinkObject (OBJ_IDX (objP), nSegment); #if 0//def _DEBUG if (objP->nType == OBJ_PLAYER) HUDMessage (0, "PENETRATING WALL (%d, %1.4f)", objP->size - xSideDists [nWallHitSide], r); #endif } }
void DoSlowMotionFrame (void) { int i, bMsg; float f, h; if (gameStates.app.bNostalgia || IsMultiGame) return; bMsg = ToggleSlowMotion (); f = (float) gameOpts->gameplay.nSlowMotionSpeedup / 2; h = (f - 1) / (SLOWDOWN_SECS * SLOWDOWN_FPS); for (i = 0; i < 2; i++) { if (gameStates.gameplay.slowmo [i].nState && (gameStates.app.nSDLTicks - gameStates.gameplay.slowmo [i].tUpdate > 25)) { gameStates.gameplay.slowmo [i].fSpeed += gameStates.gameplay.slowmo [i].nState * h; if (gameStates.gameplay.slowmo [i].fSpeed >= f) { gameStates.gameplay.slowmo [i].fSpeed = f; gameStates.gameplay.slowmo [i].nState = 0; if (!i) SlowdownSound (); } else if (gameStates.gameplay.slowmo [i].fSpeed <= 1) { gameStates.gameplay.slowmo [i].fSpeed = 1; gameStates.gameplay.slowmo [i].nState = 0; if (!i) SpeedupSound (); } gameStates.gameplay.slowmo [i].tUpdate = gameStates.app.nSDLTicks; } } if (bMsg) SlowMotionMessage (); #if 0//def _DEBUG HUDMessage (0, "%1.2f %1.2f %d", gameStates.gameplay.slowmo [0].fSpeed, gameStates.gameplay.slowmo [1].fSpeed, gameStates.gameplay.slowmo [1].bActive); #endif }
void DoPhysicsSim (tObject *objP) { short ignoreObjList [MAX_IGNORE_OBJS], nIgnoreObjs; int iseg; int bRetry; int fate; vmsVector vFrame; //movement in this frame vmsVector vNewPos, ipos; //position after this frame int count=0; short nObject = OBJ_IDX (objP); short nWallHitSeg, nWallHitSide; fvi_info hi; fvi_query fq; vmsVector vSavePos; int nSaveSeg; fix xDrag; fix xSimTime, xOldSimTime, xTimeScale; vmsVector vStartPos; int bObjStopped=0; fix xMovedTime; //how long objected moved before hit something vmsVector vSaveP0, vSaveP1; tPhysicsInfo *pi; short nOrigSegment = objP->nSegment; int bBounced = 0; tSpeedBoostData sbd = gameData.objs.speedBoost [nObject]; int bDoSpeedBoost = sbd.bBoosted; // && (objP == gameData.objs.console); Assert (objP->nType != OBJ_NONE); Assert (objP->movementType == MT_PHYSICS); if (objP->nType == OBJ_PLAYER && Controls.headingTime) objP = objP; #ifdef _DEBUG if (bDontMoveAIObjects) if (objP->controlType == CT_AI) return; #endif pi = &objP->mType.physInfo; DoPhysicsSimRot (objP); #if 1 if (!(pi->velocity.x || pi->velocity.y || pi->velocity.z)) { UnstickObject (objP); if (objP == gameData.objs.console) gameData.objs.speedBoost [nObject].bBoosted = sbd.bBoosted = 0; if (!(pi->thrust.x || pi->thrust.y || pi->thrust.z)) return; } #endif nPhysSegs = 0; bSimpleFVI = (objP->nType != OBJ_PLAYER); xSimTime = gameData.time.xFrame; vStartPos = objP->pos; nIgnoreObjs = 0; Assert (objP->mType.physInfo.brakes==0); //brakes not used anymore? //if uses thrust, cannot have zero xDrag Assert (!(objP->mType.physInfo.flags&PF_USES_THRUST) || objP->mType.physInfo.drag!=0); //do thrust & xDrag if (xDrag = objP->mType.physInfo.drag) { int count; vmsVector accel, *vel = &objP->mType.physInfo.velocity; fix r, k, d, a; d = f1_0 - xDrag; count = xSimTime / FT; r = xSimTime % FT; k = FixDiv (r, FT); if (objP->mType.physInfo.flags & PF_USES_THRUST) { VmVecCopyScale (&accel, &objP->mType.physInfo.thrust, FixDiv (f1_0, objP->mType.physInfo.mass)); a = (accel.x || accel.y || accel.z); if (bDoSpeedBoost && !(a || gameStates.input.bControlsSkipFrame)) *vel = sbd.vVel; else { while (count--) { if (a) VmVecInc (vel, &accel); VmVecScale (vel, d); } //do linear scale on remaining bit of time VmVecScaleInc (vel, &accel, k); VmVecScale (vel, f1_0 - FixMul (k, xDrag)); if (bDoSpeedBoost) { if (vel->x < sbd.vMinVel.x) vel->x = sbd.vMinVel.x; else if (vel->x > sbd.vMaxVel.x) vel->x = sbd.vMaxVel.x; if (vel->y < sbd.vMinVel.y) vel->y = sbd.vMinVel.y; else if (vel->y > sbd.vMaxVel.y) vel->y = sbd.vMaxVel.y; if (vel->z < sbd.vMinVel.z) vel->z = sbd.vMinVel.z; else if (vel->z > sbd.vMaxVel.z) vel->z = sbd.vMaxVel.z; } } } else { fix xTotalDrag = f1_0; while (count--) xTotalDrag = FixMul (xTotalDrag, d); //do linear scale on remaining bit of time xTotalDrag = FixMul (xTotalDrag, f1_0-FixMul (k, xDrag)); VmVecScale (&objP->mType.physInfo.velocity, xTotalDrag); } } if (extraGameInfo [IsMultiGame].bFluidPhysics) { if (gameData.segs.segment2s [objP->nSegment].special == SEGMENT_IS_WATER) xTimeScale = 75; else if (gameData.segs.segment2s [objP->nSegment].special == SEGMENT_IS_LAVA) xTimeScale = 66; else xTimeScale = 100; } else xTimeScale = 100; do { bRetry = 0; //Move the tObject VmVecCopyScale ( &vFrame, &objP->mType.physInfo.velocity, FixMulDiv (xSimTime, xTimeScale, 100)); if ((vFrame.x == 0) && (vFrame.y == 0) && (vFrame.z == 0)) break; retryMove: count++; // If retry count is getting large, then we are trying to do something stupid. if (count > 3) { if (objP->nType == OBJ_PLAYER) { if (count > 8) { if (sbd.bBoosted) sbd.bBoosted = 0; break; } } else break; } VmVecAdd (&vNewPos, &objP->pos, &vFrame); ignoreObjList [nIgnoreObjs] = -1; fq.p0 = &objP->pos; fq.startSeg = objP->nSegment; fq.p1 = &vNewPos; fq.rad = objP->size; fq.thisObjNum = nObject; fq.ignoreObjList = ignoreObjList; fq.flags = FQ_CHECK_OBJS; if (objP->nType == OBJ_WEAPON) fq.flags |= FQ_TRANSPOINT; //if (objP->nType == OBJ_PLAYER) fq.flags |= FQ_GET_SEGLIST; vSaveP0 = *fq.p0; vSaveP1 = *fq.p1; fate = FindVectorIntersection (&fq, &hi); #ifdef _DEBUG if (fate == HIT_WALL) fate = FindVectorIntersection (&fq, &hi); #endif // Matt: Mike's hack. if (fate == HIT_OBJECT) { tObject *objP = gameData.objs.objects + hi.hit.nObject; if ((objP->nType == OBJ_WEAPON) && ((objP->id == PROXIMITY_ID) || (objP->id == SUPERPROX_ID))) count--; } #ifdef _DEBUG if (fate == HIT_BAD_P0) { #if 0 //TRACE con_printf (CON_DEBUG, "Warning: Bad p0 in physics! Object = %i, nType = %i [%s]\n", objP - gameData.objs.objects, objP->nType, ObjectType_names [objP->nType]); #endif Int3 (); } #endif //if ((objP->nType == OBJ_PLAYER) || (objP->nType == OBJ_ROBOT) || (objP->nType == OBJ_MONSTERBALL)) { int i; #ifdef RELEASE int j; #endif if (nPhysSegs && (physSegList [nPhysSegs-1] == hi.segList [0])) nPhysSegs--; #ifdef RELEASE j = MAX_FVI_SEGS - nPhysSegs - 1; if (j > hi.nSegments) j = hi.nSegments; memcpy (physSegList + nPhysSegs, hi.segList, j * sizeof (*physSegList)); nPhysSegs += j; #else for (i = 0; (i < hi.nSegments) && (nPhysSegs < MAX_FVI_SEGS-1); ) { if (hi.segList [i] > gameData.segs.nLastSegment) LogErr ("Invalid segment in segment list #1\n"); physSegList [nPhysSegs++] = hi.segList [i++]; } #endif } ipos = hi.hit.vPoint; iseg = hi.hit.nSegment; nWallHitSide = hi.hit.nSide; nWallHitSeg = hi.hit.nSideSegment; if (iseg==-1) { //some sort of horrible error if (objP->nType == OBJ_WEAPON) objP->flags |= OF_SHOULD_BE_DEAD; break; } Assert (!((fate==HIT_WALL) && ((nWallHitSeg == -1) || (nWallHitSeg > gameData.segs.nLastSegment)))); vSavePos = objP->pos; //save the tObject's position nSaveSeg = objP->nSegment; // update tObject's position and tSegment number objP->pos = ipos; if (iseg != objP->nSegment) RelinkObject (nObject, iseg); //if start point not in tSegment, move tObject to center of tSegment if (GetSegMasks (&objP->pos, objP->nSegment, 0).centerMask) { //tObject stuck vmsVector vCenter; int n = FindObjectSeg (objP); if (n == -1) { n = FindSegByPoint (&objP->last_pos, objP->nSegment); if (n == -1) { objP->flags |= OF_SHOULD_BE_DEAD; return; } } objP->pos = objP->last_pos; RelinkObject (nObject, n); COMPUTE_SEGMENT_CENTER_I (&vCenter, objP->nSegment); VmVecDec (&vCenter, &objP->pos); if (VmVecMag (&vCenter) > F1_0) { VmVecNormalize (&vCenter); VmVecScaleFrac (&vCenter, 1, 10); } VmVecDec (&objP->pos, &vCenter); //return; } //calulate new sim time { //vmsVector vMoved; vmsVector vMoveNormal; fix attemptedDist, actualDist; xOldSimTime = xSimTime; actualDist = VmVecNormalizedDir (&vMoveNormal, &objP->pos, &vSavePos); if ((fate == HIT_WALL) && (VmVecDot (&vMoveNormal, &vFrame) < 0)) { //moved backwards //don't change position or xSimTime objP->pos = vSavePos; //iseg = objP->nSegment; //don't change tSegment if (nSaveSeg != iseg) RelinkObject (nObject, nSaveSeg); if (bDoSpeedBoost) { // int h = FindSegByPoint (&vNewPos, -1); objP->pos = vStartPos; SetSpeedBoostVelocity (nObject, -1, -1, -1, -1, -1, &vStartPos, &sbd.vDest, 0); VmVecCopyScale (&vFrame, &sbd.vVel, xSimTime); goto retryMove; } xMovedTime = 0; } else { //retryMove2: attemptedDist = VmVecMag (&vFrame); xSimTime = FixMulDiv (xSimTime, attemptedDist-actualDist, attemptedDist); xMovedTime = xOldSimTime - xSimTime; if ((xSimTime < 0) || (xSimTime > xOldSimTime)) { xSimTime = xOldSimTime; xMovedTime = 0; } } } switch (fate) { case HIT_WALL: { vmsVector vMoved; fix xHitSpeed, xWallPart, xSideDist, xSideDists [6]; short nSegment; // Find hit speed #if 0//def _DEBUG if (objP->nType == OBJ_PLAYER) HUDMessage (0, "WALL CONTACT"); fate = FindVectorIntersection (&fq, &hi); #endif VmVecSub (&vMoved, &objP->pos, &vSavePos); xWallPart = VmVecDot (&vMoved, &hi.hit.vNormal); if (xWallPart && (xMovedTime > 0) && (xHitSpeed = -FixDiv (xWallPart, xMovedTime)) > 0) { CollideObjectWithWall (objP, xHitSpeed, nWallHitSeg, nWallHitSide, &hi.hit.vPoint); #if 0//def _DEBUG if (objP->nType == OBJ_PLAYER) HUDMessage (0, "BUMP!"); #endif } else { #if 0//def _DEBUG if (objP->nType == OBJ_PLAYER) HUDMessage (0, "SCREEEEEEEEEECH"); #endif ScrapeObjectOnWall (objP, nWallHitSeg, nWallHitSide, &hi.hit.vPoint); } Assert (nWallHitSeg > -1); Assert (nWallHitSide > -1); GetSideDistsAll (&objP->pos, nWallHitSeg, xSideDists); if ((xSideDist = xSideDists [nWallHitSide]) && (xSideDist < objP->size - objP->size / 100)) { #if 1 float r = 0.1f; #else float r; xSideDist = objP->size - xSideDist; r = ((float) xSideDist / (float) objP->size) * f2fl (objP->size); #endif objP->pos.x += (fix) ((float) hi.hit.vNormal.x * r); objP->pos.y += (fix) ((float) hi.hit.vNormal.y * r); objP->pos.z += (fix) ((float) hi.hit.vNormal.z * r); nSegment = FindSegByPoint (&objP->pos, objP->nSegment); if (nSegment != objP->nSegment) RelinkObject (OBJ_IDX (objP), nSegment); #if 0//def _DEBUG if (objP->nType == OBJ_PLAYER) HUDMessage (0, "PENETRATING WALL (%d, %1.4f)", objP->size - xSideDists [nWallHitSide], r); #endif bRetry = 1; } if (!(objP->flags & OF_SHOULD_BE_DEAD)) { int forcefield_bounce; //bounce off a forcefield Assert (gameStates.app.cheats.bBouncingWeapons || !(objP->mType.physInfo.flags & PF_STICK && objP->mType.physInfo.flags & PF_BOUNCE)); //can't be bounce and stick forcefield_bounce = (gameData.pig.tex.pTMapInfo [gameData.segs.segments [nWallHitSeg].sides [nWallHitSide].nBaseTex].flags & TMI_FORCE_FIELD); if (!forcefield_bounce && (objP->mType.physInfo.flags & PF_STICK)) { //stop moving AddStuckObject (objP, nWallHitSeg, nWallHitSide); VmVecZero (&objP->mType.physInfo.velocity); bObjStopped = 1; bRetry = 0; } else { // Slide tObject along wall int bCheckVel = 0; //We're constrained by wall, so subtract wall part from //velocity vector xWallPart = VmVecDot (&hi.hit.vNormal, &objP->mType.physInfo.velocity); if (forcefield_bounce || (objP->mType.physInfo.flags & PF_BOUNCE)) { //bounce off wall xWallPart *= 2; //Subtract out wall part twice to achieve bounce if (forcefield_bounce) { bCheckVel = 1; //check for max velocity if (objP->nType == OBJ_PLAYER) xWallPart *= 2; //player bounce twice as much } if (objP->mType.physInfo.flags & PF_BOUNCES_TWICE) { Assert (objP->mType.physInfo.flags & PF_BOUNCE); if (objP->mType.physInfo.flags & PF_BOUNCED_ONCE) objP->mType.physInfo.flags &= ~ (PF_BOUNCE+PF_BOUNCED_ONCE+PF_BOUNCES_TWICE); else objP->mType.physInfo.flags |= PF_BOUNCED_ONCE; } bBounced = 1; //this tObject bBounced } VmVecScaleInc (&objP->mType.physInfo.velocity, &hi.hit.vNormal, -xWallPart); if (bCheckVel) { fix vel = VmVecMag (&objP->mType.physInfo.velocity); if (vel > MAX_OBJECT_VEL) VmVecScale (&objP->mType.physInfo.velocity, FixDiv (MAX_OBJECT_VEL, vel)); } if (bBounced && (objP->nType == OBJ_WEAPON)) VmVector2Matrix (&objP->orient, &objP->mType.physInfo.velocity, &objP->orient.uVec, NULL); bRetry = 1; } } break; } case HIT_OBJECT: { vmsVector vOldVel; vmsVector *ppos0, *ppos1, vHitPos; fix size0, size1; // Mark the hit tObject so that on a retry the fvi code // ignores this tObject. //if (bSpeedBoost && (objP == gameData.objs.console)) // break; Assert (hi.hit.nObject != -1); ppos0 = &gameData.objs.objects [hi.hit.nObject].pos; ppos1 = &objP->pos; size0 = gameData.objs.objects [hi.hit.nObject].size; size1 = objP->size; // Calculcate the hit point between the two objects. Assert (size0+size1 != 0); // Error, both sizes are 0, so how did they collide, anyway?!? //VmVecScale (VmVecSub (&pos_hit, ppos1, ppos0), FixDiv (size0, size0 + size1); //VmVecInc (&pos_hit, ppos0); VmVecSub (&vHitPos, ppos1, ppos0); VmVecScaleAdd (&vHitPos, ppos0, &vHitPos, FixDiv (size0, size0 + size1)); vOldVel = objP->mType.physInfo.velocity; CollideTwoObjects (objP, gameData.objs.objects + hi.hit.nObject, &vHitPos); if (sbd.bBoosted && (objP == gameData.objs.console)) objP->mType.physInfo.velocity = vOldVel; // Let tObject continue its movement if (!(objP->flags&OF_SHOULD_BE_DEAD) ) { if (objP->mType.physInfo.flags&PF_PERSISTENT || (vOldVel.x == objP->mType.physInfo.velocity.x && vOldVel.y == objP->mType.physInfo.velocity.y && vOldVel.z == objP->mType.physInfo.velocity.z)) { //if (gameData.objs.objects [hi.hit.nObject].nType == OBJ_POWERUP) ignoreObjList [nIgnoreObjs++] = hi.hit.nObject; bRetry = 1; } } break; } case HIT_NONE: #ifdef TACTILE if (TactileStick && objP==gameData.objs.console && !(FrameCount & 15)) Tactile_Xvibrate_clear (); #endif break; #ifdef _DEBUG case HIT_BAD_P0: Int3 (); // Unexpected collision nType: start point not in specified tSegment. #if TRACE con_printf (CON_DEBUG, "Warning: Bad p0 in physics!!!\n"); #endif break; default: // Unknown collision nType returned from FindVectorIntersection!! Int3 (); break; #endif } } while (bRetry); // Pass retry count info to AI. if (objP->controlType == CT_AI) { if (count > 0) { gameData.ai.localInfo [nObject].nRetryCount = count-1; #ifdef _DEBUG Total_retries += count-1; Total_sims++; #endif } } //I'm not sure why we do this. I wish there were a comment that //explained it. I think maybe it only needs to be done if the tObject //is sliding, but I don't know if (!(sbd.bBoosted || bObjStopped || bBounced)) { //Set velocity from actual movement vmsVector vMoved; VmVecSub (&vMoved, &objP->pos, &vStartPos); VmVecCopyScale (&objP->mType.physInfo.velocity, &vMoved, FixMulDiv (FixDiv (f1_0, gameData.time.xFrame), 100, xTimeScale)); #ifdef BUMP_HACK if (objP == gameData.objs.console && objP->mType.physInfo.velocity.x==0 && objP->mType.physInfo.velocity.y==0 && objP->mType.physInfo.velocity.z==0 && (objP->mType.physInfo.thrust.x!=0 || objP->mType.physInfo.thrust.y!=0 || objP->mType.physInfo.thrust.z!=0)) { vmsVector vCenter, vBump; //bump player a little towards vCenter of tSegment to unstick COMPUTE_SEGMENT_CENTER_I (&vCenter, objP->nSegment); //HUDMessage (0, "BUMP! %d %d", d1, d2); //don't bump player toward vCenter of reactor tSegment if (gameData.segs.segment2s [objP->nSegment].special == SEGMENT_IS_CONTROLCEN) VmVecNegate (&vBump); VmVecScaleInc (&objP->pos, &vBump, objP->size/5); //if moving away from seg, might move out of seg, so update if (gameData.segs.segment2s [objP->nSegment].special == SEGMENT_IS_CONTROLCEN) UpdateObjectSeg (objP); } #endif } //Assert (check_point_in_seg (&objP->pos, objP->nSegment, 0).centerMask==0); //if (objP->controlType == CT_FLYING) if (objP->mType.physInfo.flags & PF_LEVELLING) DoPhysicsAlignObject (objP); //hack to keep player from going through closed doors if ((objP->nType == OBJ_PLAYER) && (objP->nSegment != nOrigSegment) && (gameStates.app.cheats.bPhysics != 0xBADA55)) { int nSide; nSide = FindConnectedSide (gameData.segs.segments + objP->nSegment, gameData.segs.segments + nOrigSegment); if (nSide != -1) { if (!(WALL_IS_DOORWAY (gameData.segs.segments + nOrigSegment, nSide, NULL) & WID_FLY_FLAG)) { tSide *sideP; int nVertex, nFaces; fix dist; int vertex_list [6]; //bump tObject back sideP = gameData.segs.segments [nOrigSegment].sides + nSide; if (nOrigSegment==-1) Error ("nOrigSegment == -1 in physics"); CreateAbsVertexLists (&nFaces, vertex_list, nOrigSegment, nSide); //let'sideP pretend this wall is not triangulated nVertex = vertex_list [0]; if (nVertex > vertex_list [1]) nVertex = vertex_list [1]; if (nVertex > vertex_list [2]) nVertex = vertex_list [2]; if (nVertex > vertex_list [3]) nVertex = vertex_list [3]; #ifdef COMPACT_SEGS { vmsVector _vn; get_side_normal (gameData.segs.segments + nOrigSegment, nSide, 0, &_vn); dist = VmDistToPlane (&vStartPos, &_vn, &gameData.segs.vertices [nVertex]); VmVecScaleAdd (&objP->pos, &vStartPos, &_vn, objP->size-dist); } #else dist = VmDistToPlane (&vStartPos, sideP->normals, gameData.segs.vertices + nVertex); VmVecScaleAdd (&objP->pos, &vStartPos, sideP->normals, objP->size-dist); #endif UpdateObjectSeg (objP); } } } //if end point not in tSegment, move tObject to last pos, or tSegment center if (GetSegMasks (&objP->pos, objP->nSegment, 0).centerMask) { if (FindObjectSeg (objP) == -1) { int n; if (objP->nType==OBJ_PLAYER && (n=FindSegByPoint (&objP->last_pos, objP->nSegment))!=-1) { objP->pos = objP->last_pos; RelinkObject (nObject, n); } else { COMPUTE_SEGMENT_CENTER_I (&objP->pos, objP->nSegment); objP->pos.x += nObject; } if (objP->nType == OBJ_WEAPON) objP->flags |= OF_SHOULD_BE_DEAD; } } UnstickObject (objP); }
int ControlsReadAll (void) { int i; int bSlideOn, bBankOn; int nBankSensMod; fix pitchTime, headingTime; fix mouseAxis [3]; int nMouseButtons; int bUseMouse, bUseJoystick; Controls [0].cyclePrimaryCount = 0; Controls [0].cycleSecondaryCount = 0; Controls [0].toggleIconsCount = 0; Controls [0].zoomDownCount = 0; Controls [0].headlightCount = 0; Controls [0].fireFlareDownCount = 0; Controls [0].dropBombDownCount = 0; Controls [0].automapDownCount = 0; Controls [0].rearViewDownCount = 0; gameStates.input.bControlsSkipFrame = 1; if (ControlsCapSampleRate ()) return 1; gameStates.input.bControlsSkipFrame = 0; ControlsResetControls (); gameStates.input.bKeepSlackTime = 1; nBankSensMod = kcFrameCount; nMouseButtons = 0; bUseMouse = 0; bSlideOn = 0; bBankOn = 0; #ifdef FAST_EVENTPOLL if (!gameOpts->legacy.bInput) event_poll (SDL_ALLEVENTS); //why poll 2 dozen times in the following code when input polling calls all necessary input handlers anyway? #endif SetControlType (); bUseJoystick = gameOpts->input.joystick.bUse && ControlsReadJoystick ((int *) &joyAxis [0]); if (gameOpts->input.mouse.bUse) if (gameStates.input.bCybermouseActive) { // ReadOWL (kc_external_control); // CybermouseAdjust (); } else if (gameStates.input.nMouseType == CONTROL_CYBERMAN) bUseMouse = ControlsReadCyberman ((int *) &mouseAxis [0], &nMouseButtons); else bUseMouse = ControlsReadMouse ((int *) &mouseAxis [0], &nMouseButtons); else { mouseAxis [0] = mouseAxis [1] = mouseAxis [2] = 0; nMouseButtons = 0; bUseMouse = 0; } pitchTime = headingTime = 0; memset (Controls + 1, 0, 3 * sizeof (tControlInfo)); for (i = 0; i < 3; i++) { ControlsDoKeyboard (&bSlideOn, &bBankOn, &pitchTime, &headingTime, (int *) &gameStates.input.nCruiseSpeed, i); if (bUseJoystick) ControlsDoJoystick (&bSlideOn, &bBankOn, &pitchTime, &headingTime, (int *) &gameStates.input.nCruiseSpeed, i); if (bUseMouse) ControlsDoMouse ((int *) &mouseAxis [0], nMouseButtons, &bSlideOn, &bBankOn, &pitchTime, &headingTime, (int *) &gameStates.input.nCruiseSpeed, i); Controls [0].pitchTime = Controls [1].pitchTime + Controls [2].pitchTime + Controls [3].pitchTime; Controls [0].headingTime = Controls [1].headingTime + Controls [2].headingTime + Controls [3].headingTime; Controls [0].bankTime = Controls [1].bankTime + Controls [2].bankTime + Controls [3].bankTime; if (i == 1) { ControlsDoSlideBank (bSlideOn, bBankOn, pitchTime, headingTime); } } if (gameOpts->input.bUseHotKeys) ControlsDoD2XKeys (&bSlideOn, &bBankOn, &pitchTime, &headingTime, (int *) &gameStates.input.nCruiseSpeed, i); #ifdef WIN32 if (ControlsReadTrackIR ()) ControlsDoTrackIR (); #endif if (gameStates.input.nCruiseSpeed > I2X (100)) gameStates.input.nCruiseSpeed = I2X (100); else if (gameStates.input.nCruiseSpeed < 0) gameStates.input.nCruiseSpeed = 0; if (!Controls [0].forwardThrustTime) Controls [0].forwardThrustTime = FixMul (gameStates.input.nCruiseSpeed,gameStates.input.kcPollTime) /100; #if 0 //LIMIT_CONTROLS_FPS if (nBankSensMod > 2) { Controls [0].bankTime *= 2; Controls [0].bankTime /= nBankSensMod; } #endif //----------- Clamp values between -gameStates.input.kcPollTime and gameStates.input.kcPollTime if (gameStates.input.kcPollTime > F1_0) { #if TRACE con_printf (1, "Bogus frame time of %.2f seconds\n", X2F (gameStates.input.kcPollTime)); #endif gameStates.input.kcPollTime = F1_0; } #if 0 Controls [0].verticalThrustTime /= kcFrameCount; Controls [0].sidewaysThrustTime /= kcFrameCount; Controls [0].forwardThrustTime /= kcFrameCount; Controls [0].headingTime /= kcFrameCount; Controls [0].pitchTime /= kcFrameCount; Controls [0].bankTime /= kcFrameCount; #endif KCCLAMP (Controls [0].verticalThrustTime, nMaxTurnRate); KCCLAMP (Controls [0].sidewaysThrustTime, nMaxTurnRate); KCCLAMP (Controls [0].forwardThrustTime, nMaxTurnRate); if (ControlsLimitTurnRate (bUseMouse)) { if (Controls [1].headingTime || Controls [2].headingTime) { KCCLAMP (Controls [0].headingTime, nMaxTurnRate); } if (Controls [1].pitchTime || Controls [2].pitchTime) { KCCLAMP (Controls [0].pitchTime, nMaxTurnRate / FASTPITCH); } if (Controls [1].bankTime || Controls [2].bankTime) { KCCLAMP (Controls [0].bankTime, nMaxTurnRate); } } else { KCCLAMP (Controls [0].headingTime, nMaxTurnRate); KCCLAMP (Controls [0].pitchTime, nMaxTurnRate / FASTPITCH); KCCLAMP (Controls [0].bankTime, nMaxTurnRate); } if (gameStates.render.nZoomFactor > F1_0) { int r = (gameStates.render.nZoomFactor * 100) / F1_0; Controls [0].headingTime = (Controls [0].headingTime * 100) / r; Controls [0].pitchTime = (Controls [0].pitchTime * 100) / r; Controls [0].bankTime = (Controls [0].bankTime * 100) / r; #if DBG r = (int) ((double) gameStates.render.nZoomFactor * 100.0 / (double) F1_0); HUDMessage (0, "x %d.%02d", r / 100, r % 100); #endif } // KCCLAMP (Controls [0].afterburnerTime, gameStates.input.kcPollTime); #if DBG if (gameStates.input.keys.pressed [KEY_DELETE]) memset (&Controls, 0, sizeof (tControlInfo)); #endif gameStates.input.bKeepSlackTime = 0; kcFrameCount = 0; gameStates.input.kcPollTime = 0; return 0; }
// -------------------------------------------------------------------------------------------------------------------- // Note: This function could be optimized. Surely ObjectCanSeePlayer would benefit from the // information of a normalized gameData.ai.vVecToPlayer. // Return CPlayerData visibility: // 0 not visible // 1 visible, but robot not looking at CPlayerData (ie, on an unobstructed vector) // 2 visible and in robot's field of view // -1 CPlayerData is cloaked // If the CPlayerData is cloaked, set gameData.ai.vVecToPlayer based on time CPlayerData cloaked and last uncloaked position. // Updates ailP->nPrevVisibility if CPlayerData is not cloaked, in which case the previous visibility is left unchanged // and is copied to gameData.ai.nPlayerVisibility void ComputeVisAndVec (CObject *objP, CFixVector *pos, tAILocalInfo *ailP, tRobotInfo *botInfoP, int *flag, fix xMaxVisibleDist) { if (*flag) { LimitPlayerVisibility (xMaxVisibleDist, ailP); } else { if (LOCALPLAYER.flags & PLAYER_FLAGS_CLOAKED) { fix deltaTime, dist; int cloak_index = (objP->Index ()) % MAX_AI_CLOAK_INFO; deltaTime = gameData.time.xGame - gameData.ai.cloakInfo [cloak_index].lastTime; if (deltaTime > I2X (2)) { CFixVector vRand; gameData.ai.cloakInfo [cloak_index].lastTime = gameData.time.xGame; vRand = CFixVector::Random(); gameData.ai.cloakInfo [cloak_index].vLastPos += vRand * (8*deltaTime); } dist = CFixVector::NormalizedDir(gameData.ai.vVecToPlayer, gameData.ai.cloakInfo [cloak_index].vLastPos, *pos); gameData.ai.nPlayerVisibility = ObjectCanSeePlayer (objP, pos, botInfoP->fieldOfView [gameStates.app.nDifficultyLevel], &gameData.ai.vVecToPlayer); LimitPlayerVisibility (xMaxVisibleDist, ailP); #if DBG if (gameData.ai.nPlayerVisibility == 2) gameData.ai.nPlayerVisibility = gameData.ai.nPlayerVisibility; #endif if ((ailP->nextMiscSoundTime < gameData.time.xGame) && ((ailP->nextPrimaryFire < I2X (1)) || (ailP->nextSecondaryFire < I2X (1))) && (dist < I2X (20))) { ailP->nextMiscSoundTime = gameData.time.xGame + (d_rand () + I2X (1)) * (7 - gameStates.app.nDifficultyLevel) / 1; audio.CreateSegmentSound (botInfoP->seeSound, objP->info.nSegment, 0, *pos, 0 , nRobotSoundVolume); } } else { // Compute expensive stuff -- gameData.ai.vVecToPlayer and gameData.ai.nPlayerVisibility CFixVector::NormalizedDir(gameData.ai.vVecToPlayer, gameData.ai.vBelievedPlayerPos, *pos); if (gameData.ai.vVecToPlayer.IsZero()) { gameData.ai.vVecToPlayer[X] = I2X (1); } gameData.ai.nPlayerVisibility = ObjectCanSeePlayer (objP, pos, botInfoP->fieldOfView [gameStates.app.nDifficultyLevel], &gameData.ai.vVecToPlayer); LimitPlayerVisibility (xMaxVisibleDist, ailP); #if DBG if (gameData.ai.nPlayerVisibility == 2) gameData.ai.nPlayerVisibility = gameData.ai.nPlayerVisibility; #endif // This horrible code added by MK in desperation on 12/13/94 to make robots wake up as soon as they // see you without killing frame rate. { tAIStaticInfo *aiP = &objP->cType.aiInfo; if ((gameData.ai.nPlayerVisibility == 2) && (ailP->nPrevVisibility != 2)) if ((aiP->GOAL_STATE == AIS_REST) || (aiP->CURRENT_STATE == AIS_REST)) { aiP->GOAL_STATE = AIS_FIRE; aiP->CURRENT_STATE = AIS_FIRE; } } if ((ailP->nPrevVisibility != gameData.ai.nPlayerVisibility) && (gameData.ai.nPlayerVisibility == 2)) { if (ailP->nPrevVisibility == 0) { if (ailP->timePlayerSeen + I2X (1)/2 < gameData.time.xGame) { // -- if (gameStates.app.bPlayerExploded) // -- audio.CreateSegmentSound (botInfoP->tauntSound, objP->info.nSegment, 0, pos, 0 , nRobotSoundVolume); // -- else audio.CreateSegmentSound (botInfoP->seeSound, objP->info.nSegment, 0, *pos, 0 , nRobotSoundVolume); ailP->timePlayerSoundAttacked = gameData.time.xGame; ailP->nextMiscSoundTime = gameData.time.xGame + I2X (1) + d_rand ()*4; } } else if (ailP->timePlayerSoundAttacked + I2X (1)/4 < gameData.time.xGame) { // -- if (gameStates.app.bPlayerExploded) // -- audio.CreateSegmentSound (botInfoP->tauntSound, objP->info.nSegment, 0, pos, 0 , nRobotSoundVolume); // -- else audio.CreateSegmentSound (botInfoP->attackSound, objP->info.nSegment, 0, *pos, 0 , nRobotSoundVolume); ailP->timePlayerSoundAttacked = gameData.time.xGame; } } if ((gameData.ai.nPlayerVisibility == 2) && (ailP->nextMiscSoundTime < gameData.time.xGame)) { ailP->nextMiscSoundTime = gameData.time.xGame + (d_rand () + I2X (1)) * (7 - gameStates.app.nDifficultyLevel) / 2; // -- if (gameStates.app.bPlayerExploded) // -- audio.CreateSegmentSound (botInfoP->tauntSound, objP->info.nSegment, 0, pos, 0 , nRobotSoundVolume); // -- else audio.CreateSegmentSound (botInfoP->attackSound, objP->info.nSegment, 0, *pos, 0 , nRobotSoundVolume); } ailP->nPrevVisibility = gameData.ai.nPlayerVisibility; } *flag = 1; // @mk, 09/21/95: If CPlayerData view is not obstructed and awareness is at least as high as a nearby collision, // act is if robot is looking at player. if (ailP->playerAwarenessType >= PA_NEARBY_ROBOT_FIRED) if (gameData.ai.nPlayerVisibility == 1) gameData.ai.nPlayerVisibility = 2; if (gameData.ai.nPlayerVisibility) ailP->timePlayerSeen = gameData.time.xGame; } if (objP->Index () == nDbgObj) { HUDMessage (0, "vis: %d", gameData.ai.nPlayerVisibility); } }
int CSegment::ConquerCheck (void) { CPlayerData *playerP = gameData.multiplayer.players + gameData.multiplayer.nLocalPlayer; int team = GetTeam (gameData.multiplayer.nLocalPlayer) + 1; time_t t; gameStates.entropy.bConquering = 0; if (!(gameData.app.nGameMode & GM_ENTROPY)) return 0; #if 0 if (gameStates.entropy.nTimeLastMoved < 0) { HUDMessage (0, "you are moving"); StopConquerWarning (); return 0; } if (playerP->shields < 0) { HUDMessage (0, "you are dead"); StopConquerWarning (); return 0; } if (playerP->secondaryAmmo [PROXMINE_INDEX] < extraGameInfo [1].nCaptureVirusLimit) { HUDMessage (0, "too few viruses"); StopConquerWarning (); return 0; } if (m_owner < 0) { HUDMessage (0, "neutral room"); StopConquerWarning (); return 0; } if (m_owner == team) { HUDMessage (0, "own room"); StopConquerWarning (); return 0; } #else if ((gameStates.entropy.nTimeLastMoved < 0) || (playerP->shields < 0) || (playerP->secondaryAmmo [PROXMINE_INDEX] < extraGameInfo [1].entropy.nCaptureVirusLimit) || (m_owner < 0) || (m_owner == team)) { StopConquerWarning (); return 0; } #endif t = SDL_GetTicks (); if (!gameStates.entropy.nTimeLastMoved) gameStates.entropy.nTimeLastMoved = (int) t; if (t - gameStates.entropy.nTimeLastMoved < extraGameInfo [1].entropy.nCaptureTimeLimit * 1000) { gameStates.entropy.bConquering = 1; if (m_owner > 0) StartConquerWarning (); return 0; } StopConquerWarning (); if (m_owner) MultiSendCaptureBonus ((char) gameData.multiplayer.nLocalPlayer); playerP->secondaryAmmo [PROXMINE_INDEX] -= extraGameInfo [1].entropy.nCaptureVirusLimit; if (playerP->secondaryAmmo [SMARTMINE_INDEX] > extraGameInfo [1].entropy.nBashVirusCapacity) playerP->secondaryAmmo [SMARTMINE_INDEX] -= extraGameInfo [1].entropy.nBashVirusCapacity; else playerP->secondaryAmmo [SMARTMINE_INDEX] = 0; MultiSendConquerRoom (char (team), char (m_owner), char (m_group)); ConquerRoom (char (team), char (m_owner), char (m_group)); return 1; }
void HandleGameKey(int key) { switch (key) { #ifndef D2X_KEYS // weapon selection handled in ControlsReadAll, d1x-style // MWA changed the weapon select cases to have each case call // DoSelectWeapon the macintosh keycodes aren't consecutive from 1 // -- 0 on the keyboard -- boy is that STUPID!!!! // Select primary or secondary weapon. case KEY_1: DoSelectWeapon(0 , 0); break; case KEY_2: DoSelectWeapon(1 , 0); break; case KEY_3: DoSelectWeapon(2 , 0); break; case KEY_4: DoSelectWeapon(3 , 0); break; case KEY_5: DoSelectWeapon(4 , 0); break; case KEY_6: DoSelectWeapon(0 , 1); break; case KEY_7: DoSelectWeapon(1 , 1); break; case KEY_8: DoSelectWeapon(2 , 1); break; case KEY_9: DoSelectWeapon(3 , 1); break; case KEY_0: DoSelectWeapon(4 , 1); break; #endif case KEY_1 + KEY_SHIFTED: case KEY_2 + KEY_SHIFTED: case KEY_3 + KEY_SHIFTED: case KEY_4 + KEY_SHIFTED: case KEY_5 + KEY_SHIFTED: case KEY_6 + KEY_SHIFTED: case KEY_7 + KEY_SHIFTED: case KEY_8 + KEY_SHIFTED: case KEY_9 + KEY_SHIFTED: case KEY_0 + KEY_SHIFTED: if (gameOpts->gameplay.bEscortHotKeys) { if (IsMultiGame) HUDInitMessage (TXT_GB_MULTIPLAYER); else EscortSetSpecialGoal (key); break; } case KEY_ALTED + KEY_M: gameStates.app.bMultiThreaded = !gameStates.app.bMultiThreaded; HUDMessage (0, "multi-threading %s", gameStates.app.bMultiThreaded ? "ON" : "OFF"); break; case KEY_ALTED + KEY_P: #if PROFILING if ((gameStates.render.bShowProfiler = !gameStates.render.bShowProfiler)) memset (&gameData.profiler, 0, sizeof (gameData.profiler)); #endif break; case KEY_ALTED + KEY_F: gameStates.render.bShowFrameRate = ++gameStates.render.bShowFrameRate % (6 + (gameStates.render.bPerPixelLighting == 2)); break; case KEY_ALTED + KEY_R: ToggleRadar (); break; case KEY_ALTED + KEY_T: gameStates.render.bShowTime = !gameStates.render.bShowTime; break; case KEY_CTRLED + KEY_ALTED + KEY_R: gr_renderstats = !gr_renderstats; break; case KEY_CTRLED + KEY_ALTED + KEY_ESC: gameStates.app.bSingleStep = 1; break; case KEY_F5 + KEY_SHIFTED: DropCurrentWeapon (); break; case KEY_F6 + KEY_SHIFTED: DropSecondaryWeapon(-1); break; case KEY_0 + KEY_ALTED: DropFlag (); break; case KEY_F4: if (!gameData.marker.nDefiningMsg) InitMarkerInput (); break; case KEY_F4 + KEY_CTRLED: if (!gameData.marker.nDefiningMsg) DropSpawnMarker (); break; case KEY_ALTED + KEY_CTRLED + KEY_T: SwitchTeam (gameData.multiplayer.nLocalPlayer, 0); break; case KEY_F6: if (netGame.bRefusePlayers && networkData.refuse.bWaitForAnswer && !(gameData.app.nGameMode & GM_TEAM)) { networkData.refuse.bThisPlayer=1; HUDInitMessage (TXT_ACCEPT_PLR); } break; case KEY_ALTED + KEY_1: if (netGame.bRefusePlayers && networkData.refuse.bWaitForAnswer && (gameData.app.nGameMode & GM_TEAM)) { networkData.refuse.bThisPlayer=1; HUDInitMessage (TXT_ACCEPT_PLR); networkData.refuse.bTeam=1; } break; case KEY_ALTED + KEY_2: if (netGame.bRefusePlayers && networkData.refuse.bWaitForAnswer && (gameData.app.nGameMode & GM_TEAM)) { networkData.refuse.bThisPlayer=1; HUDInitMessage (TXT_ACCEPT_PLR); networkData.refuse.bTeam=2; } break; default: break; } //switch (key) }
void ControlsDoTrackIR (void) { int dx = (int) ((float) tirInfo.fvRot.z * (float) SWIDTH / 16384.0f), dy = (int) ((float) tirInfo.fvRot.y * (float) SHEIGHT / 16384.0f), dz; int x, y; float fDeadzone, fScale; if (gameOpts->input.trackIR.nMode == 0) { #if 1 #else dx = (int) tirInfo.fvRot.z * (gameOpts->input.trackIR.sensitivity [0] + 1); dy = (int) tirInfo.fvRot.y * (gameOpts->input.trackIR.sensitivity [1] + 1); #endif x = gameData.trackIR.x; y = gameData.trackIR.y; #if 0//def _DEBUG HUDMessage (0, "%d/%d %d/%d", x, dx, y, dy); #endif if (abs (dx - x) > gameOpts->input.trackIR.nDeadzone * 4) { dx = dx * (gameOpts->input.trackIR.sensitivity [0] + 1) / 4; gameData.trackIR.x = dx; dx -= x; } else dx = 0; if (abs (dy - y) > gameOpts->input.trackIR.nDeadzone * 4) { dy = dy * (gameOpts->input.trackIR.sensitivity [1] + 1) / 4; gameData.trackIR.y = dy; dy -= y; } else dy = 0; if (gameOpts->input.trackIR.bMove [0]) { Controls [0].headingTime -= (fix) (dx * gameStates.input.kcPollTime); Controls [0].pitchTime += (fix) (dy * gameStates.input.kcPollTime); } if (gameOpts->input.trackIR.bMove [1]) Controls [0].bankTime += (int) (tirInfo.fvRot.x * gameStates.input.kcPollTime / 131072.0f * (gameOpts->input.trackIR.sensitivity [2] + 1)); } else if (gameOpts->input.trackIR.nMode == 1) { dx = (int) ((float) tirInfo.fvRot.z * (float) SWIDTH / 16384.0f); dy = (int) ((float) tirInfo.fvRot.y * (float) SHEIGHT / 16384.0f); dz = 0; //CalcDeadzone (dy, gameOpts->input.trackIR.nDeadzone); if (dx < 0) { if (dx > -dz) dx = 0; else dx += dz; } else { if (dx < dz) dx = 0; else dx -= dz; } dz = 0; //CalcDeadzone (dx, gameOpts->input.trackIR.nDeadzone); if (dy < 0) { if (dy > -dz) dy = 0; else dy += dz; } else { if (dy < dz) dy = 0; else dy -= dz; } #if 0//def _DEBUG HUDMessage (0, "%d %d", dx, dy); #endif dx = 640 * dx / (SWIDTH / (gameOpts->input.trackIR.sensitivity [0] + 1)); dy = 480 * dy / (SHEIGHT / (gameOpts->input.trackIR.sensitivity [1] + 1)); if (gameOpts->input.trackIR.bMove [0]) { Controls [0].headingTime -= dx; Controls [0].pitchTime += dy; } if (gameOpts->input.trackIR.bMove [1]) Controls [0].bankTime += (int) (tirInfo.fvRot.x * gameStates.input.kcPollTime / 131072.0f * (gameOpts->input.trackIR.sensitivity [2] + 1)); } else { viewInfo.bUsePlayerHeadAngles = 1; if (gameOpts->input.trackIR.bMove [0]) { viewInfo.playerHeadAngles[HA] = (fixang) -tirInfo.fvRot.z / 4 * (gameOpts->input.trackIR.sensitivity [0] + 1); viewInfo.playerHeadAngles[PA] = (fixang) tirInfo.fvRot.y / 4 * (gameOpts->input.trackIR.sensitivity [1] + 1); } else viewInfo.playerHeadAngles[HA] = viewInfo.playerHeadAngles[PA] = 0; if (gameOpts->input.trackIR.bMove [1]) viewInfo.playerHeadAngles[BA] = (fixang) tirInfo.fvRot.x / 4 * (gameOpts->input.trackIR.sensitivity [2] + 1); else viewInfo.playerHeadAngles[BA] = 0; } fDeadzone = 256.0f * gameOpts->input.trackIR.nDeadzone; fScale = 16384.0f / (16384.0f - fDeadzone); if (gameOpts->input.trackIR.bMove [2] && ((float) fabs (tirInfo.fvTrans.x) > fDeadzone)) { if (tirInfo.fvTrans.x < 0) tirInfo.fvTrans.x += fDeadzone; else tirInfo.fvTrans.x -= fDeadzone; Controls [0].sidewaysThrustTime -= (int) ((tirInfo.fvTrans.x - fDeadzone) * gameStates.input.kcPollTime / 65536.0f * (gameOpts->input.trackIR.sensitivity [0] + 1)); } if (gameOpts->input.trackIR.bMove [3] && ((float) fabs (tirInfo.fvTrans.y) > fDeadzone)) { if (tirInfo.fvTrans.y < 0) tirInfo.fvTrans.y += fDeadzone; else tirInfo.fvTrans.y -= fDeadzone; Controls [0].verticalThrustTime += (int) ((tirInfo.fvTrans.y - fDeadzone) * gameStates.input.kcPollTime / 65536.0f * (gameOpts->input.trackIR.sensitivity [1] + 1)); } if (gameOpts->input.trackIR.bMove [4] && ((float) fabs (tirInfo.fvTrans.z) > fDeadzone)) { if (tirInfo.fvTrans.z < 0) tirInfo.fvTrans.z += fDeadzone; else tirInfo.fvTrans.z -= fDeadzone; Controls [0].forwardThrustTime -= (int) ((tirInfo.fvTrans.z - fDeadzone) * gameStates.input.kcPollTime / 8192.0f * (gameOpts->input.trackIR.sensitivity [2] + 1)); } }