// ----------------------------------------------------------------------------- // Fire Laser: Registers a laser fire, and performs special stuff for the fusion // cannon. void ChargeFusion (void) { if ((LOCALPLAYER.energy < I2X (2)) && (gameData.fusion.xAutoFireTime == 0)) { gameData.laser.nGlobalFiringCount = 0; } else { gameData.fusion.xFrameTime += gameData.time.xFrame; if (!gameData.FusionCharge ()) LOCALPLAYER.energy -= I2X (2); fix h = (gameData.fusion.xFrameTime <= LOCALPLAYER.energy) ? gameData.fusion.xFrameTime : LOCALPLAYER.energy; gameData.SetFusionCharge (gameData.FusionCharge () + h); LOCALPLAYER.energy -= h; if (LOCALPLAYER.energy > 0) gameData.fusion.xAutoFireTime = gameData.time.xGame + gameData.fusion.xFrameTime / 2 + 1; else { LOCALPLAYER.energy = 0; gameData.fusion.xAutoFireTime = gameData.time.xGame - 1; // Fire now! } if (gameStates.limitFPS.bFusion && !gameStates.app.tick40fps.bTick) return; float fScale = float (gameData.FusionCharge () >> 11) / 64.0f; tRgbaColorf* colorP = gameData.weapons.color + FUSION_ID; if (gameData.FusionCharge () < I2X (2)) paletteManager.BumpEffect (colorP->red * fScale, colorP->green * fScale, colorP->blue * fScale); else paletteManager.BumpEffect (colorP->blue * fScale, colorP->red * fScale, colorP->green * fScale); if (gameData.time.xGame < gameData.fusion.xLastSoundTime) //gametime has wrapped gameData.fusion.xNextSoundTime = gameData.fusion.xLastSoundTime = gameData.time.xGame; if (gameData.fusion.xNextSoundTime < gameData.time.xGame) { if (gameData.FusionCharge () > I2X (2)) { audio.PlaySound (11); gameData.objs.consoleP->ApplyDamageToPlayer (gameData.objs.consoleP, d_rand () * 4); } else { CreateAwarenessEvent (gameData.objs.consoleP, WEAPON_ROBOT_COLLISION); audio.PlaySound (SOUND_FUSION_WARMUP); if (IsMultiGame) MultiSendPlaySound (SOUND_FUSION_WARMUP, I2X (1)); } gameData.fusion.xLastSoundTime = gameData.time.xGame; gameData.fusion.xNextSoundTime = gameData.time.xGame + I2X (1) / 8 + d_rand () / 4; } gameData.fusion.xFrameTime = 0; } }
void CHUD::DrawCloak (void) { if (cockpit->Hide ()) return; static int nIdCloak = 0; if ((LOCALPLAYER.flags & PLAYER_FLAGS_CLOAKED) && ((LOCALPLAYER.cloakTime + CLOAK_TIME_MAX - gameData.time.xGame > I2X (3)) || (gameData.time.xGame & 0x8000))) { int y = CCanvas::Current ()->Height (); if (IsMultiGame) y -= 7 * m_info.nLineSpacing; else y -= 4 * m_info.nLineSpacing; if ((LOCALPLAYER.flags & PLAYER_FLAGS_AFTERBURNER) && !gameOpts->render.cockpit.bTextGauges) y -= m_info.nLineSpacing + gameStates.render.fonts.bHires + 1; fontManager.SetColorRGBi (GREEN_RGBA, 1, 0, 0); nIdCloak = GrPrintF (&nIdCloak, 2, y, "%s", TXT_CLOAKED); } }
void CStatusBar::DrawAfterburnerBar (void) { if (gameStates.app.bD1Mission) return; int nEraseHeight; CCanvas::Push (); fontManager.SetScale (floor (float (CCanvas::Current ()->Width ()) / 640.0f)); CCanvas::SetCurrent (CurrentGameScreen ()); BitBlt (SB_GAUGE_AFTERBURNER, SB_AFTERBURNER_GAUGE_X, SB_AFTERBURNER_GAUGE_Y); nEraseHeight = FixMul ((I2X (1) - gameData.physics.xAfterburnerCharge), SB_AFTERBURNER_GAUGE_H); if (nEraseHeight > 0) { glDisable (GL_BLEND); Rect (SB_AFTERBURNER_GAUGE_X, SB_AFTERBURNER_GAUGE_Y, SB_AFTERBURNER_GAUGE_X + SB_AFTERBURNER_GAUGE_W - 1, SB_AFTERBURNER_GAUGE_Y + nEraseHeight - 1); glEnable (GL_BLEND); } fontManager.SetScale (1.0f); CCanvas::Pop (); }
// Volume 0-I2X (1) int CAudio::StartSound (short nSound, int nSoundClass, fix nVolume, int nPan, int bLooping, int nLoopStart, int nLoopEnd, int nSoundObj, int nSpeed, const char *pszWAV, CFixVector* vPos) { CAudioChannel* channelP; if (!gameStates.app.bUseSound) return -1; if (!m_info.bAvailable) return -1; if (((nSoundObj > -1) || bLooping || (nVolume > I2X (1))) && !nSoundClass) nSoundClass = -1; if (!(channelP = FindFreeChannel (nSoundClass))) return -1; if (0 > channelP->Start (nSound, nSoundClass, nVolume, nPan, bLooping, nLoopStart, nLoopEnd, nSoundObj, nSpeed, pszWAV, vPos)) { return -1; } int i = m_info.nFreeChannel; if (++m_info.nFreeChannel >= MAX_SOUND_CHANNELS) m_info.nFreeChannel = 0; return i; }
int CParticleSystem::Update (void) { if (!m_bValid) return 0; CParticleEmitter *emitterP; int i = 0; if ((m_nObject == 0x7fffffff) && (m_nType == SMOKE_PARTICLES) && (gameStates.app.nSDLTicks - m_nBirth > (MAX_SHRAPNEL_LIFE / I2X (1)) * 1000)) SetLife (0); #if DBG if ((m_nObject >= 0) && (m_nObject < 0x70000000) && (OBJECTS [m_nObject].info.nType == 255)) i = i; #endif if ((emitterP = m_emitters.Buffer ())) { bool bKill = (m_nObject < 0) || ((m_nObject < 0x70000000) && ((OBJECTS [m_nObject].info.nSignature != m_nSignature) || (OBJECTS [m_nObject].info.nType == OBJ_NONE))); for (i = 0; i < m_nEmitters; ) { if (!m_emitters) return 0; if (emitterP->IsDead (gameStates.app.nSDLTicks)) { if (!RemoveEmitter (i)) { //particleManager.Destroy (m_nId); m_bDestroy = true; break; } } else { if (bKill) emitterP->SetLife (0); emitterP->Update (gameStates.app.nSDLTicks, -1); emitterP++, i++; } } } return i; }
//------------------------------------------------------------------------------ //draw an CObject that is a texture-mapped rod void DrawObjectRodTexPoly (CObject *objP, tBitmapIndex bmi, int bLit, int iFrame) { CBitmap *bmP = gameData.pig.tex.bitmaps [0] + bmi.index; fix light; CFixVector delta, top_v, bot_v; g3sPoint top_p, bot_p; LoadBitmap (bmi.index, 0); if ((bmP->Type () == BM_TYPE_STD) && bmP->Override ()) { bmP->SetupTexture (1, gameOpts->render.bDepthSort <= 0); bmP = bmP->Override (iFrame); } delta = objP->info.position.mOrient.UVec () * objP->info.xSize; top_v = objP->info.position.vPos + delta; bot_v = objP->info.position.vPos - delta; G3TransformAndEncodePoint (&top_p, top_v); G3TransformAndEncodePoint (&bot_p, bot_v); if (bLit) light = ComputeObjectLight (objP, &top_p.p3_vec); else light = I2X (1); G3DrawRodTexPoly (bmP, &bot_p, objP->info.xSize, &top_p, objP->info.xSize, light, NULL); }
void RenderPowerupCorona (CObject *objP, float red, float green, float blue, float alpha) { if ((IsEnergyPowerup (objP->info.nId) ? gameOpts->render.coronas.bPowerups : gameOpts->render.coronas.bWeapons) && LoadGlare ()) { static tRgbaColorf keyColors [3] = { {0.2f, 0.2f, 0.9f, 0.2f}, {0.9f, 0.2f, 0.2f, 0.2f}, {0.9f, 0.8f, 0.2f, 0.2f} }; tRgbaColorf color; fix xSize; float fScale; if ((objP->info.nId >= POW_KEY_BLUE) && (objP->info.nId <= POW_KEY_GOLD)) { int i = objP->info.nId - POW_KEY_BLUE; color = keyColors [(((i < 0) || (i > 2)) ? 3 : i)]; xSize = I2X (12); } else { float b = (float) sqrt ((red * 3 + green * 5 + blue * 2) / 10); color.red = red / b; color.green = green / b; color.blue = blue / b; xSize = 2 * objP->info.xSize; //I2X (8); } color.alpha = alpha; fScale = coronaIntensities [gameOpts->render.coronas.nObjIntensity] / 2; color.red *= fScale; color.green *= fScale; color.blue *= fScale; bmpGlare->SetColor (&color); ogl.RenderSprite (bmpGlare, objP->info.position.vPos, xSize, xSize, alpha, LIGHTTRAIL_BLENDMODE, 5); bmpGlare->SetColor (NULL); } }
void CCockpit::DrawAfterburnerBar (void) { #if 1 if (!(LOCALPLAYER.flags & PLAYER_FLAGS_AFTERBURNER)) return; //don't draw if don't have if (!gameData.physics.xAfterburnerCharge) return; #endif //CCanvas::Current ()->SetColorRGB (255, 255, 255, 255); BitBlt (GAUGE_AFTERBURNER, AFTERBURNER_GAUGE_X, AFTERBURNER_GAUGE_Y); int yMax = FixMul (I2X (1) - gameData.physics.xAfterburnerCharge, AFTERBURNER_GAUGE_H); if (yMax) { int x [4], y [4]; ubyte* tableP = gameStates.video.nDisplayMode ? afterburnerBarTableHires : afterburnerBarTable; y [0] = y [1] = ScaleY (AFTERBURNER_GAUGE_Y); y [3] = ScaleY (AFTERBURNER_GAUGE_Y + yMax) - 1; x [1] = ScaleX (AFTERBURNER_GAUGE_X + tableP [0]); x [0] = ScaleX (AFTERBURNER_GAUGE_X + tableP [1] + 1); x [2] = x [1]; y [2] = 0; for (int i = 1; i < yMax - 1; i++) if (x [2] >= tableP [2 * i]) { x [2] = tableP [2 * i]; y [2] = i; } x [2] = ScaleX (AFTERBURNER_GAUGE_X + x [2] + 1); y [2] = ScaleY (AFTERBURNER_GAUGE_Y + y [2]); x [3] = ScaleX (AFTERBURNER_GAUGE_X + tableP [2 * yMax - 1] + 1); gameStates.render.grAlpha = 1.0f; glEnable (GL_BLEND); glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); OglDrawFilledPoly (x, y, 4, gaugeFadeColors [0], 1); glDisable (GL_BLEND); } }
int CObject::PowerupToDevice (void) { CAngleVector a; short nModel, nId; int bHasModel = 0; if (!SHOW_OBJ_FX) return 0; if (!gameOpts->render.powerups.b3D) return 0; if (info.controlType == CT_WEAPON) return 1; if ((info.nType != OBJ_POWERUP) && (info.nType != OBJ_WEAPON)) return 0; nModel = PowerupToModel (info.nId); if (nModel) nId = info.nId; else { nId = PowerupToObject (info.nId); if (nId >= 0) { nModel = gameData.weapons.info [nId].nModel; bHasModel = 1; } } if (!bHasModel && ((info.nType != OBJ_WEAPON) || !gameData.objs.bIsMissile [info.nId]) && !(nModel && HaveReplacementModel (nModel))) return 0; if (gameData.demo.nState != ND_STATE_PLAYBACK) { a[PA] = (rand () % I2X (1)) - I2X (1) / 2; a[BA] = (rand () % I2X (1)) - I2X (1) / 2; a[HA] = (rand () % I2X (1)) - I2X (1) / 2; info.position.mOrient = CFixMatrix::Create(a); } mType.physInfo.mass = I2X (1); mType.physInfo.drag = 512; mType.physInfo.brakes = 0; #if 0 if ((info.nType == OBJ_WEAPON) && gameData.objs.bIsMissile [info.nId]) #endif { mType.physInfo.rotVel[X] = 0; mType.physInfo.rotVel[Y] = mType.physInfo.rotVel[Z] = gameOpts->render.powerups.nSpin ? I2X (1) / (5 - gameOpts->render.powerups.nSpin) : 0; } #if 0 else { mType.physInfo.rotVel[X] = mType.physInfo.rotVel[Z] = 0; mType.physInfo.rotVel[Y] = gameOpts->render.powerups.nSpin ? I2X (1) / (5 - gameOpts->render.powerups.nSpin) : 0; } #endif info.controlType = CT_WEAPON; info.renderType = RT_POLYOBJ; info.movementType = MT_PHYSICS; mType.physInfo.flags = PF_BOUNCE | PF_FREE_SPINNING; rType.polyObjInfo.nModel = nModel; #if 1 if (bHasModel) info.xSize = gameData.models.polyModels [0][rType.polyObjInfo.nModel].Rad (); #endif rType.polyObjInfo.nTexOverride = -1; info.xLifeLeft = IMMORTAL_TIME; return 1; }
void DoPlayerSmoke (tObject *objP, int i) { int h, j, d, nParts, nType; float nScale; tCloud *pCloud; vmsVector fn, mn, vDir, *vDirP; tThrusterInfo ti; static int bForward = 1; if (i < 0) i = objP->info.nId; if ((gameData.multiplayer.players [i].flags & PLAYER_FLAGS_CLOAKED) || (gameStates.render.automap.bDisplay && IsMultiGame && !AM_SHOW_PLAYERS)) { KillObjectSmoke (i); return; } j = OBJ_IDX (objP); if (gameOpts->render.smoke.bDecreaseLag && (i == gameData.multiplayer.nLocalPlayer)) { fn = objP->info.position.mOrient[FVEC]; mn = objP->info.position.vPos - objP->info.vLastPos; vmsVector::Normalize(fn); vmsVector::Normalize(mn); d = vmsVector::Dot(fn, mn); if (d >= -F1_0 / 2) bForward = 1; else { if (bForward) { if ((h = gameData.smoke.objects [j]) >= 0) { KillObjectSmoke (j); DestroySmoke (h); } bForward = 0; nScale = 0; return; } } } #if 0 if (EGI_FLAG (bThrusterFlames, 1, 1, 0)) { if ((a <= F1_0 / 4) && (a || !gameStates.input.bControlsSkipFrame)) //no thruster flames if moving backward DropAfterburnerBlobs (objP, 2, I2X (1), -1, gameData.objs.consoleP, 1); //F1_0 / 4); } #endif if ((gameData.app.nGameMode & GM_NETWORK) && !gameData.multiplayer.players [i].connected) nParts = 0; else if (objP->info.nFlags & (OF_SHOULD_BE_DEAD | OF_DESTROYED)) nParts = 0; else if ((i == gameData.multiplayer.nLocalPlayer) && (gameStates.app.bPlayerIsDead || (gameData.multiplayer.players [i].shields < 0))) nParts = 0; else { h = X2IR (gameData.multiplayer.players [i].shields); nParts = 10 - h / 5; nScale = X2F (objP->info.xSize); if (h <= 25) nScale /= 1.5; else if (h <= 50) nScale /= 2; else nScale /= 3; if (nParts <= 0) { nType = 2; //nParts = (gameStates.entropy.nTimeLastMoved < 0) ? 250 : 125; } else { CreateDamageExplosion (nParts, j); nType = (h > 25); nParts *= 25; nParts += 75; } nParts = objP->mType.physInfo.thrust.IsZero() ? SHIP_MAX_PARTS : SHIP_MAX_PARTS / 2; if (SHOW_SMOKE && nParts && gameOpts->render.smoke.bPlayers) { if (gameOpts->render.smoke.bSyncSizes) { nParts = -MAX_PARTICLES (nParts, gameOpts->render.smoke.nDens [0]); nScale = PARTICLE_SIZE (gameOpts->render.smoke.nSize [0], nScale); } else { nParts = -MAX_PARTICLES (nParts, gameOpts->render.smoke.nDens [1]); nScale = PARTICLE_SIZE (gameOpts->render.smoke.nSize [1], nScale); } if (!objP->mType.physInfo.thrust.IsZero ()) vDirP = NULL; else { // if the ship is standing still, let the thruster smoke move away from it nParts /= 2; nScale /= 2; vDir = OBJPOS (objP)->mOrient [FVEC] * (F1_0 / 8); vDir = -vDir; vDirP = &vDir; } if (0 > (h = gameData.smoke.objects [j])) { //PrintLog ("creating tPlayer smoke\n"); h = SetSmokeObject (j, CreateSmoke (&objP->info.position.vPos, vDirP, NULL, objP->info.nSegment, 2, nParts, nScale, gameOpts->render.smoke.nSize [1], 2, PLR_PART_LIFE / (nType + 1) * (vDirP ? 2 : 1), PLR_PART_SPEED, SMOKE_PARTICLES, j, smokeColors + nType, 1, -1)); } else { if (vDirP) SetSmokeDir (h, vDirP); SetSmokeLife (h, PLR_PART_LIFE / (nType + 1) * (vDirP ? 2 : 1)); SetSmokeType (h, SMOKE_PARTICLES); SetSmokePartScale (h, -nScale); SetSmokeDensity (h, nParts, gameOpts->render.smoke.bSyncSizes ? -1 : gameOpts->render.smoke.nSize [1]); SetSmokeSpeed (gameData.smoke.objects [i], objP->mType.physInfo.thrust.IsZero () ? PLR_PART_SPEED * 2 : PLR_PART_SPEED); } CalcThrusterPos (objP, &ti, 0); for (j = 0; j < 2; j++) if ((pCloud = GetCloud (h, j))) SetCloudPos (pCloud, ti.vPos + j, NULL, objP->info.nSegment); DoGatlingSmoke (objP); return; } } KillObjectSmoke (i); KillGatlingSmoke (objP); }
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); }
// ----------------------------------------------------------------------------- //if an effect is hit, and it can blow up, then blow it up //returns true if it blew up int CSegment::CheckEffectBlowup (int nSide, CFixVector& vHit, CObject* blowerP, int bForceBlowup) { int tm, tmf, ec, nBitmap = 0; int bOkToBlow = 0, nSwitchType = -1; short nSound, bPermaTrigger; ubyte vc; fix u, v; fix xDestSize; tEffectClip* ecP = NULL; CBitmap* bmP; CWall* wallP; CTrigger* trigP; CObject* parentP = (!blowerP || (blowerP->cType.laserInfo.parent.nObject < 0)) ? NULL : OBJECTS + blowerP->cType.laserInfo.parent.nObject; // If this CWall has a CTrigger and the blowerP-upper is not the CPlayerData or the buddy, abort! if (parentP) { if ((parentP->info.nType == OBJ_ROBOT) && ROBOTINFO (parentP->info.nId).companion) bOkToBlow = 1; if (!(bOkToBlow || (parentP->info.nType == OBJ_PLAYER)) && ((wallP = Wall (nSide)) && (wallP->nTrigger < gameData.trigs.m_nTriggers))) return 0; } if (!(tm = m_sides [nSide].m_nOvlTex)) return 0; tmf = m_sides [nSide].m_nOvlOrient; //tm flags ec = gameData.pig.tex.tMapInfoP [tm].nEffectClip; if (ec < 0) { if (gameData.pig.tex.tMapInfoP [tm].destroyed == -1) return 0; nBitmap = -1; nSwitchType = 0; } else { ecP = gameData.eff.effectP + ec; if (ecP->flags & EF_ONE_SHOT) return 0; nBitmap = ecP->nDestBm; if (nBitmap < 0) return 0; nSwitchType = 1; } //check if it's an animation (monitor) or casts light bmP = gameData.pig.tex.bitmapP + gameData.pig.tex.bmIndexP [tm].index; LoadBitmap (gameData.pig.tex.bmIndexP [tm].index, gameStates.app.bD1Data); //this can be blown up...did we hit it? if (!bForceBlowup) { HitPointUV (nSide, &u, &v, NULL, vHit, 0); //evil: always say face zero bForceBlowup = !PixelTranspType (tm, tmf, m_sides [nSide].m_nFrame, u, v); } if (!bForceBlowup) return 0; if (IsMultiGame && netGame.bIndestructibleLights && !nSwitchType) return 0; //note: this must get called before the texture changes, //because we use the light value of the texture to change //the static light in the CSegment wallP = Wall (nSide); bPermaTrigger = (trigP = Trigger (nSide)) && (trigP->flags & TF_PERMANENT); if (!bPermaTrigger) SubtractLight (Index (), nSide); if (gameData.demo.nState == ND_STATE_RECORDING) NDRecordEffectBlowup (Index (), nSide, vHit); if (nSwitchType) { xDestSize = ecP->xDestSize; vc = ecP->nDestVClip; } else { xDestSize = I2X (20); vc = 3; } /*Object*/CreateExplosion (short (Index ()), vHit, xDestSize, vc); if (nSwitchType) { if ((nSound = gameData.eff.vClipP [vc].nSound) != -1) audio.CreateSegmentSound (nSound, Index (), 0, vHit); if ((nSound = ecP->nSound) != -1) //kill sound audio.DestroySegmentSound (Index (), nSide, nSound); if (!bPermaTrigger && (ecP->nDestEClip != -1) && (gameData.eff.effectP [ecP->nDestEClip].nSegment == -1)) { tEffectClip *newEcP = gameData.eff.effectP + ecP->nDestEClip; int nNewBm = newEcP->changingWallTexture; if (ChangeTextures (-1, nNewBm)) { newEcP->xTimeLeft = EffectFrameTime (newEcP); newEcP->nCurFrame = 0; newEcP->nSegment = Index (); newEcP->nSide = nSide; newEcP->flags |= EF_ONE_SHOT | ecP->flags; newEcP->flags &= ~EF_INITIALIZED; newEcP->nDestBm = ecP->nDestBm; Assert ((nNewBm != 0) && (m_sides [nSide].m_nOvlTex != 0)); m_sides [nSide].m_nOvlTex = nNewBm; //replace with destoyed } } else { Assert ((nBitmap != 0) && (m_sides [nSide].m_nOvlTex != 0)); if (!bPermaTrigger) m_sides [nSide].m_nOvlTex = nBitmap; //replace with destoyed } } else { if (!bPermaTrigger) m_sides [nSide].m_nOvlTex = gameData.pig.tex.tMapInfoP [tm].destroyed; //assume this is a light, and play light sound audio.CreateSegmentSound (SOUND_LIGHT_BLOWNUP, Index (), 0, vHit); } return 1; //blew up! }
void NetworkHandlePingReturn (ubyte nPlayer) { if ((nPlayer >= gameData.multiplayer.nPlayers) || !pingStats [nPlayer].launchTime) { #if 1 console.printf (CON_DBG, "Got invalid PING RETURN from %s!\n", gameData.multiplayer.players [nPlayer].callsign); #endif return; } xPingReturnTime = TimerGetFixedSeconds (); pingStats [nPlayer].ping = X2I (FixMul (xPingReturnTime - pingStats [nPlayer].launchTime, I2X (1000))); if (!gameStates.render.cockpit.bShowPingStats) HUDInitMessage ("Ping time for %s is %d ms!", gameData.multiplayer.players [nPlayer].callsign, pingStats [nPlayer].ping); pingStats [nPlayer].launchTime = 0; pingStats [nPlayer].received++; }
void NetworkDoFrame (int bForce, int bListen) { tFrameInfoShort shortSyncPack; static fix xLastEndlevel = 0; int i; if (!(gameData.app.nGameMode & GM_NETWORK)) return; if ((networkData.nStatus == NETSTAT_PLAYING) && !gameStates.app.bEndLevelSequence) { // Don't send postion during escape sequence... if (nakedData.nLength) { Assert (nakedData.nDestPlayer >- 1); if (gameStates.multi.nGameType >= IPX_GAME) IPXSendPacketData (reinterpret_cast<ubyte*> (nakedData.buf), nakedData.nLength, netPlayers.players [nakedData.nDestPlayer].network.ipx.server, netPlayers.players [nakedData.nDestPlayer].network.ipx.node, gameData.multiplayer.players [nakedData.nDestPlayer].netAddress); nakedData.nLength = 0; nakedData.nDestPlayer = -1; } if (networkData.refuse.bWaitForAnswer && TimerGetApproxSeconds ()> (networkData.refuse.xTimeLimit+ (I2X (12)))) networkData.refuse.bWaitForAnswer=0; networkData.xLastSendTime += gameData.time.xFrame; networkData.xLastTimeoutCheck += gameData.time.xFrame; // Send out packet PacksPerSec times per second maximum... unless they fire, then send more often... if ((networkData.xLastSendTime > I2X (1) / PacketsPerSec ()) || (gameData.multigame.laser.bFired) || bForce || networkData.bPacketUrgent) { if (LOCALPLAYER.connected) { int nObject = LOCALPLAYER.nObject; networkData.bPacketUrgent = 0; if (bListen) { MultiSendRobotFrame (0); MultiSendFire (); // Do firing if needed.. } networkData.xLastSendTime = 0; if (netGame.bShortPackets) { #if defined (WORDS_BIGENDIAN) || defined (__BIG_ENDIAN__) ubyte send_data [MAX_PACKETSIZE]; #endif memset (&shortSyncPack, 0, sizeof (shortSyncPack)); CreateShortPos (&shortSyncPack.objPos, OBJECTS+nObject, 0); shortSyncPack.nType = PID_PDATA; shortSyncPack.nPlayer = gameData.multiplayer.nLocalPlayer; shortSyncPack.objRenderType = OBJECTS [nObject].info.renderType; shortSyncPack.nLevel = gameData.missions.nCurrentLevel; shortSyncPack.dataSize = networkData.syncPack.dataSize; memcpy (shortSyncPack.data, networkData.syncPack.data, networkData.syncPack.dataSize); networkData.syncPack.nPackets = INTEL_INT (gameData.multiplayer.players [0].nPacketsSent++); shortSyncPack.nPackets = networkData.syncPack.nPackets; #if !(defined (WORDS_BIGENDIAN) || defined (__BIG_ENDIAN__)) IpxSendGamePacket ( reinterpret_cast<ubyte*> (&shortSyncPack), sizeof (tFrameInfoShort) - networkData.nMaxXDataSize + networkData.syncPack.dataSize); #else SquishShortFrameInfo (shortSyncPack, send_data); IpxSendGamePacket ( reinterpret_cast<ubyte*> (send_data), IPX_SHORT_INFO_SIZE-networkData.nMaxXDataSize+networkData.syncPack.dataSize); #endif } else {// If long packets int send_dataSize; networkData.syncPack.nType = PID_PDATA; networkData.syncPack.nPlayer = gameData.multiplayer.nLocalPlayer; networkData.syncPack.objRenderType = OBJECTS [nObject].info.renderType; networkData.syncPack.nLevel = gameData.missions.nCurrentLevel; networkData.syncPack.nObjSeg = OBJECTS [nObject].info.nSegment; networkData.syncPack.objPos = OBJECTS [nObject].info.position.vPos; networkData.syncPack.objOrient = OBJECTS [nObject].info.position.mOrient; networkData.syncPack.physVelocity = OBJECTS [nObject].mType.physInfo.velocity; networkData.syncPack.physRotVel = OBJECTS [nObject].mType.physInfo.rotVel; send_dataSize = networkData.syncPack.dataSize; // do this so correct size data is sent #if defined (WORDS_BIGENDIAN) || defined (__BIG_ENDIAN__) // do the swap stuff if (gameStates.multi.nGameType >= IPX_GAME) { networkData.syncPack.nObjSeg = INTEL_SHORT (networkData.syncPack.nObjSeg); INTEL_VECTOR (networkData.syncPack.objPos); INTEL_MATRIX (networkData.syncPack.objOrient); INTEL_VECTOR (networkData.syncPack.physVelocity); INTEL_VECTOR (networkData.syncPack.physRotVel); networkData.syncPack.dataSize = INTEL_SHORT (networkData.syncPack.dataSize); } #endif networkData.syncPack.nPackets = INTEL_INT (gameData.multiplayer.players [0].nPacketsSent++); IpxSendGamePacket ( reinterpret_cast<ubyte*> (&networkData.syncPack), sizeof (tFrameInfo) - networkData.nMaxXDataSize + send_dataSize); } networkData.syncPack.dataSize = 0; // Start data over at 0 length. networkData.bD2XData = 0; if (gameData.reactor.bDestroyed) { if (gameStates.app.bPlayerIsDead) LOCALPLAYER.connected=3; if (TimerGetApproxSeconds () > (xLastEndlevel+ (I2X (1)/2))) { NetworkSendEndLevelPacket (); xLastEndlevel = TimerGetApproxSeconds (); } } } } if (!bListen) return; if ((networkData.xLastTimeoutCheck > I2X (1)) && !gameData.reactor.bDestroyed) { fix t = (fix) SDL_GetTicks (); // Check for CPlayerData timeouts for (i = 0; i < gameData.multiplayer.nPlayers; i++) { if ((i != gameData.multiplayer.nLocalPlayer) && ((gameData.multiplayer.players [i].connected == 1) || downloadManager.Downloading (i))) { if ((networkData.nLastPacketTime [i] == 0) || (networkData.nLastPacketTime [i] + downloadManager.GetTimeoutSecs () * 1000 > t)) { ResetPlayerTimeout (i, t); continue; } #if 1//!DBG if (gameOpts->multi.bTimeoutPlayers && (t - networkData.nLastPacketTime [i] > 15000)) NetworkTimeoutPlayer (i); #endif } } networkData.xLastTimeoutCheck = 0; } } if (!bListen) { networkData.syncPack.dataSize = 0; return; } NetworkListen (); #if 0 if ((networkData.sync.nPlayer != -1) && !(gameData.app.nFrameCount & 63)) ResendSyncDueToPacketLoss (); // This will resend to network_player_rejoining #endif NetworkDoSyncFrame (); if (NetworkIAmMaster ()) tracker.AddServer (); }
float WallAlpha (short nSegment, short nSide, short nWall, ubyte widFlags, int bIsMonitor, ubyte bAdditive, tRgbaColorf *colorP, int *nColor, ubyte *bTextured, ubyte *bCloaked, ubyte* bTransparent) { static tRgbaColorf cloakColor = {1, 1, 1, 0}; CWall *wallP; float fAlpha, fMaxColor; short c; if (!IS_WALL (nWall)) return 1; #if DBG if ((nSegment == nDbgSeg) && ((nDbgSide < 0) || (nSide == nDbgSide))) nDbgSeg = nDbgSeg; #endif if (!(wallP = WALLS + nWall)) return 1; if (SHOW_DYN_LIGHT) { *bTransparent = (wallP->state == WALL_DOOR_CLOAKING) || (wallP->state == WALL_DOOR_DECLOAKING); *bCloaked = !*bTransparent && ((widFlags & WID_CLOAKED_FLAG) != 0); } else { *bTransparent = 0; *bCloaked = (wallP->state == WALL_DOOR_CLOAKING) || (wallP->state == WALL_DOOR_DECLOAKING) || ((widFlags & WID_CLOAKED_FLAG) != 0); } if (*bCloaked || *bTransparent || (widFlags & WID_TRANSPARENT_FLAG)) { if (bIsMonitor) return 1; c = wallP->cloakValue; if (*bCloaked || *bTransparent) { *colorP = cloakColor; *nColor = 1; *bTextured = !*bCloaked; colorP->alpha = (c >= FADE_LEVELS) ? 0 : 1.0f - float (c) / float (FADE_LEVELS); if (*bTransparent) colorP->red = colorP->green = colorP->blue = colorP->alpha; #if DBG if (colorP->alpha < 1) return colorP->alpha; #endif return colorP->alpha; } if (!gameOpts->render.color.bWalls) c = 0; if (WALLS [nWall].hps) fAlpha = (float) fabs ((1.0f - (float) WALLS [nWall].hps / ((float) I2X (100)))); else if (IsMultiGame && gameStates.app.bHaveExtraGameInfo [1]) fAlpha = COMPETITION ? 0.5f : (float) (FADE_LEVELS - extraGameInfo [1].grWallTransparency) / (float) FADE_LEVELS; else fAlpha = 1.0f - extraGameInfo [0].grWallTransparency / (float) FADE_LEVELS; if (fAlpha < 1) { //fAlpha = (float) sqrt (fAlpha); paletteManager.Game ()->ToRgbaf ((ubyte) c, *colorP); if (bAdditive) { colorP->red /= fAlpha; colorP->green /= fAlpha; colorP->blue /= fAlpha; } fMaxColor = colorP->red; if (fMaxColor < colorP->green) fMaxColor = colorP->green; if (fMaxColor < colorP->blue) fMaxColor = colorP->blue; if (fMaxColor > 1) { colorP->red /= fMaxColor; colorP->green /= fMaxColor; colorP->blue /= fMaxColor; } *bTextured = 0; *nColor = 1; } return colorP->alpha = fAlpha; } if (gameStates.app.bD2XLevel) { c = wallP->cloakValue; return colorP->alpha = (c && (c < FADE_LEVELS)) ? (float) (FADE_LEVELS - c) / (float) FADE_LEVELS : 1; } if (gameOpts->render.effects.bAutoTransparency && IsTransparentTexture (SEGMENTS [nSegment].m_sides [nSide].m_nBaseTex)) return colorP->alpha = 0.8f; return colorP->alpha = 1; }
// -------------------------------------------------------------------------------------------------------------------- // 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); }
void RenderLaserCorona (CObject *objP, tRgbaColorf *colorP, float alpha, float fScale) { if (!SHOW_OBJ_FX) return; if (SHOW_SHADOWS && (gameStates.render.nShadowPass != 1)) return; if (gameOpts->render.coronas.bShots && LoadGlare ()) { tHitbox* phb = &gameData.models.hitboxes [objP->rType.polyObjInfo.nModel].hitboxes [0]; float fLength = X2F (phb->vMax [Z] - phb->vMin [Z]) / 2; tRgbaColorf color; static CFloatVector vEye = CFloatVector::ZERO; colorP->alpha = alpha; float fScale = coronaIntensities [gameOpts->render.coronas.nObjIntensity] / 2; color = *colorP; colorP = &color; color.red *= fScale; color.green *= fScale; color.blue *= fScale; bmpGlare->SetColor (colorP); ogl.RenderSprite (bmpGlare, objP->info.position.vPos + objP->info.position.mOrient.FVec () * (F2X (fLength - 0.5f)), I2X (1), I2X (1), alpha, LIGHTTRAIL_BLENDMODE, 1); bmpGlare->SetColor (NULL); } }
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; }
int CParticle::Update (int nCurTime) { int j, nRad; short nSegment; fix t, dot; CFixVector vPos, drift; fix drag = (m_nType == BUBBLE_PARTICLES) ? I2X (1) : F2X ((float) m_nLife / (float) m_nTTL); if ((m_nLife <= 0) /*|| (m_color [0].alpha < 0.01f)*/) return 0; t = nCurTime - m_nMoved; if (m_nDelay > 0) m_nDelay -= t; else { vPos = m_vPos; drift = m_vDrift; if ((m_nType == SMOKE_PARTICLES) /*|| (m_nType == BUBBLE_PARTICLES)*/) { drift [X] = ChangeDir (drift [X]); drift [Y] = ChangeDir (drift [Y]); drift [Z] = ChangeDir (drift [Z]); } for (j = 0; j < 2; j++) { if (t < 0) t = -t; m_vPos = vPos + drift * t; //(I2X (t) / 1000); if (m_bHaveDir) { CFixVector vi = drift, vj = m_vDir; CFixVector::Normalize (vi); CFixVector::Normalize (vj); // if (CFixVector::Dot (drift, m_vDir) < 0) if (CFixVector::Dot (vi, vj) < 0) drag = -drag; // VmVecScaleInc (&drift, &m_vDir, drag); m_vPos += m_vDir * drag; } if ((m_nType == BUBBLE_PARTICLES) || (m_nTTL - m_nLife > I2X (1) / 16)) { nSegment = FindSegByPos (m_vPos, m_nSegment, 0, 0, 1); if (nSegment < 0) { #if DBG if (m_nSegment == nDbgSeg) nSegment = FindSegByPos (m_vPos, m_nSegment, 1, 0, 1); #endif nSegment = FindSegByPos (m_vPos, m_nSegment, 0, 1, 1); if (nSegment < 0) return 0; } if ((m_nType == BUBBLE_PARTICLES) && (SEGMENTS [nSegment].m_nType != SEGMENT_IS_WATER)) return 0; m_nSegment = nSegment; } if (gameOpts->render.particles.bCollisions && CollideWithWall ()) { //Reflect the particle if (m_nType == BUBBLE_PARTICLES) return 0; if (j) return 0; else if (!(dot = CFixVector::Dot (drift, *wallNorm))) return 0; else { drift = m_vDrift + *wallNorm * (-2 * dot); //VmVecScaleAdd (&m_vPos, &vPos, &drift, 2 * t); m_nBounce = 3; continue; } } else if (m_nBounce) m_nBounce--; else { break; } } m_vDrift = drift; if (m_nTTL >= 0) { #if SMOKE_SLOWMO m_nLife -= (int) (t / gameStates.gameplay.slowmo [0].fSpeed); #else m_nLife -= t; #endif if ((m_nType == SMOKE_PARTICLES) && (nRad = m_nRad)) { if (m_bBlowUp) { if (m_nWidth >= nRad) m_nRad = 0; else { m_nWidth += nRad / 10 / m_bBlowUp; m_nHeight += nRad / 10 / m_bBlowUp; if (m_nWidth > nRad) m_nWidth = nRad; if (m_nHeight > nRad) m_nHeight = nRad; m_color [0].alpha *= (1.0f + 0.0725f / m_bBlowUp); if (m_color [0].alpha > 1) m_color [0].alpha = 1; } } else { if (m_nWidth <= nRad) m_nRad = 0; else { m_nRad += nRad / 5; m_color [0].alpha *= 1.0725f; if (m_color [0].alpha > 1) m_color [0].alpha = 1; } } } } } m_nMoved = nCurTime; return 1; }
int CParticle::Create (CFixVector *vPos, CFixVector *vDir, CFixMatrix *mOrient, short nSegment, int nLife, int nSpeed, char nParticleSystemType, char nClass, float nScale, tRgbaColorf *colorP, int nCurTime, int bBlowUp, float fBrightness, CFixVector *vEmittingFace) { static tRgbaColorf defaultColor = {1,1,1,1}; tRgbaColorf color; CFixVector vDrift; int nRad, nFrames, nType = particleImageManager.GetType (nParticleSystemType); if (nScale < 0) nRad = (int) -nScale; else if (gameOpts->render.particles.bSyncSizes) nRad = (int) PARTICLE_SIZE (gameOpts->render.particles.nSize [0], nScale); else nRad = (int) nScale; if (!nRad) nRad = I2X (1); m_nType = nType; m_bEmissive = (nParticleSystemType == LIGHT_PARTICLES); m_nClass = nClass; m_nSegment = nSegment; m_nBounce = 0; color = colorP ? *colorP : defaultColor; m_color [0] = m_color [1] = color; if ((nType == BULLET_PARTICLES) || (nType == BUBBLE_PARTICLES)) { m_bBright = 0; m_nFade = -1; } else { m_bBright = (nType == SMOKE_PARTICLES) ? (rand () % 50) == 0 : 0; if (colorP) { if (nType != LIGHT_PARTICLES) { m_color [0].red *= RANDOM_FADE; m_color [0].green *= RANDOM_FADE; m_color [0].blue *= RANDOM_FADE; } m_nFade = 0; } else { m_color [0].red = 1.0f; m_color [0].green = 0.5f; m_color [0].blue = 0.0f; m_nFade = 2; } if (m_bEmissive) m_color [0].alpha = (float) (SMOKE_START_ALPHA + 64) / 255.0f; else if (nParticleSystemType != GATLING_PARTICLES) { if (!colorP) m_color [0].alpha = (float) (SMOKE_START_ALPHA + randN (64)) / 255.0f; else { if (colorP->alpha < 0) m_color [0].alpha = -colorP->alpha; else { if (2 == (m_nFade = (char) colorP->alpha)) { m_color [0].red = 1.0f; m_color [0].green = 0.5f; m_color [0].blue = 0.0f; } m_color [0].alpha = (float) (SMOKE_START_ALPHA + randN (64)) / 255.0f; } } } #if 1 if (gameOpts->render.particles.bDisperse && !m_bBright) { fBrightness = 1.0f - fBrightness; m_color [0].alpha += fBrightness * fBrightness / 8.0f; } #endif } //nSpeed = (int) (sqrt (nSpeed) * (float) I2X (1)); nSpeed *= I2X (1); if (vDir) { CAngleVector a; CFixMatrix m; float d; a [PA] = randN (I2X (1) / 4) - I2X (1) / 8; a [BA] = randN (I2X (1) / 4) - I2X (1) / 8; a [HA] = randN (I2X (1) / 4) - I2X (1) / 8; m = CFixMatrix::Create (a); vDrift = m * (*vDir); CFixVector::Normalize (vDrift); d = (float) CFixVector::DeltaAngle (vDrift, *vDir, NULL); if (d) { d = (float) exp ((I2X (1) / 8) / d); nSpeed = (fix) ((float) nSpeed / d); } #if 0 if (!colorP) // hack for static particleSystem w/o user defined color m_color [0].green = m_color [0].blue = 1.0f; #endif vDrift *= nSpeed; if ((nType == SMOKE_PARTICLES) || (nType == BUBBLE_PARTICLES)) m_vDir = *vDir * (I2X (3) / 4 + I2X (randN (16)) / 64); else m_vDir = *vDir; m_bHaveDir = 1; } else { CFixVector vOffs; vDrift [X] = nSpeed - randN (2 * nSpeed); vDrift [Y] = nSpeed - randN (2 * nSpeed); vDrift [Z] = nSpeed - randN (2 * nSpeed); vOffs = vDrift; m_vDir.SetZero (); m_bHaveDir = 1; } m_vDrift = vDrift; if (vEmittingFace) m_vPos = *RandomPointOnQuad (vEmittingFace, vPos); else if (nType != BUBBLE_PARTICLES) m_vPos = *vPos + vDrift * (I2X (1) / 64); else { //m_vPos = *vPos + vDrift * (I2X (1) / 32); nSpeed = vDrift.Mag () / 16; vDrift = CFixVector::Avg ((*mOrient).RVec () * (nSpeed - randN (2 * nSpeed)), (*mOrient).UVec () * (nSpeed - randN (2 * nSpeed))); m_vPos = *vPos + vDrift + (*mOrient).FVec () * (I2X (1) / 2 - randN (I2X (1))); #if 1 m_vDrift.SetZero (); #else CFixVector::Normalize (m_vDrift); m_vDrift *= I2X (32); #endif } if ((nType != BUBBLE_PARTICLES) && mOrient) { CAngleVector vRot; CFixMatrix mRot; vRot [BA] = 0; vRot [PA] = 2048 - ((d_rand () % 9) * 512); vRot [HA] = 2048 - ((d_rand () % 9) * 512); mRot = CFixMatrix::Create (vRot); m_mOrient = *mOrient * mRot; } if (nLife < 0) nLife = -nLife; if (nType == SMOKE_PARTICLES) { if (gameOpts->render.particles.bDisperse) nLife = (nLife * 2) / 3; nLife = nLife / 2 + randN (nLife / 2); } m_nLife = m_nTTL = nLife; m_nMoved = nCurTime; m_nDelay = 0; //bStart ? randN (nLife) : 0; if (nType == SMOKE_PARTICLES) nRad += randN (nRad); else if (nType == BUBBLE_PARTICLES) nRad = nRad / 10 + randN (9 * nRad / 10); else nRad *= 2; if ((m_bBlowUp = bBlowUp)) { m_nRad = nRad / 2; m_nWidth = m_nHeight = m_nRad; m_nRad += m_nRad / bBlowUp; } else { m_nWidth = m_nHeight = nRad; m_nRad = nRad / 2; } nFrames = nParticleFrames [0][nType]; if (nType == BULLET_PARTICLES) { m_nFrame = 0; m_nRotFrame = 0; m_nOrient = 3; } else if (nType == BUBBLE_PARTICLES) { m_nFrame = rand () % (nFrames * nFrames); m_nRotFrame = 0; m_nOrient = 0; } else if (nType == LIGHT_PARTICLES) { m_nFrame = 0; m_nRotFrame = 0; m_nOrient = 0; } else { m_nFrame = rand () % (nFrames * nFrames); m_nRotFrame = m_nFrame / 2; m_nOrient = rand () % 4; } #if 1 if (m_bEmissive) m_color [0].alpha *= ParticleBrightness (colorP); else if (nParticleSystemType == SMOKE_PARTICLES) m_color [0].alpha /= colorP ? color.red + color.green + color.blue + 2 : 2; else if (nParticleSystemType == BUBBLE_PARTICLES) m_color [0].alpha /= 2; else if (nParticleSystemType == LIGHT_PARTICLES) m_color [0].alpha /= 5; # if 0 else if (nParticleSystemType == GATLING_PARTICLES) ;//m_color [0].alpha /= 6; # endif #endif return 1; }
// Volume 0-I2X (1) int CAudioChannel::Start (short nSound, int nSoundClass, fix nVolume, int nPan, int bLooping, int nLoopStart, int nLoopEnd, int nSoundObj, int nSpeed, const char *pszWAV, CFixVector* vPos) { CSoundSample* soundP = NULL; int bPersistent = (nSoundObj > -1) || bLooping || (nVolume > I2X (1)); if (!(pszWAV && *pszWAV && gameOpts->sound.bUseSDLMixer)) { if (nSound < 0) return -1; if (!gameData.pig.sound.nSoundFiles [gameStates.sound.bD1Sound]) return -1; soundP = gameData.pig.sound.sounds [gameStates.sound.bD1Sound] + nSound % gameData.pig.sound.nSoundFiles [gameStates.sound.bD1Sound]; if (!(soundP->data [soundP->bCustom].Buffer () && soundP->nLength [soundP->bCustom])) return -1; } if (m_info.bPlaying) { m_info.bPlaying = 0; if (m_info.nSoundObj > -1) audio.EndSoundObject (m_info.nSoundObj); if (soundQueue.Channel () == audio.FreeChannel ()) soundQueue.End (); } #if USE_OPENAL if (m_info.source == 0xFFFFFFFF) { CFloatVector fPos; DigiALError (); alGenSources (1, &m_info.source); if (DigiALError ()) return -1; alSourcei (m_info.source, AL_BUFFER, soundP->buffer); if (DigiALError ()) return -1; alSourcef (m_info.source, AL_GAIN, ((nVolume < I2X (1)) ? X2F (nVolume) : 1) * 2 * X2F (m_info.nVolume)); alSourcei (m_info.source, AL_LOOPING, (ALuint) ((nSoundObj > -1) || bLooping || (nVolume > I2X (1)))); fPos.Assign (vPos ? *vPos : OBJECTS [LOCALPLAYER.nObject].nPosition.vPos); alSourcefv (m_info.source, AL_POSITION, reinterpret_cast<ALfloat*> (fPos)); alSource3f (m_info.source, AL_VELOCITY, 0, 0, 0); alSource3f (m_info.source, AL_DIRECTION, 0, 0, 0); if (DigiALError ()) return -1; alSourcePlay (m_info.source); if (DigiALError ()) return -1; } #endif #if USE_SDL_MIXER if (gameOpts->sound.bUseSDLMixer) { if (m_info.mixChunkP) { Mix_HaltChannel (m_info.nChannel); if (m_info.bBuiltIn) m_info.bBuiltIn = 0; else Mix_FreeChunk (m_info.mixChunkP); m_info.mixChunkP = NULL; } } #endif if (m_info.bResampled) { m_info.sample.Destroy (); m_info.bResampled = 0; } #if USE_SDL_MIXER if (gameOpts->sound.bUseSDLMixer) { //resample to two channels m_info.nChannel = audio.FreeChannel (); if (pszWAV && *pszWAV) { if (!(m_info.mixChunkP = LoadAddonSound (pszWAV, &m_info.bBuiltIn))) return -1; } else { int l; if (soundP->bHires) { l = soundP->nLength [soundP->bCustom]; m_info.sample.SetBuffer (soundP->data [soundP->bCustom].Buffer (), 1, l); m_info.mixChunkP = Mix_QuickLoad_WAV (reinterpret_cast<Uint8*> (m_info.sample.Buffer ())); } else { if (gameOpts->sound.bHires [0]) return -1; //cannot mix hires and standard sounds l = Resample (soundP, gameStates.sound.bD1Sound && (gameOpts->sound.digiSampleRate != SAMPLE_RATE_11K), songManager.MP3 ()); if (l <= 0) return -1; if (nSpeed < I2X (1)) l = Speedup (soundP, nSpeed); #if MAKE_WAV m_info.mixChunkP = Mix_QuickLoad_WAV (reinterpret_cast<Uint8*> (m_info.sample.Buffer ())); #else m_info.mixChunkP = Mix_QuickLoad_RAW (reinterpret_cast<Uint8*> (m_info.sample.Buffer ()), l); #endif } } Mix_VolPan (m_info.nChannel, nVolume, nPan); Mix_PlayChannel (m_info.nChannel, m_info.mixChunkP, bLooping ? -1 : nLoopEnd - nLoopStart); } else #else if (pszWAV && *pszWAV) return -1; #endif { if (gameStates.sound.bD1Sound && (gameOpts->sound.digiSampleRate != SAMPLE_RATE_11K)) { int l = Resample (soundP, 0, 0); if (l <= 0) return -1; m_info.nLength = l; } else { m_info.sample.SetBuffer (soundP->data [soundP->bCustom].Buffer (), 1, m_info.nLength = soundP->nLength [soundP->bCustom]); } if (nSpeed < I2X (1)) Speedup (soundP, nSpeed); } m_info.nVolume = FixMul (audio.Volume (), nVolume); m_info.nPan = nPan; m_info.nPosition = 0; m_info.nSoundObj = nSoundObj; m_info.nSoundClass = nSoundClass; m_info.bLooped = bLooping; #if USE_OPENAL m_info.loops = bLooping ? -1 : nLoopEnd - nLoopStart + 1; #endif m_info.nSound = nSound; m_info.bPersistent = 0; m_info.bPlaying = 1; m_info.bPersistent = bPersistent; return audio.FreeChannel (); }
void DrawObjectBlob (CObject *objP, int bmi0, int bmi, int iFrame, tRgbaColorf *colorP, float fAlpha) { CBitmap* bmP; tRgbaColorf color; int nType = objP->info.nType; int nId = objP->info.nId; #if 0 int bMuzzleFlash = 0; #endif int bAdditive = 0, bEnergy = 0, nTransp = (nType == OBJ_POWERUP) ? 3 : 2; fix xSize; float fScale; if ((nType == OBJ_WEAPON) && (objP->info.nId == OMEGA_ID) && omegaLightnings.Exist ()) return; #if DBG if ((nType == nDbgObjType) && ((nDbgObjId < 0) || (objP->info.nId == nDbgObjId))) nDbgObjType = nDbgObjType; #endif if (gameOpts->render.textures.bUseHires [0] || gameOpts->render.effects.bTransparent) { if (fAlpha) { bAdditive = (nType == OBJ_FIREBALL) || (nType == OBJ_EXPLOSION) || ((nType == OBJ_WEAPON) && (objP->info.nId == OMEGA_ID)); #if 0 bMuzzleFlash = (nType == OBJ_FIREBALL) && ((nId == 11) || (nId == 12) || (nId == 15) || (nId == 22) || (nId == 86)); #endif } else { if (nType == OBJ_POWERUP) { if (IsEnergyPowerup (nId)) { fAlpha = 2.0f / 3.0f; bEnergy = 1; } else fAlpha = 1.0f; } else if ((nType != OBJ_FIREBALL) && (nType != OBJ_EXPLOSION)) fAlpha = 1.0f; else { fAlpha = 2.0f / 3.0f; bAdditive = 1; } } } else { nTransp = 3; fAlpha = 1.0f; } #if 0 if (bmi < 0) { PageInAddonBitmap (bmi); bmP = gameData.pig.tex.addonBitmaps - bmi - 1; #if DBG if ((objP->rType.vClipInfo.nCurFrame < 0) || (objP->rType.vClipInfo.nCurFrame >= bmP->FrameCount ())) { objP->rType.vClipInfo.nCurFrame = 0; return; } #endif } else { LoadBitmap (bmi, 0); bmP = gameData.pig.tex.bitmaps [0] + bmi; } #else if (bmi < 0) { bmP = gameData.pig.tex.addonBitmaps - bmi - 1; bmP = bmP->SetCurFrame (iFrame); } else { CBitmap* bmoP; bmP = gameData.pig.tex.bitmaps [0] + bmi; if ((bmP->Type () == BM_TYPE_STD) && (bmoP = bmP->Override ())) bmP = bmoP->SetCurFrame (iFrame); } #endif //bmP->SetupTexture (1, 1); if (!bmP) return; #if 0 if (!bmP->Prepared () && bmP->PrepareTexture (1, 0)) return; #endif fScale = ObjectBlobColor (objP, bmP, &color); if (colorP /*&& (bmi >= 0)*/) *colorP = color; //memcpy (colorP, gameData.pig.tex.bitmapColors + bmi, sizeof (tRgbaColorf)); xSize = objP->info.xSize; if (nType == OBJ_POWERUP) { if ((bEnergy && gameOpts->render.coronas.bPowerups) || (!bEnergy && gameOpts->render.coronas.bWeapons)) RenderPowerupCorona (objP, color.red, color.green, color.blue, coronaIntensities [gameOpts->render.coronas.nObjIntensity]); } if ((objP->info.nType == OBJ_POWERUP) && (objP->info.nId == POW_SHIELD_BOOST) && !gameStates.app.bNostalgia && gameOpts->render.powerups.b3D && gameOpts->render.powerups.b3DShields) { if ((objP->mType.physInfo.velocity.IsZero ()) && (objP->info.movementType != MT_SPINNING)) { objP->info.movementType = MT_SPINNING; objP->mType.spinRate = objP->info.position.mOrient.UVec () * (I2X (1) / 8); } //the actual shield in the sprite texture has 3/4 of the textures size DrawShieldSphere (objP, 3 * color.red / 2, 3 * color.green / 2, 3 * color.blue / 2, 1.0f, 3 * objP->info.xSize / 4); } else if ((gameOpts->render.bDepthSort > 0) && (fAlpha < 1)) { if (bAdditive) { #if 1 color.red = color.green = color.blue = 0.5f; #else if ((nType == OBJ_FIREBALL) && (fScale > 0)) { fScale = 1.0f - fScale / 6.0f; color.red *= fScale; color.green *= fScale; color.blue *= fScale; } #endif } else color.red = color.green = color.blue = 1; color.alpha = fAlpha; if (bmP->Width () > bmP->Height ()) transparencyRenderer.AddSprite (bmP, objP->info.position.vPos, &color, xSize, FixMulDiv (xSize, bmP->Height (), bmP->Width ()), iFrame, bAdditive, (nType == OBJ_FIREBALL) ? 10.0f : 0.0f); else transparencyRenderer.AddSprite (bmP, objP->info.position.vPos, &color, FixMulDiv (xSize, bmP->Width (), bmP->Height ()), xSize, iFrame, bAdditive, (nType == OBJ_FIREBALL) ? 10.0f : 0.0f); } else { if (bmP->Width () > bmP->Height ()) G3DrawBitmap (objP->info.position.vPos, xSize, FixMulDiv (xSize, bmP->Height (), bmP->Width ()), bmP, NULL, fAlpha, nTransp); else G3DrawBitmap (objP->info.position.vPos, FixMulDiv (xSize, bmP->Width (), bmP->Height ()), xSize, bmP, NULL, fAlpha, nTransp); } gameData.render.nTotalSprites++; }
static int RenderWeaponModel (CObject* objP, int bDepthSort, int bSpectate) { if (automap.m_bDisplay && !AM_SHOW_POWERUPS (1)) return 0; if (!(gameStates.app.bNostalgia || gameOpts->render.powerups.b3D) && WeaponIsMine (objP->info.nId) && (objP->info.nId != SMALLMINE_ID)) ConvertWeaponToVClip (objP); else { if (gameStates.render.nType != 1) return 0; if (gameData.objs.bIsMissile [objP->info.nId]) { //make missiles smaller during launch if ((objP->cType.laserInfo.parent.nType == OBJ_PLAYER) && (gameData.models.renderModels [1][108].m_bValid > 0)) { //hires player ship float dt = X2F (gameData.time.xGame - objP->CreationTime ()); if (dt < 1) { fix xScale = (fix) (I2X (1) + I2X (1) * dt * dt) / 2; gameData.models.vScale.Set (xScale, xScale, xScale); } } //DoObjectSmoke (objP); DrawPolygonObject (objP, bDepthSort, 0); #if RENDER_HITBOX # if 0 DrawShieldSphere (objP, 0.66f, 0.2f, 0.0f, 0.4f); # else RenderHitbox (objP, 0.5f, 0.0f, 0.6f, 0.4f); # endif #endif RenderThrusterFlames (objP); gameData.models.vScale.SetZero (); } else { #if RENDER_HITBOX # if 0 DrawShieldSphere (objP, 0.66f, 0.2f, 0.0f, 0.4f); # else RenderHitbox (objP, 0.5f, 0.0f, 0.6f, 0.4f); # endif #endif if (objP->info.nType != OBJ_WEAPON) { DrawPolygonObject (objP, bDepthSort, 0); if ((objP->info.nId != SMALLMINE_ID) && !gameStates.render.bQueryCoronas) RenderLightTrail (objP); } else { if ((objP->info.nId == VULCAN_ID) || (objP->info.nId == GAUSS_ID)) { if (SHOW_OBJ_FX && extraGameInfo [0].bTracers) { if (!gameStates.render.bQueryCoronas) RenderLightTrail (objP); gameData.models.vScale.Set (I2X (1) / 4, I2X (1) / 4, I2X (2)); CFixVector vSavedPos = objP->info.position.vPos; objP->info.position.vPos += objP->info.position.mOrient.FVec (); DrawPolygonObject (objP, bDepthSort, 0); objP->info.position.vPos = vSavedPos; } } else { if ((objP->info.nId != SMALLMINE_ID) && !gameStates.render.bQueryCoronas) RenderLightTrail (objP); DrawPolygonObject (objP, bDepthSort, 0); } gameData.models.vScale.SetZero (); } } } return 1; }
fix SetVertexLight (int nSegment, int nSide, int nVertex, tFaceColor *colorP, fix light) { tRgbColorf *pdc; fix dynLight; float fl, dl, hl; //the tUVL struct has static light already in it //scale static light for destruction effect if (EGI_FLAG (bDarkness, 0, 0, 0)) light = 0; else { #if LMAP_LIGHTADJUST if (USE_LIGHTMAPS) { else { light = I2X (1) / 2 + gameData.render.lights.segDeltas [nSegment * 6 + nSide]; if (light < 0) light = 0; } } #endif if (gameData.reactor.bDestroyed || gameStates.gameplay.seismic.nMagnitude) //make lights flash light = FixMul (gameStates.render.nFlashScale, light); } //add in dynamic light (from explosions, etc.) dynLight = gameData.render.lights.dynamicLight [nVertex]; fl = X2F (light); dl = X2F (dynLight); light += dynLight; #if DBG if (nVertex == nDbgVertex) nVertex = nVertex; #endif if (gameStates.app.bHaveExtraGameInfo [IsMultiGame]) { if (gameData.render.lights.bGotDynColor [nVertex]) { pdc = gameData.render.lights.dynamicColor + nVertex; if (gameOpts->render.color.bMix) { if (gameOpts->render.color.bGunLight) { if (gameStates.render.bAmbientColor) { if ((fl != 0) && gameData.render.color.vertBright [nVertex]) { hl = fl / gameData.render.color.vertBright [nVertex]; colorP->color.red = colorP->color.red * hl + pdc->red * dl; colorP->color.green = colorP->color.green * hl + pdc->green * dl; colorP->color.blue = colorP->color.blue * hl + pdc->blue * dl; ScaleColor (colorP, fl + dl); } else { colorP->color.red = pdc->red * dl; colorP->color.green = pdc->green * dl; colorP->color.blue = pdc->blue * dl; ScaleColor (colorP, dl); } } else { colorP->color.red = fl + pdc->red * dl; colorP->color.green = fl + pdc->green * dl; colorP->color.blue = fl + pdc->blue * dl; ScaleColor (colorP, fl + dl); } } else { colorP->color.red = colorP->color.green = colorP->color.blue = fl + dl; } if (gameOpts->render.color.bCap) { if (colorP->color.red > 1.0) colorP->color.red = 1.0; if (colorP->color.green > 1.0) colorP->color.green = 1.0; if (colorP->color.blue > 1.0) colorP->color.blue = 1.0; } } else { float dl = X2F (light); dl = (float) pow (dl, 1.0f / 3.0f); colorP->color.red = pdc->red * dl; colorP->color.green = pdc->green * dl; colorP->color.blue = pdc->blue * dl; } } else { ScaleColor (colorP, fl + dl); } } else { ScaleColor (colorP, fl + dl); } //saturate at max value if (light > MAX_LIGHT) light = MAX_LIGHT; return light; }
int DrawPolygonObject (CObject *objP, int bDepthSort, int bForce) { fix xLight; int imSave = 0; fix xEngineGlow [2]; //element 0 is for engine glow, 1 for headlight int bBlendPolys = 0; int bBrightPolys = 0; int bGatling = 0; int bCloaked = ObjectIsCloaked (objP); int bEnergyWeapon; int i, id, bOk = 0; if (objP->info.nType == 255) return 0; id = (int) objP->info.nId; if ((id < 0) || (id == 255)) bEnergyWeapon = id = 0; else { #if 0 bGatling = ((objP->info.nType == OBJ_WEAPON) && ((id == VULCAN_ID) || (id == GAUSS_ID))); #endif bEnergyWeapon = (objP->info.nType == OBJ_WEAPON) && gameData.objs.bIsWeapon [id] && !gameData.objs.bIsMissile [id]; } #if SHADOWS if (!bForce && FAST_SHADOWS && !gameOpts->render.shadows.bSoft && (gameStates.render.nShadowPass == 3)) return 1; #endif if (gameStates.render.bBuildModels) xLight = I2X (1); else { xLight = CalcObjectLight (objP, xEngineGlow); if ((bCloaked || bEnergyWeapon) && bDepthSort && (gameStates.render.nShadowPass != 2)) { transparencyRenderer.AddObject (objP); return 1; } if (DrawHiresObject (objP, xLight, xEngineGlow)) return 1; gameStates.render.bBrightObject = bEnergyWeapon; gameOpts->render.bDepthSort = -gameOpts->render.bDepthSort; imSave = gameStates.render.nInterpolationMethod; if (bLinearTMapPolyObjs) gameStates.render.nInterpolationMethod = 1; } if (objP->rType.polyObjInfo.nTexOverride != -1) { #if DBG CPolyModel* pm = gameData.models.polyModels [0] + objP->rType.polyObjInfo.nModel; #endif tBitmapIndex bm = gameData.pig.tex.bmIndex [0][objP->rType.polyObjInfo.nTexOverride], bmiP [MAX_MODEL_TEXTURES]; #if DBG Assert (pm->TextureCount () <= 12); #endif for (i = 0; i < MAX_MODEL_TEXTURES; i++) //fill whole array, in case simple model needs more bmiP [i] = bm; bOk = DrawPolyModel (objP, &objP->info.position.vPos, &objP->info.position.mOrient, reinterpret_cast<CAngleVector*> ( &objP->rType.polyObjInfo.animAngles), objP->rType.polyObjInfo.nModel, objP->rType.polyObjInfo.nSubObjFlags, xLight, xEngineGlow, bmiP, NULL); } else { if (bCloaked) { if (objP->info.nType == OBJ_PLAYER) bOk = DrawCloakedObject (objP, xLight, xEngineGlow, gameData.multiplayer.players [id].cloakTime, gameData.multiplayer.players [id].cloakTime + CLOAK_TIME_MAX); else if (objP->info.nType == OBJ_ROBOT) { if (!ROBOTINFO (id).bossFlag) bOk = DrawCloakedObject (objP, xLight, xEngineGlow, gameData.time.xGame - I2X (10), gameData.time.xGame + I2X (10)); else if (0 <= (i = gameData.bosses.Find (objP->Index ()))) bOk = DrawCloakedObject (objP, xLight, xEngineGlow, gameData.bosses [i].m_nCloakStartTime, gameData.bosses [i].m_nCloakEndTime); } } else { tBitmapIndex *bmiAltTex = (objP->rType.polyObjInfo.nAltTextures > 0) ? mpTextureIndex [objP->rType.polyObjInfo.nAltTextures - 1] : NULL; // Snipers get bright when they fire. if (!gameStates.render.bBuildModels) { if ((objP->info.nType == OBJ_ROBOT) && (gameData.ai.localInfo [objP->Index ()].nextPrimaryFire < I2X (1) / 8) && (objP->cType.aiInfo.behavior == AIB_SNIPE)) xLight = 2 * xLight + I2X (1); bBlendPolys = bEnergyWeapon && (gameData.weapons.info [id].nInnerModel > -1); bBrightPolys = bGatling || (bBlendPolys && WI_energy_usage (id)); if (bEnergyWeapon) { if (gameOpts->legacy.bRender) gameStates.render.grAlpha = GrAlpha (FADE_LEVELS - 2); else ogl.BlendFunc (GL_ONE, GL_ONE); } if (bBlendPolys) { #if 0 fix xDistToEye = CFixVector::Dist(gameData.objs.viewerP->info.position.vPos, objP->info.position.vPos); if (xDistToEye < gameData.models.nSimpleModelThresholdScale * I2X (2)) #endif bOk = DrawPolyModel (objP, &objP->info.position.vPos, &objP->info.position.mOrient, objP->rType.polyObjInfo.animAngles, gameData.weapons.info [id].nInnerModel, objP->rType.polyObjInfo.nSubObjFlags, bBrightPolys ? I2X (1) : xLight, xEngineGlow, bmiAltTex, NULL); } if (bEnergyWeapon) gameStates.render.grAlpha = GrAlpha (4 * FADE_LEVELS / 5); else if (!bBlendPolys) gameStates.render.grAlpha = 1.0f; } bOk = DrawPolyModel (objP, &objP->info.position.vPos, &objP->info.position.mOrient, objP->rType.polyObjInfo.animAngles, objP->rType.polyObjInfo.nModel, objP->rType.polyObjInfo.nSubObjFlags, (bGatling || bBrightPolys) ? I2X (1) : xLight, xEngineGlow, bmiAltTex, (bGatling || bEnergyWeapon) ? gameData.weapons.color + id : NULL); if (!gameStates.render.bBuildModels) { if (!gameOpts->legacy.bRender) ogl.BlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); gameStates.render.grAlpha = 1.0f; } } } if (!gameStates.render.bBuildModels) { gameStates.render.nInterpolationMethod = imSave; gameStates.render.bBrightObject = 0; gameOpts->render.bDepthSort = -gameOpts->render.bDepthSort; } return bOk; }
int CFont::DrawString (int left, int top, const char *s) { const char* textP, * nextRowP, * text_ptr1; int width, spacing, letter; int x, y; int origColor = CCanvas::Current ()->FontColor (0).index; //to allow easy reseting to default string color with colored strings -MPM float fScale = fontManager.Scale (); ubyte c; CBitmap* bmf; tCanvasColor* colorP = (m_info.flags & FT_COLOR) ? NULL : &CCanvas::Current ()->FontColor (0); if (CCanvas::Current ()->Mode () != BM_OGL) return -1; nextRowP = s; y = top; if (screen.Canvas ()->Mode () != BM_OGL) Error ("carp.\n"); while (nextRowP != NULL) { text_ptr1 = nextRowP; nextRowP = NULL; textP = text_ptr1; x = (left == 0x8000) ? fontManager.Current ()->GetCenteredX (textP) : left; while ((c = *textP)) { if (c == '\n') { nextRowP = textP + 1; y += m_info.height + 2; break; } letter = c - m_info.minChar; fontManager.Current ()->GetCharWidth (c, textP [1], width, spacing); if (c <= 0x06) { //not in font, draw as space textP = ScanEmbeddedColors (c, textP, origColor, 128, 2); continue; } if (fontManager.Current ()->InFont (letter)) { bmf = m_info.bitmaps + letter; bmf->AddFlags (BM_FLAG_TRANSPARENT); bmf->RenderScaled (x, y, int (bmf->Width () * fScale), int (bmf->Height () * fScale), I2X (1), 0, colorP); } x += spacing; textP++; } } return 0; }
// ------------------------------------------------------------------------ // static const initializations const CFloatVector CFloatVector::ZERO = CFloatVector::Create (0,0,0,1); const CFloatVector CFloatVector::ZERO4 = CFloatVector::Create (0,0,0,0); const CFloatVector CFloatVector::XVEC = CFloatVector::Create (1,0,0,1); const CFloatVector CFloatVector::YVEC = CFloatVector::Create (0,1,0,1); const CFloatVector CFloatVector::ZVEC = CFloatVector::Create (0,0,1,1); const CFloatVector3 CFloatVector3::ZERO = CFloatVector3::Create (0,0,0); const CFloatVector3 CFloatVector3::XVEC = CFloatVector3::Create (1,0,0); const CFloatVector3 CFloatVector3::YVEC = CFloatVector3::Create (0,1,0); const CFloatVector3 CFloatVector3::ZVEC = CFloatVector3::Create (0,0,1); const CFixVector CFixVector::ZERO = CFixVector::Create (0,0,0); const CFixVector CFixVector::XVEC = CFixVector::Create (I2X (1),0,0); const CFixVector CFixVector::YVEC = CFixVector::Create (0,I2X (1),0); const CFixVector CFixVector::ZVEC = CFixVector::Create (0,0,I2X (1)); const CAngleVector CAngleVector::ZERO = CAngleVector::Create (0,0,0); const CFixMatrix CFixMatrix::IDENTITY = CFixMatrix::Create (CFixVector::XVEC, CFixVector::YVEC, CFixVector::ZVEC); const CFloatMatrix CFloatMatrix::IDENTITY = CFloatMatrix::Create (CFloatVector::Create (1.0f, 0, 0, 0), CFloatVector::Create (0, 1.0f, 0, 0), CFloatVector::Create (0, 0, 1.0f, 0), CFloatVector::Create (0, 0, 0, 1.0f)); // ------------------------------------------------------------------------
int GrString (int x, int y, const char *s, int *idP) { if (gameOpts->render.coronas.nStyle < 2) { grsString *ps; if ((MODE == BM_OGL) && (ps = GetPoolString (s, idP))) { CBitmap* bmP = ps->bmP; float fScale = fontManager.Scale (); ps->bmP->RenderScaled (x, y, int (bmP->Width () * fScale), int (bmP->Height () * fScale), I2X (1), 0, &CCanvas::Current ()->FontColor (0)); return (int) (ps - stringPool) + 1; } } #if 0 return fontManager.Current ()->DrawString (x, y, s); #else int w, h, aw, clipped = 0; Assert (fontManager.Current () != NULL); if (x == 0x8000) { if (y < 0) clipped |= 1; fontManager.Current ()->StringSize (s, w, h, aw); // for x, since this will be centered, only look at // width. if (w > CCanvas::Current ()->Width ()) clipped |= 1; if (y > CCanvas::Current ()->Height ()) clipped |= 3; else if ((y + h) > CCanvas::Current ()->Height ()) clipped |= 1; else if ((y + h) < 0) clipped |= 2; } else { if ((x < 0) || (y < 0)) clipped |= 1; fontManager.Current ()->StringSize (s, w, h, aw); if (x > CCanvas::Current ()->Width ()) clipped |= 3; else if ((x + w) > CCanvas::Current ()->Width ()) clipped |= 1; else if ((x + w) < 0) clipped |= 2; if (y > CCanvas::Current ()->Height ()) clipped |= 3; else if ((y + h) > CCanvas::Current ()->Height ()) clipped |= 1; else if ((y + h) < 0) clipped |= 2; } if (!clipped) return fontManager.Current ()->DrawString (x, y, s); if (clipped & 2) { // Completely clipped... return 0; } if (clipped & 1) { // Partially clipped... } // Partially clipped... if (MODE == BM_OGL) return fontManager.Current ()->DrawString (x, y, s); if (fontManager.Current ()->Flags () & FT_COLOR) return fontManager.Current ()->DrawString (x, y, s); if (CCanvas::Current ()->FontColor (1).index == -1) return GrInternalStringClippedM (x, y, s); return GrInternalStringClipped (x, y, s); #endif }
// -------------------------------------------------------------------------------------------------------------------- // If fire_anyway, fire even if CPlayerData is not visible. We're firing near where we believe him to be. Perhaps he's // lurking behind a corner. void AIDoActualFiringStuff (CObject *objP, tAIStaticInfo *aiP, tAILocalInfo *ailP, tRobotInfo *botInfoP, int nGun) { fix dot; if ((gameData.ai.nPlayerVisibility == 2) || (gameData.ai.nDistToLastPlayerPosFiredAt < FIRE_AT_NEARBY_PLAYER_THRESHOLD)) { CFixVector vFirePos = gameData.ai.vBelievedPlayerPos; // Hack: If visibility not == 2, we're here because we're firing at a nearby player. // So, fire at gameData.ai.vLastPlayerPosFiredAt instead of the CPlayerData position. if (!botInfoP->attackType && (gameData.ai.nPlayerVisibility != 2)) vFirePos = gameData.ai.vLastPlayerPosFiredAt; // Changed by mk, 01/04/95, onearm would take about 9 seconds until he can fire at you. // Above comment corrected. Date changed from 1994, to 1995. Should fix some very subtle bugs, as well as not cause me to wonder, in the future, why I was writing AI code for onearm ten months before he existed. if (!gameData.ai.bObjAnimates || ReadyToFire (botInfoP, ailP)) { dot = CFixVector::Dot (objP->info.position.mOrient.FVec (), gameData.ai.vVecToPlayer); if ((dot >= I2X (7) / 8) || ((dot > I2X (1) / 4) && botInfoP->bossFlag)) { if (nGun < botInfoP->nGuns) { if (botInfoP->attackType == 1) { if (gameStates.app.bPlayerExploded || (gameData.ai.xDistToPlayer >= objP->info.xSize + gameData.objs.consoleP->info.xSize + I2X (2))) // botInfoP->circleDistance [gameStates.app.nDifficultyLevel] + gameData.objs.consoleP->info.xSize) return; if (!AIMultiplayerAwareness (objP, ROBOT_FIRE_AGITATION - 2)) return; DoAIRobotHitAttack (objP, gameData.objs.consoleP, &objP->info.position.vPos); } else { #if 1 if (AICanFireAtPlayer (objP, &gameData.ai.vGunPoint, &vFirePos)) { #else if (gameData.ai.vGunPoint.p.x || gameData.ai.vGunPoint.p.y || gameData.ai.vGunPoint.p.z) { #endif if (!AIMultiplayerAwareness (objP, ROBOT_FIRE_AGITATION)) return; // New, multi-weapon-nType system, 06/05/95 (life is slipping awayd:\temp\dm_test.) if (nGun != 0) { if (ailP->nextPrimaryFire <= 0) { AIFireLaserAtPlayer (objP, &gameData.ai.vGunPoint, nGun, &vFirePos); gameData.ai.vLastPlayerPosFiredAt = vFirePos; } if ((ailP->nextSecondaryFire <= 0) && (botInfoP->nSecWeaponType != -1)) { CalcGunPoint (&gameData.ai.vGunPoint, objP, 0); AIFireLaserAtPlayer (objP, &gameData.ai.vGunPoint, 0, &vFirePos); gameData.ai.vLastPlayerPosFiredAt = vFirePos; } } else if (ailP->nextPrimaryFire <= 0) { AIFireLaserAtPlayer (objP, &gameData.ai.vGunPoint, nGun, &vFirePos); gameData.ai.vLastPlayerPosFiredAt = vFirePos; } } } } // Wants to fire, so should go into chase mode, probably. if ((aiP->behavior != AIB_RUN_FROM) && (aiP->behavior != AIB_STILL) && (aiP->behavior != AIB_SNIPE) && (aiP->behavior != AIB_FOLLOW) && !botInfoP->attackType && ((ailP->mode == AIM_FOLLOW_PATH) || (ailP->mode == AIM_IDLING))) ailP->mode = AIM_CHASE_OBJECT; aiP->GOAL_STATE = AIS_RECOVER; ailP->goalState [aiP->CURRENT_GUN] = AIS_RECOVER; // Switch to next gun for next fire. #if 0 if (++(aiP->CURRENT_GUN) >= botInfoP->nGuns) { if ((botInfoP->nGuns == 1) || (botInfoP->nSecWeaponType == -1)) aiP->CURRENT_GUN = 0; else aiP->CURRENT_GUN = 1; } #endif } } } else if ((!botInfoP->attackType && gameData.weapons.info [botInfoP->nWeaponType].homingFlag) || (((botInfoP->nSecWeaponType != -1) && gameData.weapons.info [botInfoP->nSecWeaponType].homingFlag))) { fix dist; // Robots which fire homing weapons might fire even if they don't have a bead on the player. if ((!gameData.ai.bObjAnimates || (ailP->achievedState [aiP->CURRENT_GUN] == AIS_FIRE)) && (((ailP->nextPrimaryFire <= 0) && (aiP->CURRENT_GUN != 0)) || ((ailP->nextSecondaryFire <= 0) && (aiP->CURRENT_GUN == 0))) && ((dist = CFixVector::Dist(gameData.ai.vHitPos, objP->info.position.vPos)) > I2X (40))) { if (!AIMultiplayerAwareness (objP, ROBOT_FIRE_AGITATION)) return; AIFireLaserAtPlayer (objP, &gameData.ai.vGunPoint, nGun, &gameData.ai.vBelievedPlayerPos); aiP->GOAL_STATE = AIS_RECOVER; ailP->goalState [aiP->CURRENT_GUN] = AIS_RECOVER; // Switch to next gun for next fire. if (++(aiP->CURRENT_GUN) >= botInfoP->nGuns) aiP->CURRENT_GUN = 0; } else { // Switch to next gun for next fire. if (++(aiP->CURRENT_GUN) >= botInfoP->nGuns) aiP->CURRENT_GUN = 0; } } else { // --------------------------------------------------------------- CFixVector vLastPos; if (d_rand ()/2 < FixMul (gameData.time.xFrame, (gameStates.app.nDifficultyLevel << 12) + 0x4000)) { if ((!gameData.ai.bObjAnimates || ReadyToFire (botInfoP, ailP)) && (gameData.ai.nDistToLastPlayerPosFiredAt < FIRE_AT_NEARBY_PLAYER_THRESHOLD)) { CFixVector::NormalizedDir(vLastPos, gameData.ai.vBelievedPlayerPos, objP->info.position.vPos); dot = CFixVector::Dot (objP->info.position.mOrient.FVec (), vLastPos); if (dot >= I2X (7) / 8) { if (aiP->CURRENT_GUN < botInfoP->nGuns) { if (botInfoP->attackType == 1) { if (!gameStates.app.bPlayerExploded && (gameData.ai.xDistToPlayer < objP->info.xSize + gameData.objs.consoleP->info.xSize + I2X (2))) { // botInfoP->circleDistance [gameStates.app.nDifficultyLevel] + gameData.objs.consoleP->info.xSize) { if (!AIMultiplayerAwareness (objP, ROBOT_FIRE_AGITATION-2)) return; DoAIRobotHitAttack (objP, gameData.objs.consoleP, &objP->info.position.vPos); } else return; } else { if (gameData.ai.vGunPoint.IsZero()) ; else { if (!AIMultiplayerAwareness (objP, ROBOT_FIRE_AGITATION)) return; // New, multi-weapon-nType system, 06/05/95 (life is slipping awayd:\temp\dm_test.) if (nGun != 0) { if (ailP->nextPrimaryFire <= 0) AIFireLaserAtPlayer (objP, &gameData.ai.vGunPoint, nGun, &gameData.ai.vLastPlayerPosFiredAt); if ((ailP->nextSecondaryFire <= 0) && (botInfoP->nSecWeaponType != -1)) { CalcGunPoint (&gameData.ai.vGunPoint, objP, 0); AIFireLaserAtPlayer (objP, &gameData.ai.vGunPoint, 0, &gameData.ai.vLastPlayerPosFiredAt); } } else if (ailP->nextPrimaryFire <= 0) AIFireLaserAtPlayer (objP, &gameData.ai.vGunPoint, nGun, &gameData.ai.vLastPlayerPosFiredAt); } } // Wants to fire, so should go into chase mode, probably. if ((aiP->behavior != AIB_RUN_FROM) && (aiP->behavior != AIB_STILL) && (aiP->behavior != AIB_SNIPE) && (aiP->behavior != AIB_FOLLOW) && ((ailP->mode == AIM_FOLLOW_PATH) || (ailP->mode == AIM_IDLING))) ailP->mode = AIM_CHASE_OBJECT; } aiP->GOAL_STATE = AIS_RECOVER; ailP->goalState [aiP->CURRENT_GUN] = AIS_RECOVER; // Switch to next gun for next fire. if (++(aiP->CURRENT_GUN) >= botInfoP->nGuns) { if (botInfoP->nGuns == 1) aiP->CURRENT_GUN = 0; else aiP->CURRENT_GUN = 1; } } } } } }
int CLightManager::Add (CSegFace* faceP, tRgbaColorf *colorP, fix xBrightness, short nSegment, short nSide, short nObject, short nTexture, CFixVector *vPos, ubyte bAmbient) { CDynLight* pl; short h, i; float fBrightness = X2F (xBrightness); #if USE_OGL_LIGHTS GLint nMaxLights; #endif #if 0 if (xBrightness > I2X (1)) xBrightness = I2X (1); #endif if (fBrightness <= 0) return -1; #if DBG if ((nDbgSeg >= 0) && (nSegment == nDbgSeg)) nSegment = nSegment; if ((nDbgObj >= 0) && (nObject == nDbgObj)) nDbgObj = nDbgObj; if (colorP && ((colorP->red > 1) || (colorP->green > 1) || (colorP->blue > 1))) colorP = colorP; #endif if (gameStates.render.nLightingMethod && (nSegment >= 0) && (nSide >= 0)) { #if 1 fBrightness /= Intensity (colorP->red, colorP->green, colorP->blue); #else if (fBrightness < 1) fBrightness = (float) sqrt (fBrightness); else fBrightness *= fBrightness; #endif } if (colorP) colorP->alpha = 1.0f; if (0 <= (h = Update (colorP, fBrightness, nSegment, nSide, nObject))) return h; if (!colorP) return -1; if ((colorP->red == 0.0f) && (colorP->green == 0.0f) && (colorP->blue == 0.0f)) { if (gameStates.app.bD2XLevel && gameStates.render.bColored) return -1; colorP->red = colorP->green = colorP->blue = 1.0f; } if (m_data.nLights [0] >= MAX_OGL_LIGHTS) { gameStates.render.bHaveDynLights = 0; return -1; //too many lights } i = m_data.nLights [0]; //LastEnabledDynLight () + 1; pl = m_data.lights + i; pl->info.faceP = faceP; pl->info.nSegment = nSegment; pl->info.nSide = nSide; pl->info.nObject = nObject; pl->info.nPlayer = -1; pl->info.bState = 1; pl->info.bSpot = 0; pl->info.fBoost = 0; pl->info.bPowerup = 0; pl->info.bAmbient = bAmbient; //0: static light //2: object/lightning //3: headlight if (nObject >= 0) { CObject *objP = OBJECTS + nObject; //HUDMessage (0, "Adding object light %d, type %d", m_data.nLights [0], objP->info.nType); pl->info.nType = 2; if (objP->info.nType == OBJ_POWERUP) { int id = objP->info.nId; if ((id == POW_EXTRA_LIFE) || (id == POW_ENERGY) || (id == POW_SHIELD_BOOST) || (id == POW_HOARD_ORB) || (id == POW_MONSTERBALL) || (id == POW_INVUL)) pl->info.bPowerup = 1; else pl->info.bPowerup = 2; } pl->info.vPos = objP->info.position.vPos; pl->info.fRad = 0; //X2F (OBJECTS [nObject].size) / 2; if (fBrightness > 1) { if ((objP->info.nType == OBJ_FIREBALL) || (objP->info.nType == OBJ_EXPLOSION)) { pl->info.fBoost = 1; pl->info.fRad = fBrightness; } else if ((objP->info.nType == OBJ_WEAPON) && (objP->info.nId == FLARE_ID)) { pl->info.fBoost = 1; pl->info.fRad = 2 * fBrightness; } } m_data.owners [nObject] = m_data.nLights [0]; } else if (nSegment >= 0) { #if 0 CFixVector vOffs; CSide *sideP = SEGMENTS [nSegment].m_sides + nSide; #endif if (nSide < 0) { pl->info.nType = 2; pl->info.bVariable = 0; pl->info.fRad = 0; if (vPos) pl->info.vPos = *vPos; else pl->info.vPos = SEGMENTS [nSegment].Center (); } else { #if DBG if ((nSegment == nDbgSeg) && ((nDbgSide < 0) || (nSide == nDbgSide))) nDbgSeg = nDbgSeg; #endif pl->info.nType = 0; pl->info.fRad = faceP ? faceP->fRads [1] / 2.0f : 0; //RegisterLight (NULL, nSegment, nSide); pl->info.bVariable = IsDestructible (nTexture) || IsFlickering (nSegment, nSide) || IsTriggered (nSegment, nSide) || SEGMENTS [nSegment].Side (nSide)->IsVolatile (); m_data.nVariable += pl->info.bVariable; CSide* sideP = SEGMENTS [nSegment].m_sides + nSide; pl->info.vPos = sideP->Center (); CFixVector vOffs = CFixVector::Avg (sideP->m_normals [0], sideP->m_normals [1]); pl->info.vDirf.Assign (vOffs); CFloatVector::Normalize (pl->info.vDirf); #if 0 if (gameStates.render.bPerPixelLighting) { vOffs *= I2X (1) / 64; pl->info.vPos += vOffs; } #endif } } else { pl->info.nType = 3; pl->info.bVariable = 0; } #if 0 PrintLog ("adding light %d,%d\n", m_data.nLights [0], pl - m_data.lights [0]); #endif pl->info.bOn = 1; pl->bTransform = 1; SetColor (m_data.nLights [0], colorP->red, colorP->green, colorP->blue, fBrightness); return m_data.nLights [0]++; }