// ----------------------------------------------------------------------------------------------------------- // Determine if two OBJECTS are on a line of sight. If so, return true, else return false. // Calls fvi. int ObjectToObjectVisibility (CObject *objP1, CObject *objP2, int transType) { CHitQuery fq; CHitData hitData; int fate, nTries = 0, bSpectate = SPECTATOR (objP1); do { if (nTries++) { fq.startSeg = bSpectate ? FindSegByPos (gameStates.app.playerPos.vPos, gameStates.app.nPlayerSegment, 1, 0) : FindSegByPos (objP1->info.position.vPos, objP1->info.nSegment, 1, 0); if (fq.startSeg < 0) { fate = HIT_BAD_P0; return false; } } else fq.startSeg = bSpectate ? gameStates.app.nPlayerSegment : objP1->info.nSegment; fq.p0 = bSpectate ? &gameStates.app.playerPos.vPos : &objP1->info.position.vPos; fq.p1 = SPECTATOR (objP2) ? &gameStates.app.playerPos.vPos : &objP2->info.position.vPos; fq.radP0 = fq.radP1 = 0x10; fq.thisObjNum = OBJ_IDX (objP1); fq.ignoreObjList = NULL; fq.flags = transType; fq.bCheckVisibility = false; fate = FindHitpoint (&fq, &hitData); } while ((fate == HIT_BAD_P0) && (nTries < 2)); return (fate == HIT_NONE) || (fate == HIT_BAD_P0); }
void WiggleObject (CObject *objP) { fix xWiggle; int nParent; CObject *pParent; if (gameStates.render.nShadowPass == 2) return; if (gameOpts->app.bEpilepticFriendly) return; if (!gameStates.app.bNostalgia && (!EGI_FLAG (nDrag, 0, 0, 0) || !EGI_FLAG (bWiggle, 1, 0, 1))) return; nParent = gameData.objs.parentObjs [objP->Index ()]; pParent = (nParent < 0) ? NULL : OBJECTS + nParent; FixFastSinCos (fix (gameData.time.xGame / gameStates.gameplay.slowmo [1].fSpeed), &xWiggle, NULL); if (gameData.time.xFrame < I2X (1))// Only scale wiggle if getting at least 1 FPS, to avoid causing the opposite problem. xWiggle = FixMul (xWiggle * 20, gameData.time.xFrame); //make wiggle fps-independent (based on pre-scaled amount of wiggle at 20 FPS) if (SPECTATOR (objP)) OBJPOS (objP)->vPos += (OBJPOS (objP)->mOrient.UVec () * FixMul (xWiggle, gameData.pig.ship.player->wiggle)) * (I2X (1) / 20); else if ((objP->info.nType == OBJ_PLAYER) || !pParent) objP->mType.physInfo.velocity += objP->info.position.mOrient.UVec () * FixMul (xWiggle, gameData.pig.ship.player->wiggle); else { objP->mType.physInfo.velocity += pParent->info.position.mOrient.UVec () * FixMul (xWiggle, gameData.pig.ship.player->wiggle); objP->info.position.vPos += objP->mType.physInfo.velocity * gameData.time.xFrame; } }
int UpdateOmegaLightnings (tObject *parentObjP, tObject *targetObjP) { vmsVector vFiringPos; int bSpectate; if (!(SHOW_LIGHTNINGS && gameOpts->render.lightnings.bOmega)) return -1; if (gameData.omega.xCharge [IsMultiGame] >= MAX_OMEGA_CHARGE) DestroyOmegaLightnings (); if (gameData.laser.nLightning < 0) return 0; if (parentObjP) { if (parentObjP != gameData.laser.parentObjP) return 0; if (targetObjP != gameData.laser.targetObjP) return 0; } if ((bSpectate = SPECTATOR (gameData.laser.parentObjP))) { VmVecSub (&vFiringPos, &gameStates.app.playerPos.vPos, &gameStates.app.playerPos.mOrient.uVec); VmVecInc (&vFiringPos, &gameStates.app.playerPos.mOrient.fVec); } else { VmVecSub (&vFiringPos, &gameData.laser.parentObjP->position.vPos, &gameData.laser.parentObjP->position.mOrient.uVec); VmVecInc (&vFiringPos, &gameData.laser.parentObjP->position.mOrient.fVec); } MoveLightnings (gameData.laser.nLightning, NULL, &vFiringPos, bSpectate ? gameStates.app.nPlayerSegment : gameData.laser.parentObjP->nSegment, 1, 0); if (gameData.laser.targetObjP) MoveLightnings (gameData.laser.nLightning, NULL, &gameData.laser.targetObjP->position.vPos, gameData.laser.targetObjP->nSegment, 1, 1); return 1; }
int CreateOmegaLightnings (vmsVector *vTargetPos, tObject *parentObjP, tObject *targetObjP) { if (!(SHOW_LIGHTNINGS && gameOpts->render.lightnings.bOmega)) return 0; if (!UpdateOmegaLightnings (parentObjP, targetObjP)) { static tRgbaColorf color = {0.9f, 0.6f, 0.6f, 0.3f}; vmsVector *vEnd, vFiringPos; int bSpectate = SPECTATOR (parentObjP); tPosition *posP = bSpectate ? &gameStates.app.playerPos : &parentObjP->position; DestroyOmegaLightnings (); VmVecSub (&vFiringPos, &posP->vPos, &posP->mOrient.uVec); VmVecInc (&vFiringPos, &posP->mOrient.fVec); gameData.laser.parentObjP = parentObjP; gameData.laser.targetObjP = targetObjP; vEnd = targetObjP ? &targetObjP->position.vPos : vTargetPos; #if OMEGA_PLASMA color.alpha = gameOpts->render.lightnings.bPlasma ? 0.5f : 0.3f; #endif gameData.laser.nLightning = CreateLightning (10, &vFiringPos, vEnd, NULL, -(bSpectate ? gameStates.app.nPlayerSegment : parentObjP->nSegment) - 1, -5000, 0, VmVecDist (&vFiringPos, vEnd), F1_0 * 3, 0, 0, 100, 10, 1, 3, 1, 1, #if OMEGA_PLASMA (parentObjP != gameData.objs.viewer) || gameStates.app.bFreeCam || gameStates.render.bExternalView, #else 0, #endif 1, -1, &color); } return (gameData.laser.nLightning >= 0); }
void DoGatlingSmoke (tObject *objP) { int nModel = objP->rType.polyObjInfo.nModel; int bHires = G3HaveModel (nModel) - 1; if (bHires >= 0) { tG3Model *pm = gameData.models.g3Models [bHires] + nModel; if (pm->bBullets) { int nPlayer = objP->info.nId; int nGun = EquippedPlayerGun (objP); int bDoEffect = (bHires >= 0) && ((nGun == VULCAN_INDEX) || (nGun == GAUSS_INDEX)) && (gameData.multiplayer.weaponStates [nPlayer].firing [0].nDuration >= GATLING_DELAY); int i = gameData.multiplayer.gatlingSmoke [nPlayer]; if (bDoEffect) { int bSpectate = SPECTATOR (objP); tTransformation *posP = bSpectate ? &gameStates.app.playerPos : &objP->info.position; vmsVector *vGunPoints, vEmitter, vDir; vmsMatrix m, *viewP; if (!(vGunPoints = GetGunPoints (objP, nGun))) return; if (bSpectate) { viewP = &m; *viewP = posP->mOrient.Transpose(); } else viewP = ObjectView (objP); vEmitter = *viewP * vGunPoints[nGun]; vEmitter += posP->vPos; //vDir = posP->mOrient[FVEC]; vDir = posP->mOrient[FVEC] * (F1_0 / 8); if (i < 0) { gameData.multiplayer.gatlingSmoke [nPlayer] = CreateSmoke (&vEmitter, &vDir, &posP->mOrient, objP->info.nSegment, 1, GATLING_MAX_PARTS, F1_0 / 2, 1, 1, GATLING_PART_LIFE, GATLING_PART_SPEED, SMOKE_PARTICLES, 0x7ffffffe, smokeColors + 1, 0, -1); } else { SetSmokePos (i, &vEmitter, &posP->mOrient, objP->info.nSegment); } } else { if (i >= 0) { SetSmokeLife (i, 0); gameData.multiplayer.gatlingSmoke [nPlayer] = -1; } } } } }
void DoPlayerBullets (tObject *objP) { if (RENDERPATH && gameOpts->render.ship.bBullets) { int nModel = objP->rType.polyObjInfo.nModel; int bHires = G3HaveModel (nModel) - 1; if (bHires >= 0) { tG3Model *pm = gameData.models.g3Models [bHires] + nModel; if (pm->bBullets) { int nPlayer = objP->info.nId; int nGun = EquippedPlayerGun (objP); int bDoEffect = (bHires >= 0) && ((nGun == VULCAN_INDEX) || (nGun == GAUSS_INDEX)) && (gameData.multiplayer.weaponStates [nPlayer].firing [0].nDuration >= GATLING_DELAY); int i = gameData.multiplayer.bulletEmitters [nPlayer]; if (bDoEffect) { int bSpectate = SPECTATOR (objP); tTransformation *posP = bSpectate ? &gameStates.app.playerPos : &objP->info.position; vmsVector vEmitter, vDir; vmsMatrix m, *viewP; if (bSpectate) { viewP = &m; m = posP->mOrient.Transpose(); } else viewP = ObjectView (objP); vEmitter = *viewP * pm->vBullets; vEmitter += posP->vPos; vDir = posP->mOrient[UVEC]; vDir.Neg(); if (i < 0) { gameData.multiplayer.bulletEmitters [nPlayer] = CreateSmoke (&vEmitter, &vDir, &posP->mOrient, objP->info.nSegment, 1, BULLET_MAX_PARTS, 15.0f, 1, 1, BULLET_PART_LIFE, BULLET_PART_SPEED, BULLET_PARTICLES, 0x7fffffff, NULL, 0, -1); } else { SetSmokePos (i, &vEmitter, &posP->mOrient, objP->info.nSegment); } } else { if (i >= 0) { SetSmokeLife (i, 0); gameData.multiplayer.bulletEmitters [nPlayer] = -1; } } } } } }
void DoOmegaStuff (tObject *parentObjP, vmsVector *vFiringPos, tObject *weaponObjP) { short nTargetObj, nFiringSeg, nParentSeg; vmsVector vTargetPos; int nPlayer = parentObjP->id; int bSpectate = SPECTATOR (parentObjP); static int nDelay = 0; #if 1 if (gameStates.gameplay.bMineMineCheat && (gameData.omega.xCharge [IsMultiGame] < MAX_OMEGA_CHARGE)) gameData.omega.xCharge [IsMultiGame] = MAX_OMEGA_CHARGE - 1; #endif if (nPlayer == gameData.multiplayer.nLocalPlayer) { // If charge >= min, or (some charge and zero energy), allow to fire. if ((gameData.omega.xCharge [IsMultiGame] < MIN_OMEGA_CHARGE) && (!gameData.omega.xCharge [IsMultiGame] || gameData.multiplayer.players [nPlayer].energy)) { ReleaseObject (OBJ_IDX (weaponObjP)); DestroyOmegaLightnings (); return; } gameData.omega.xCharge [IsMultiGame] -= gameData.time.xFrame; if (gameData.omega.xCharge [IsMultiGame] < 0) gameData.omega.xCharge [IsMultiGame] = 0; // Ensure that the lightning cannon can be fired next frame. gameData.laser.xNextFireTime = gameData.time.xGame + 1; gameData.omega.nLastFireFrame = gameData.app.nFrameCount; } weaponObjP->cType.laserInfo.parentType = OBJ_PLAYER; weaponObjP->cType.laserInfo.nParentObj = gameData.multiplayer.players [nPlayer].nObject; weaponObjP->cType.laserInfo.nParentSig = gameData.objs.objects [gameData.multiplayer.players [nPlayer].nObject].nSignature; if (gameStates.limitFPS.bOmega && !gameStates.app.tick40fps.bTick) #if 1 return; if (SlowMotionActive ()) { if (nDelay > 0) { nDelay -= 2; if (nDelay > 0) return; } nDelay += gameOpts->gameplay.nSlowMotionSpeedup; } #else nTargetObj = -1; else
CFixVector *TransformGunPoint (CObject *objP, CFixVector *vGunPoints, int nGun, fix xDelay, ubyte nLaserType, CFixVector *vMuzzle, CFixMatrix *mP) { int bSpectate = SPECTATOR (objP); tObjTransformation* posP = bSpectate ? &gameStates.app.playerPos : &objP->info.position; CFixMatrix m, *viewP; CFixVector v [2]; #if FULL_COCKPIT_OFFS int bLaserOffs = ((gameStates.render.cockpit.nType == CM_FULL_COCKPIT) && (objP->Index () == LOCALPLAYER.nObject)); #else int bLaserOffs = 0; #endif if (nGun < 0) { // use center between gunPoints nGun and nGun + 1 *v = vGunPoints [-nGun] + vGunPoints [-nGun - 1]; // VmVecScale (VmVecAdd (v, vGunPoints - nGun, vGunPoints - nGun - 1), I2X (1) / 2); *v *= (I2X (1) / 2); } else { v [0] = vGunPoints [nGun]; if (bLaserOffs) v [0] += posP->mOrient.UVec () * LASER_OFFS; } if (!mP) mP = &m; if (bSpectate) { viewP = mP; *viewP = posP->mOrient.Transpose (); } else viewP = objP->View (); v[1] = *viewP * v [0]; memcpy (mP, &posP->mOrient, sizeof (CFixMatrix)); if (nGun < 0) v[1] += (*mP).UVec () * (-2 * v->Mag ()); (*vMuzzle) = posP->vPos + v [1]; // If supposed to fire at a delayed time (xDelay), then move this point backwards. if (xDelay) *vMuzzle += mP->FVec () * (-FixMul (xDelay, WI_speed (nLaserType, gameStates.app.nDifficultyLevel))); return vMuzzle; }
int CanSeePoint (CObject *objP, CFixVector *vSource, CFixVector *vDest, short nSegment, fix xRad) { CHitQuery fq; int nHitType; CHitData hitData; //see if we can see this CPlayerData fq.p0 = vSource; fq.p1 = vDest; fq.radP0 = 1; fq.radP1 = xRad; fq.thisObjNum = objP ? objP->Index () : -1; fq.flags = FQ_TRANSWALL; if (SPECTATOR (objP)) fq.startSeg = FindSegByPos (objP->info.position.vPos, objP->info.nSegment, 1, 0); else fq.startSeg = objP ? objP->info.nSegment : nSegment; fq.ignoreObjList = NULL; fq.bCheckVisibility = false; nHitType = FindHitpoint (&fq, &hitData); return nHitType != HIT_WALL; }
int FireWeaponDelayedWithSpread ( CObject *objP, ubyte nLaserType, int nGun, fix xSpreadR, fix xSpreadU, fix xDelay, int bMakeSound, int bHarmless, short nLightObj) { short nLaserSeg; int nFate; CFixVector vLaserPos, vLaserDir, *vGunPoints; CHitQuery fq; CHitData hitData; int nObject; CObject* laserP; #if FULL_COCKPIT_OFFS int bLaserOffs = ((gameStates.render.cockpit.nType == CM_FULL_COCKPIT) && (objP->Index () == LOCALPLAYER.nObject)); #else int bLaserOffs = 0; #endif CFixMatrix m; int bSpectate = SPECTATOR (objP); tObjTransformation* posP = bSpectate ? &gameStates.app.playerPos : &objP->info.position; #if DBG if (nLaserType == SMARTMINE_BLOB_ID) nLaserType = nLaserType; #endif CreateAwarenessEvent (objP, PA_WEAPON_WALL_COLLISION); // Find the initial vPosition of the laser if (!(vGunPoints = GetGunPoints (objP, nGun))) return 0; TransformGunPoint (objP, vGunPoints, nGun, xDelay, nLaserType, &vLaserPos, &m); //--------------- Find vLaserPos and nLaserSeg ------------------ fq.p0 = &posP->vPos; fq.startSeg = bSpectate ? gameStates.app.nPlayerSegment : objP->info.nSegment; fq.p1 = &vLaserPos; fq.radP0 = fq.radP1 = 0x10; fq.thisObjNum = objP->Index (); fq.ignoreObjList = NULL; fq.flags = FQ_CHECK_OBJS | FQ_IGNORE_POWERUPS; fq.bCheckVisibility = false; nFate = FindHitpoint (&fq, &hitData); nLaserSeg = hitData.hit.nSegment; if (nLaserSeg == -1) { //some sort of annoying error return -1; } //SORT OF HACK... IF ABOVE WAS CORRECT THIS WOULDNT BE NECESSARY. if (CFixVector::Dist (vLaserPos, posP->vPos) > 3 * objP->info.xSize / 2) { return -1; } if (nFate == HIT_WALL) { return -1; } #if 0 //as of 12/6/94, we don't care if the laser is stuck in an object. We //just fire away normally if (nFate == HIT_OBJECT) { if (OBJECTS [hitData.hitObject].nType == OBJ_ROBOT) OBJECTS [hitData.hitObject].Die (); if (OBJECTS [hitData.hitObject].nType != OBJ_POWERUP) return; } #endif // Now, make laser spread out. vLaserDir = m.FVec (); if (xSpreadR || xSpreadU) { vLaserDir += m.RVec () * xSpreadR; vLaserDir += m.UVec () * xSpreadU; } if (bLaserOffs) vLaserDir += m.UVec () * LASER_OFFS; nObject = CreateNewWeapon (&vLaserDir, &vLaserPos, nLaserSeg, objP->Index (), nLaserType, bMakeSound); // Omega cannon is a hack, not surprisingly. Don't want to do the rest of this stuff. if (nLaserType == OMEGA_ID) return -1; if (nObject == -1) return -1; //TrackWeaponObject (nObject, int (objP->info.nId)); laserP = OBJECTS + nObject; if ((nLaserType == GUIDEDMSL_ID) && gameData.multigame.bIsGuided) gameData.objs.guidedMissile [objP->info.nId].objP = laserP; gameData.multigame.bIsGuided = 0; if (gameData.objs.bIsMissile [nLaserType] && (nLaserType != GUIDEDMSL_ID)) { if (!gameData.objs.missileViewerP && (objP->info.nId == gameData.multiplayer.nLocalPlayer)) gameData.objs.missileViewerP = laserP; } // If this weapon is supposed to be silent, set that bit! if (!bMakeSound) laserP->info.nFlags |= OF_SILENT; // If this weapon is supposed to be silent, set that bit! if (bHarmless) laserP->info.nFlags |= OF_HARMLESS; // If the object firing the laser is the CPlayerData, then indicate the laser object so robots can dodge. // New by MK on 6/8/95, don't let robots evade proximity bombs, thereby decreasing uselessness of bombs. if ((objP == gameData.objs.consoleP) && !WeaponIsPlayerMine (laserP->info.nId)) gameStates.app.bPlayerFiredLaserThisFrame = nObject; if (gameStates.app.cheats.bHomingWeapons || gameData.weapons.info [nLaserType].homingFlag) { if (objP == gameData.objs.consoleP) { laserP->cType.laserInfo.nHomingTarget = FindHomingObject (&vLaserPos, laserP); gameData.multigame.laser.nTrack = laserP->cType.laserInfo.nHomingTarget; } else {// Some other CPlayerData shot the homing thing Assert (IsMultiGame); laserP->cType.laserInfo.nHomingTarget = gameData.multigame.laser.nTrack; } } lightClusterManager.Add (nObject, nLightObj); return nObject; }