void CObject::CheckAfterburnerBlobDrop (void) { if (gameStates.render.bDropAfterburnerBlob) { Assert (this == gameData.objs.consoleP); DropAfterburnerBlobs (this, 2, I2X (5) / 2, -1, NULL, 0); // -1 means use default lifetime if (IsMultiGame) MultiSendDropBlobs ((char) gameData.multiplayer.nLocalPlayer); gameStates.render.bDropAfterburnerBlob = 0; } if ((info.nType == OBJ_WEAPON) && (gameData.weapons.info [info.nId].nAfterburnerSize)) { int nObject, bSmoke; fix vel; fix delay, lifetime, nSize; #if 1 if ((info.nType == OBJ_WEAPON) && gameData.objs.bIsMissile [info.nId]) { if (SHOW_SMOKE && gameOpts->render.particles.bMissiles) return; if ((gameStates.app.bNostalgia || EGI_FLAG (bThrusterFlames, 1, 1, 0)) && (info.nId != MERCURYMSL_ID)) return; } #endif if ((vel = mType.physInfo.velocity.Mag()) > I2X (200)) delay = I2X (1) / 16; else if (vel > I2X (40)) delay = FixDiv (I2X (13), vel); else delay = DEG90; if ((bSmoke = SHOW_SMOKE && gameOpts->render.particles.bMissiles)) { nSize = I2X (3); lifetime = I2X (1) / 12; delay = 0; } else { nSize = I2X (gameData.weapons.info [info.nId].nAfterburnerSize) / 16; lifetime = 3 * delay / 2; if (!IsMultiGame) { delay /= 2; lifetime *= 2; } } nObject = OBJ_IDX (this); if (bSmoke || (gameData.objs.xLastAfterburnerTime [nObject] + delay < gameData.time.xGame) || (gameData.objs.xLastAfterburnerTime [nObject] > gameData.time.xGame)) { DropAfterburnerBlobs (this, 1, nSize, lifetime, NULL, bSmoke); gameData.objs.xLastAfterburnerTime [nObject] = gameData.time.xGame; } } }
void DoRobotSmoke (tObject *objP) { int h = -1, i, nShields = 0, nParts; float nScale; vmsVector pos; i = OBJ_IDX (objP); if (!(SHOW_SMOKE && gameOpts->render.smoke.bRobots)) { if (gameData.smoke.objects [i] >= 0) KillObjectSmoke (i); return; } if ((objP->shields < 0) || (objP->flags & (OF_SHOULD_BE_DEAD | OF_DESTROYED))) nParts = 0; else { nShields = f2ir (RobotDefaultShields (objP)); h = f2ir (objP->shields) * 100 / nShields; } if (h < 0) return; nParts = 10 - h / 5; if (nParts > 0) { if (nShields > 4000) nShields = 4000; else if (nShields < 1000) nShields = 1000; CreateDamageExplosion (nParts, i); //nParts *= nShields / 10; nParts = BOT_MAX_PARTS; nScale = (float) sqrt (8.0 / f2fl (objP->size)); nScale *= 1.0f + h / 25.0f; if (!gameOpts->render.smoke.bSyncSizes) { nParts = -MAX_PARTICLES (nParts, gameOpts->render.smoke.nDens [2]); nScale = PARTICLE_SIZE (gameOpts->render.smoke.nSize [2], nScale); } if (gameData.smoke.objects [i] < 0) { //PrintLog ("creating robot %d smoke\n", i); SetSmokeObject (i, CreateSmoke (&objP->position.vPos, NULL, NULL, objP->nSegment, 1, nParts, nScale, gameOpts->render.smoke.bSyncSizes ? -1 : gameOpts->render.smoke.nSize [2], 1, BOT_PART_LIFE, BOT_PART_SPEED, 0, i, NULL, 1, -1)); } else { SetSmokePartScale (gameData.smoke.objects [i], nScale); SetSmokeDensity (gameData.smoke.objects [i], nParts, gameOpts->render.smoke.bSyncSizes ? -1 : gameOpts->render.smoke.nSize [2]); SetSmokeSpeed (gameData.smoke.objects [i], (objP->mType.physInfo.velocity.p.x || objP->mType.physInfo.velocity.p.y || objP->mType.physInfo.velocity.p.z) ? BOT_PART_SPEED : BOT_PART_SPEED * 2 / 3); } VmVecScaleAdd (&pos, &objP->position.vPos, &objP->position.mOrient.fVec, -objP->size / 2); SetSmokePos (gameData.smoke.objects [i], &pos, NULL, objP->nSegment); } else KillObjectSmoke (i); }
int CObject::CheckWallPhysics (void) { int nType = 0, sideMask; if (info.nType != OBJ_PLAYER) return 0; sideMask = SEGMENTS [info.nSegment].Masks (info.position.vPos, info.xSize).m_side; if (sideMask) { short nSide; int bit; for (nSide = 0, bit = 1; nSide < 6; bit <<= 1, nSide++) if ((sideMask & bit) && (nType = ApplyWallPhysics (info.nSegment, nSide))) break; } if (!nType) nType = CheckSegmentPhysics (); // type 1,2: segment related sound // type 2,3: sound caused by ship touching a wall // type & 1: lava // type & 2: water if (nType) { short nSound; if (nType == 2) nSound = mType.physInfo.thrust.IsZero () ? 0 : SOUND_SHIP_IN_WATER; else nSound = (nType & 1) ? SOUND_LAVAFALL_HISS : SOUND_SHIP_IN_WATERFALL; if (nSound != gameData.objs.nSoundPlaying [info.nId]) { if (gameData.objs.nSoundPlaying [info.nId]) audio.DestroyObjectSound (OBJ_IDX (this)); if (nSound) audio.CreateObjectSound (nSound, SOUNDCLASS_GENERIC, OBJ_IDX (this), 1); gameData.objs.nSoundPlaying [info.nId] = nSound; } } else if (gameData.objs.nSoundPlaying [info.nId]) { audio.DestroyObjectSound (OBJ_IDX (this)); gameData.objs.nSoundPlaying [info.nId] = 0; } return nType; }
//------------------------------------------------------------------------------ //process this powerup for this frame void DoPowerupFrame (tObject *objP) { //if (gameStates.app.b40fpsTick) tVClipInfo *vciP = &objP->rType.vClipInfo; tVideoClip *vcP = gameData.eff.vClips [0] + vciP->nClipIndex; int i = OBJ_IDX (objP); UpdatePowerupClip (vcP, vciP, i); if (objP->lifeleft <= 0) { ObjectCreateExplosion (objP->nSegment, &objP->pos, F1_0 * 7 / 2, VCLIP_POWERUP_DISAPPEARANCE); if (gameData.eff.vClips [0][VCLIP_POWERUP_DISAPPEARANCE].nSound > -1) DigiLinkSoundToObject (gameData.eff.vClips [0][VCLIP_POWERUP_DISAPPEARANCE].nSound, i, 0, F1_0); } }
//------------------------------------------------------------------------------ //process this powerup for this frame void DoPowerupFrame (object *objP) { //if (gameStates.app.b40fpsTick) vclip_info *vciP = &objP->rtype.vclip_info; vclip *vcP = gameData.eff.vClips [0] + vciP->nClipIndex; int i = OBJ_IDX (objP); UpdatePowerupClip (vcP, vciP, i); if (objP->lifeleft <= 0) { ObjectCreateExplosion (objP->segnum, &objP->pos, F1_0 * 7 / 2, VCLIP_POWERUP_DISAPPEARANCE); if (gameData.eff.vClips [0][VCLIP_POWERUP_DISAPPEARANCE].sound_num > -1) DigiLinkSoundToObject (gameData.eff.vClips [0][VCLIP_POWERUP_DISAPPEARANCE].sound_num, i, 0, F1_0); } }
void CObject::UpdateShipSound (void) { if (!gameOpts->sound.bShip) return; int nObject = OBJ_IDX (this); if (nObject != LOCALPLAYER.nObject) return; int nSpeed = mType.physInfo.velocity.Mag(); nSpeed -= I2X (2); if (nSpeed < 0) nSpeed = 0; if (gameData.multiplayer.bMoving == nSpeed) return; if (gameData.multiplayer.bMoving < 0) audio.CreateObjectSound (-1, SOUNDCLASS_PLAYER, OBJ_IDX (this), 1, I2X (1) / 64 + nSpeed / 256, I2X (256), -1, -1, const_cast<char*> (addonSounds [SND_ADDON_MISSILE_SMALL].szSoundFile), 1); else audio.ChangeObjectSound (OBJ_IDX (this), I2X (1) / 64 + nSpeed / 256); gameData.multiplayer.bMoving = nSpeed; }
int AICanFireAtPlayer (CObject *objP, CFixVector *vGun, CFixVector *vPlayer) { tFVIQuery fq; fix nSize, h; short nModel, ignoreObjs [2] = {OBJ_IDX (gameData.objs.consoleP), -1}; // Assume that robot's gun tip is in same CSegment as robot's center. if (vGun->IsZero()) return 0; if (!extraGameInfo [IsMultiGame].bRobotsHitRobots) return 1; objP->cType.aiInfo.SUB_FLAGS &= ~SUB_FLAGS_GUNSEG; if (((*vGun) [X] == objP->info.position.vPos [X]) && ((*vGun) [Y] == objP->info.position.vPos [Y]) && ((*vGun) [Z] == objP->info.position.vPos [Z])) fq.startSeg = objP->info.nSegment; else { short nSegment = FindSegByPos (*vGun, objP->info.nSegment, 1, 0); if (nSegment == -1) return -1; if (nSegment != objP->info.nSegment) objP->cType.aiInfo.SUB_FLAGS |= SUB_FLAGS_GUNSEG; fq.startSeg = nSegment; } h = CFixVector::Dist (*vGun, objP->info.position.vPos); h = CFixVector::Dist (*vGun, *vPlayer); nModel = objP->rType.polyObjInfo.nModel; nSize = objP->info.xSize; objP->rType.polyObjInfo.nModel = -1; //make sure sphere/hitbox and not hitbox/hitbox collisions get tested objP->info.xSize = I2X (2); //chose some meaningful small size to simulate a weapon fq.p0 = vGun; fq.p1 = vPlayer; fq.radP0 = fq.radP1 = I2X (1); fq.thisObjNum = objP->Index (); fq.ignoreObjList = ignoreObjs; fq.flags = FQ_CHECK_OBJS | FQ_ANY_OBJECT | FQ_IGNORE_POWERUPS; //what about trans walls??? fq.bCheckVisibility = true; gameData.ai.nHitType = FindVectorIntersection (&fq, &gameData.ai.hitData); #if DBG if (gameData.ai.nHitType == 0) FindVectorIntersection (&fq, &gameData.ai.hitData); #endif gameData.ai.vHitPos = gameData.ai.hitData.hit.vPoint; gameData.ai.nHitSeg = gameData.ai.hitData.hit.nSegment; objP->rType.polyObjInfo.nModel = nModel; objP->info.xSize = nSize; return (gameData.ai.nHitType == HIT_NONE); }
//------------------------------------------------------------------------------ //process this powerup for this frame void DoPowerupFrame (object *objP) { static fix xPowerupTime = 0; xPowerupTime += gameData.app.xFrameTime; //if (gameStates.app.b40fpsTick) { vclip_info *vci = &objP->rtype.vclip_info; vclip *vcP = gameData.eff.vClips [0] + vci->nClipIndex; int i = OBJ_IDX (objP); int nFrames = vcP->nFrameCount; fix xFudge = (xPowerupTime * (i & 3)) >> 4; grs_bitmap *bmP; if (vcP->flags & WCF_ALTFMT) { if (vcP->flags & WCF_INITIALIZED) { bmP = BM_OVERRIDE (gameData.pig.tex.pBitmaps + vcP->frames [0].index); nFrames = ((bmP->bm_type != BM_TYPE_ALT) && BM_PARENT (bmP)) ? BM_FRAMECOUNT (BM_PARENT (bmP)) : BM_FRAMECOUNT (bmP); } else { bmP = SetupHiresAnim ((short *) vcP->frames, nFrames, -1, 0, 1, &nFrames); if (!bmP) vcP->flags &= ~WCF_ALTFMT; else if (!gameOpts->ogl.bGlTexMerge) vcP->flags &= ~WCF_ALTFMT; else vcP->flags |= WCF_INITIALIZED; } } vci->xFrameTime -= xPowerupTime + xFudge; while (vci->xFrameTime < 0) { vci->xFrameTime += vcP->xFrameTime; if (i & 1) { if (0 > -- (vci->nCurFrame)) vci->nCurFrame = nFrames - 1; } else { if (++ (vci->nCurFrame) >= nFrames) vci->nCurFrame = 0; } } if (objP->lifeleft <= 0) { ObjectCreateExplosion (objP->segnum, &objP->pos, F1_0 * 7 / 2, VCLIP_POWERUP_DISAPPEARANCE); if (gameData.eff.vClips [0][VCLIP_POWERUP_DISAPPEARANCE].sound_num > -1) DigiLinkSoundToObject ( gameData.eff.vClips [0][VCLIP_POWERUP_DISAPPEARANCE].sound_num, OBJ_IDX (objP), 0, F1_0); } xPowerupTime = 0; } }
//------------------------------------------------------------------------------ //blows up a xBadAss weapon, creating the xBadAss explosion //return the explosion tObject tObject *ExplodeBadassWeapon (tObject *objP, vmsVector *pos) { tWeaponInfo *wi = &gameData.weapons.info [objP->id]; Assert (wi->damage_radius); if ((objP->id == EARTHSHAKER_ID) || (objP->id == ROBOT_EARTHSHAKER_ID)) ShakerRockStuff (); DigiLinkSoundToObject (SOUND_BADASS_EXPLOSION, OBJ_IDX (objP), 0, F1_0, SOUNDCLASS_EXPLOSION); return ObjectCreateBadassExplosion (objP, objP->nSegment, pos, wi->impact_size, wi->robot_hit_vclip, wi->strength [gameStates.app.nDifficultyLevel], wi->damage_radius, wi->strength [gameStates.app.nDifficultyLevel], objP->cType.laserInfo.nParentObj); }
void DoSnipeFrame (tObject *objP) { if (gameData.ai.xDistToPlayer <= MAX_SNIPE_DIST) { tAILocalInfo *ailP = gameData.ai.localInfo + OBJ_IDX (objP); int i = ailP->mode; if ((i >= AIM_SNIPE_ATTACK) && (i <= AIM_SNIPE_WAIT)) aiSnipeHandlers [i - AIM_SNIPE_ATTACK] (objP, ailP); else { Int3 (); // Oops, illegal mode for snipe behavior. ailP->mode = AIM_SNIPE_ATTACK; ailP->nextActionTime = F1_0; } } }
int DoAnyRobotDyingFrame (tObject *objP) { if (objP->cType.aiInfo.xDyingStartTime) { int bDeathRoll = ROBOTINFO (objP->id).bDeathRoll; int rval = DoRobotDyingFrame (objP, objP->cType.aiInfo.xDyingStartTime, min (bDeathRoll/2+1,6)*F1_0, &objP->cType.aiInfo.bDyingSoundPlaying, ROBOTINFO (objP->id).deathrollSound, bDeathRoll*F1_0/8, bDeathRoll*F1_0/2); if (rval) { ExplodeObject (objP, F1_0/4); DigiLinkSoundToObject2 (SOUND_BADASS_EXPLOSION, OBJ_IDX (objP), 0, F2_0, F1_0*512, SOUNDCLASS_EXPLOSION); if ((gameData.missions.nCurrentLevel < 0) && (ROBOTINFO (objP->id).thief)) RecreateThief (objP); } return 1; } return 0; }
void DrawPowerup (object *objP) { bitmap_index *frameP = gameData.eff.vClips [0][objP->rtype.vclip_info.nClipIndex].frames; int iFrame = objP->rtype.vclip_info.nCurFrame; #ifdef EDITOR blob_vertices[0] = 0x80000; #endif DrawObjectBlob (objP, *frameP, frameP [iFrame], iFrame, NULL, 0); #ifdef EDITOR if ((gameStates.app.nFunctionMode == FMODE_EDITOR) && (Cur_object_index == OBJ_IDX (objP))) if (blob_vertices[0] != 0x80000) DrawBlobOutline (); #endif }
void AIIdleAnimation (tObject *objP) { if (gameOpts->gameplay.bIdleAnims) { int h, i, j; tSegment *segP = gameData.segs.segments + objP->nSegment; vmsVector *vVertex, vVecToGoal, vGoal = gameData.objs.vRobotGoals [OBJ_IDX (objP)]; for (i = 0; i < 8; i++) { vVertex = gameData.segs.vertices + segP->verts [i]; if ((vGoal.p.x == vVertex->p.x) && (vGoal.p.y == vVertex->p.y) && (vGoal.p.z == vVertex->p.z)) break; } VmVecNormalize (VmVecSub (&vVecToGoal, &vGoal, &objP->position.vPos)); if (i == 8) h = 1; else if (AITurnTowardsVector (&vVecToGoal, objP, ROBOTINFO (objP->id).turnTime [2]) < F1_0 - F1_0 / 5) { if (VmVecDot (&vVecToGoal, &objP->position.mOrient.fVec) > F1_0 - F1_0 / 5) h = rand () % 2 == 0; else h = 0; } else if (MoveTowardsPoint (objP, &vGoal, objP->size * 3 / 2)) h = rand () % 8 == 0; else h = 1; if (h && (rand () % 25 == 0)) { j = rand () % 8; if ((j == i) || (rand () % 3 == 0)) COMPUTE_SEGMENT_CENTER_I (&vGoal, objP->nSegment); else vGoal = gameData.segs.vertices [segP->verts [j]]; gameData.objs.vRobotGoals [OBJ_IDX (objP)] = vGoal; DoSillyAnimation (objP); } } }
//sets the tPlayer facing curseg/curside, normal to face0 of curside, and //far enough away to see all of curside int SetPlayerFromCursegMinusOne() { vmsVector view_vec,view_vec2,side_center; vmsVector corner_v[4]; vmsVector upvec; g3sPoint corner_p[4]; int i; fix max,viewDist=f1_0*10; static int edgenum=0; int newseg; view_vec = Cursegp->sides[Curside].normals[0]; VmVecNegate(&view_vec); COMPUTE_SIDE_CENTER(&side_center,Cursegp,Curside); VmVecCopyScale(&view_vec2,&view_vec,viewDist); VmVecSub(&gameData.objs.console->position.vPos,&side_center,&view_vec2); VmVecSub(&upvec, &gameData.segs.vertices[Cursegp->verts[sideToVerts[Curside][edgenum%4]]], &gameData.segs.vertices[Cursegp->verts[sideToVerts[Curside][(edgenum+3)%4]]]); edgenum++; VmVector2Matrix(&gameData.objs.console->position.mOrient,&view_vec,&upvec,NULL); GrSetCurrentCanvas(Canv_editor_game); G3StartFrame(); G3SetViewMatrix(&gameData.objs.console->position.vPos,&gameData.objs.console->position.mOrient,gameStates.render.xZoom, 1); for (i=max=0;i<4;i++) { corner_v[i] = gameData.segs.vertices[Cursegp->verts[sideToVerts[Curside][i]]]; G3TransformAndEncodePoint(&corner_p[i],&corner_v[i]); if (labs(corner_p[i].p3_x) > max) max = labs(corner_p[i].p3_x); if (labs(corner_p[i].p3_y) > max) max = labs(corner_p[i].p3_y); } viewDist = FixMul(viewDist,FixDiv(FixDiv(max,SIDE_VIEW_FRAC),corner_p[0].p3_z); VmVecCopyScale(&view_vec2,&view_vec,viewDist); VmVecSub(&gameData.objs.console->position.vPos,&side_center,&view_vec2); //RelinkObject(OBJ_IDX (gameData.objs.console), SEG_IDX(Cursegp) ); //UpdateObjectSeg(gameData.objs.console); //might have backed right out of curseg newseg = FindSegByPoint(&gameData.objs.console->position.vPos, SEG_IDX(Cursegp), 1, 0); if (newseg != -1) RelinkObject(OBJ_IDX (gameData.objs.console),newseg); UpdateFlags |= UF_ED_STATE_CHANGED | UF_GAME_VIEW_CHANGED; return 1; }
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
int CreateCameras (void) { int h, i, j, k, r; ubyte t; tWall *wallP; tObject *objP; tTrigger *triggerP; if (!gameStates.app.bD2XLevel) return 0; PrintLog (" creating cameras\n"); memset (gameData.cameras.nSides, 0xFF, MAX_SEGMENTS * 6 * sizeof (*gameData.cameras.nSides)); for (i = 0, wallP = gameData.walls.walls; i < gameData.walls.nWalls; i++, wallP++) { t = wallP->nTrigger; if (t >= gameData.trigs.nTriggers) continue; triggerP = gameData.trigs.triggers + t; if (triggerP->nType == TT_CAMERA) { for (j = 0; j < triggerP->nLinks; j++) if (CreateCamera (gameData.cameras.cameras + gameData.cameras.nCameras, (short) wallP->nSegment, (short) wallP->nSide, triggerP->nSegment [j], triggerP->nSide [j], NULL, 0, 0)) gameData.cameras.nSides [triggerP->nSegment [j] * 6 + triggerP->nSide [j]] = (char) gameData.cameras.nCameras++; } #if TELEPORT_CAMERAS else if (/*EGI_FLAG (bTeleporterCams, 0, 0) &&*/ (triggerP->nType == TT_TELEPORT)) { if (CreateCamera (gameData.cameras.cameras + gameData.cameras.nCameras, triggerP->nSegment [0], triggerP->nSide [0], (short) wallP->nSegment, (short) wallP->nSide, NULL, 0, 1)) gameData.cameras.nSides [wallP->nSegment * 6 + wallP->nSide] = (char) gameData.cameras.nCameras++; } #endif } FORALL_OBJS (objP, i) { r = j = gameData.trigs.firstObjTrigger [OBJ_IDX (objP)]; #if DBG if (j >= 0) j = j; #endif for (h = sizeofa (gameData.trigs.objTriggerRefs); (j >= 0) && h; h--) { triggerP = gameData.trigs.objTriggers + j; if (triggerP->nType == TT_CAMERA) { for (k = 0; k < triggerP->nLinks; k++) if (CreateCamera (gameData.cameras.cameras + gameData.cameras.nCameras, -1, -1, triggerP->nSegment [k], triggerP->nSide [k], objP, 0, 0)) gameData.cameras.nSides [triggerP->nSegment [k] * 6 + triggerP->nSide [k]] = (char) gameData.cameras.nCameras++; } if (r == (j = gameData.trigs.objTriggerRefs [j].next)) break; } }
//------------------------------------------------------------------------------ //set viewerP CObject to next CObject in array void ObjectGotoPrevViewer (void) { CObject *objP; int nStartObj = 0; //int i; nStartObj = OBJ_IDX (gameData.objs.viewerP); //get viewerP CObject number FORALL_OBJS (objP, i) { if (--nStartObj < 0) nStartObj = gameData.objs.nLastObject [0]; if (OBJECTS [nStartObj].info.nType != OBJ_NONE) { gameData.objs.viewerP = OBJECTS + nStartObj; return; } } Error ("Couldn't find a viewerP CObject!"); }
void DoMissileSmoke (tObject *objP) { int nParts, nSpeed, nLife, i; float nScale = 1.5f; tThrusterInfo ti; i = OBJ_IDX (objP); if (!(SHOW_SMOKE && gameOpts->render.smoke.bMissiles)) { if (gameData.smoke.objects [i] >= 0) KillObjectSmoke (i); return; } if ((objP->info.xShields < 0) || (objP->info.nFlags & (OF_SHOULD_BE_DEAD | OF_DESTROYED))) nParts = 0; else { nSpeed = WI_speed (objP->info.nId, gameStates.app.nDifficultyLevel); nLife = gameOpts->render.smoke.nLife [3] + 1; #if 1 nParts = (int) (MSL_MAX_PARTS * X2F (nSpeed) / (40.0f * (4 - nLife))); if ((objP->info.nId == EARTHSHAKER_MEGA_ID) || (objP->info.nId == ROBOT_SHAKER_MEGA_ID)) nParts /= 2; #else nParts = (objP->info.nId == EARTHSHAKER_ID) ? 1500 : (objP->info.nId == MEGAMSL_ID) ? 1400 : (objP->info.nId == SMARTMSL_ID) ? 1300 : 1200; #endif } if (nParts) { if (gameData.smoke.objects [i] < 0) { if (!gameOpts->render.smoke.bSyncSizes) { nParts = -MAX_PARTICLES (nParts, gameOpts->render.smoke.nDens [3]); nScale = PARTICLE_SIZE (gameOpts->render.smoke.nSize [3], nScale); } SetSmokeObject (i, CreateSmoke (&objP->info.position.vPos, NULL, NULL, objP->info.nSegment, 1, nParts, nScale, gameOpts->render.smoke.bSyncSizes ? -1 : gameOpts->render.smoke.nSize [3], 1, nLife * MSL_PART_LIFE, MSL_PART_SPEED, SMOKE_PARTICLES, i, smokeColors + 1, 1, -1)); } CalcThrusterPos (objP, &ti, 0); SetSmokePos (gameData.smoke.objects [i], ti.vPos, NULL, objP->info.nSegment); } else KillObjectSmoke (i); }
void DrawPowerup (tObject *objP) { if (objP->nType == OBJ_MONSTERBALL) DrawMonsterball (objP, 1.0f, 0.5f, 0.0f, 0.9f); else { tBitmapIndex *frameP = gameData.eff.vClips [0][objP->rType.vClipInfo.nClipIndex].frames; int iFrame = objP->rType.vClipInfo.nCurFrame; #ifdef EDITOR blob_vertices[0] = 0x80000; #endif DrawObjectBlob (objP, *frameP, frameP [iFrame], iFrame, NULL, 0); #ifdef EDITOR if ((gameStates.app.nFunctionMode == FMODE_EDITOR) && (CurObject_index == OBJ_IDX (objP))) if (blob_vertices[0] != 0x80000) DrawBlobOutline (); #endif } }
void DoStaticSmoke (tObject *objP) { int i, j, bBubbles = objP->rType.smokeInfo.nType == SMOKE_TYPE_BUBBLES; vmsVector pos, offs, dir; static tRgbaColorf defaultColors [2] = {{0.5f, 0.5f, 0.5f, 0.0f}, {0.8f, 0.9f, 1.0f, 1.0f}}; i = (int) OBJ_IDX (objP); if (!(SHOW_SMOKE && gameOpts->render.smoke.bStatic)) { if (gameData.smoke.objects [i] >= 0) KillObjectSmoke (i); return; } if (gameData.smoke.objects [i] < 0) { tRgbaColorf color; int bColor; color.red = (float) objP->rType.smokeInfo.color.red / 255.0f; color.green = (float) objP->rType.smokeInfo.color.green / 255.0f; color.blue = (float) objP->rType.smokeInfo.color.blue / 255.0f; if ((bColor = (color.red + color.green + color.blue > 0))) color.alpha = (float) -objP->rType.smokeInfo.color.alpha / 255.0f; dir = objP->info.position.mOrient [FVEC] * (objP->rType.smokeInfo.nSpeed * 2 * F1_0 / 55); SetSmokeObject (i, CreateSmoke (&objP->info.position.vPos, &dir, &objP->info.position.mOrient, objP->info.nSegment, 1, -objP->rType.smokeInfo.nParts, -PARTICLE_SIZE (objP->rType.smokeInfo.nSize [gameOpts->render.smoke.bDisperse], 2.0f), -1, 3, STATIC_SMOKE_PART_LIFE * objP->rType.smokeInfo.nLife, objP->rType.smokeInfo.nDrift, bBubbles ? BUBBLE_PARTICLES : SMOKE_PARTICLES, i, bColor ? &color : defaultColors + bBubbles, 1, objP->rType.smokeInfo.nSide - 1)); SetSmokeBrightness (gameData.smoke.objects [i], objP->rType.smokeInfo.nBrightness); } if (objP->rType.smokeInfo.nSide <= 0) { //don't vary emitter position for smoke emitting faces i = objP->rType.smokeInfo.nDrift >> 4; i += objP->rType.smokeInfo.nSize [0] >> 2; i /= 2; if (!(j = i - i / 2)) j = 2; i /= 2; offs [X] = (F1_0 / 4 - d_rand ()) * (d_rand () % j + i); offs [Y] = (F1_0 / 4 - d_rand ()) * (d_rand () % j + i); offs [Z] = (F1_0 / 4 - d_rand ()) * (d_rand () % j + i); pos = objP->info.position.vPos + offs; SetSmokePos (gameData.smoke.objects [i], &pos, NULL, objP->info.nSegment); }
void move_player_2_segment_and_rotate(tSegment *seg,int tSide) { vmsVector vp; vmsVector upvec; static int edgenum=0; COMPUTE_SEGMENT_CENTER(&gameData.objs.console->position.vPos,seg); COMPUTE_SIDE_CENTER(&vp,seg,tSide); VmVecDec(&vp,&gameData.objs.console->position.vPos); VmVecSub(&upvec, &gameData.segs.vertices[Cursegp->verts[sideToVerts[Curside][edgenum%4]]], &gameData.segs.vertices[Cursegp->verts[sideToVerts[Curside][(edgenum+3)%4]]]); edgenum++; VmVector2Matrix(&gameData.objs.console->position.mOrient,&vp,&upvec,NULL); // VmVector2Matrix(&gameData.objs.console->position.mOrient,&vp,NULL,NULL); RelinkObject( OBJ_IDX (gameData.objs.console), SEG_IDX(seg) ); }
void PhysApplyForce (tObject *objP, vmsVector *vForce) { // Put in by MK on 2/13/96 for force getting applied to Omega blobs, which have 0 mass, // in collision with crazy reactor robot thing on d2levf-s. if (objP->mType.physInfo.mass == 0) return; if (objP->movementType != MT_PHYSICS) return; #ifdef TACTILE if (TactileStick && obj==&gameData.objs.objects [gameData.multi.players [gameData.multi.nLocalPlayer].nObject]) Tactile_apply_force (vForce, &objP->orient); #endif //Add in acceleration due to force if (!gameData.objs.speedBoost [OBJ_IDX (objP)].bBoosted || (objP != gameData.objs.console)) VmVecScaleInc (&objP->mType.physInfo.velocity, vForce, FixDiv (f1_0, objP->mType.physInfo.mass)); }
// ---------------------------------------------------------------------- // General purpose robot-dies-with-death-roll-and-groan code. // Return true if tObject just died. // scale: F1_0*4 for boss, much smaller for much smaller guys int DoRobotDyingFrame (tObject *objP, fix StartTime, fix xRollDuration, sbyte *bDyingSoundPlaying, short deathSound, fix xExplScale, fix xSoundScale) { fix xRollVal, temp; fix xSoundDuration; tDigiSound *soundP; if (!xRollDuration) xRollDuration = F1_0/4; xRollVal = FixDiv (gameData.time.xGame - StartTime, xRollDuration); FixSinCos (FixMul (xRollVal, xRollVal), &temp, &objP->mType.physInfo.rotVel.p.x); FixSinCos (xRollVal, &temp, &objP->mType.physInfo.rotVel.p.y); FixSinCos (xRollVal-F1_0/8, &temp, &objP->mType.physInfo.rotVel.p.z); temp = gameData.time.xGame - StartTime; objP->mType.physInfo.rotVel.p.x = temp / 9; objP->mType.physInfo.rotVel.p.y = temp / 5; objP->mType.physInfo.rotVel.p.z = temp / 7; if (gameOpts->sound.digiSampleRate) { soundP = gameData.pig.sound.pSounds + DigiXlatSound (deathSound); xSoundDuration = FixDiv (soundP->nLength [soundP->bHires], gameOpts->sound.digiSampleRate); } else xSoundDuration = F1_0; if (StartTime + xRollDuration - xSoundDuration < gameData.time.xGame) { if (!*bDyingSoundPlaying) { #if TRACE con_printf (CONDBG, "Starting death sound!\n"); #endif *bDyingSoundPlaying = 1; DigiLinkSoundToObject2 (deathSound, OBJ_IDX (objP), 0, xSoundScale, xSoundScale * 256, SOUNDCLASS_ROBOT); // F1_0*512 means play twice as loud } else if (d_rand () < gameData.time.xFrame*16) CreateSmallFireballOnObject (objP, (F1_0 + d_rand ()) * (16 * xExplScale/F1_0) / 8, 0); } else if (d_rand () < gameData.time.xFrame * 8) CreateSmallFireballOnObject (objP, (F1_0/2 + d_rand ()) * (16 * xExplScale / F1_0) / 8, 1); return (StartTime + xRollDuration < gameData.time.xGame); }
int CanSeeObject (int nObject, int bCheckObjs) { CHitQuery fq; int nHitType; CHitData hitData; //see if we can see this CPlayerData fq.p0 = &gameData.objs.viewerP->info.position.vPos; fq.p1 = &OBJECTS [nObject].info.position.vPos; fq.radP0 = fq.radP1 = 0; fq.thisObjNum = gameStates.render.cameras.bActive ? -1 : OBJ_IDX (gameData.objs.viewerP); fq.flags = bCheckObjs ? FQ_CHECK_OBJS | FQ_TRANSWALL : FQ_TRANSWALL; fq.startSeg = gameData.objs.viewerP->info.nSegment; fq.ignoreObjList = NULL; fq.bCheckVisibility = false; nHitType = FindHitpoint (&fq, &hitData); return bCheckObjs ? (nHitType == HIT_OBJECT) && (hitData.hit.nObject == nObject) : (nHitType != HIT_WALL); }
void DoReactorSmoke (tObject *objP) { int h = -1, i, nShields = 0, nParts; vmsVector vDir, vPos; i = OBJ_IDX (objP); if (!(SHOW_SMOKE && gameOpts->render.smoke.bRobots)) { if (gameData.smoke.objects [i] >= 0) KillObjectSmoke (i); return; } if ((objP->info.xShields < 0) || (objP->info.nFlags & (OF_SHOULD_BE_DEAD | OF_DESTROYED))) nParts = 0; else { nShields = X2IR (gameData.bots.info [gameStates.app.bD1Mission][objP->info.nId].strength); h = nShields ? X2IR (objP->info.xShields) * 100 / nShields : 0; } if (h < 0) h = 0; nParts = 10 - h / 10; if (nParts > 0) { nParts = REACTOR_MAX_PARTS; if (gameData.smoke.objects [i] < 0) { //PrintLog ("creating robot %d smoke\n", i); SetSmokeObject (i, CreateSmoke (&objP->info.position.vPos, NULL, NULL, objP->info.nSegment, 1, nParts, F2X (-4.0), -1, 1, BOT_PART_LIFE * 2, BOT_PART_SPEED, SMOKE_PARTICLES, i, smokeColors, 1, -1)); } else { SetSmokePartScale (gameData.smoke.objects [i], F2X (-4.0)); SetSmokeDensity (gameData.smoke.objects [i], nParts, -1); vDir[X] = d_rand () - F1_0 / 4; vDir[Y] = d_rand () - F1_0 / 4; vDir[Z] = d_rand () - F1_0 / 4; vmsVector::Normalize(vDir); vPos = objP->info.position.vPos + vDir * (-objP->info.xSize / 2); SetSmokePos (gameData.smoke.objects [i], &vPos, NULL, objP->info.nSegment); } } else KillObjectSmoke (i); }
void DoReactorSmoke (tObject *objP) { int h = -1, i, nShields = 0, nParts; vmsVector vDir, vPos; i = OBJ_IDX (objP); if (!(SHOW_SMOKE && gameOpts->render.smoke.bRobots)) { if (gameData.smoke.objects [i] >= 0) KillObjectSmoke (i); return; } if ((objP->shields < 0) || (objP->flags & (OF_SHOULD_BE_DEAD | OF_DESTROYED))) nParts = 0; else { nShields = f2ir (gameData.bots.info [gameStates.app.bD1Mission][objP->id].strength); h = nShields ? f2ir (objP->shields) * 100 / nShields : 0; } if (h < 0) h = 0; nParts = 10 - h / 10; if (nParts > 0) { nParts = REACTOR_MAX_PARTS; if (gameData.smoke.objects [i] < 0) { //PrintLog ("creating robot %d smoke\n", i); SetSmokeObject (i, CreateSmoke (&objP->position.vPos, NULL, NULL, objP->nSegment, 1, nParts, fl2f (-4.0), -1, 1, BOT_PART_LIFE * 2, BOT_PART_SPEED, 0, i, NULL, 1, -1)); } else { SetSmokePartScale (gameData.smoke.objects [i], fl2f (-4.0)); SetSmokeDensity (gameData.smoke.objects [i], nParts, -1); vDir.p.x = d_rand () - F1_0 / 4; vDir.p.y = d_rand () - F1_0 / 4; vDir.p.z = d_rand () - F1_0 / 4; VmVecNormalize (&vDir); VmVecScaleAdd (&vPos, &objP->position.vPos, &vDir, -objP->size / 2); SetSmokePos (gameData.smoke.objects [i], &vPos, NULL, objP->nSegment); } } else KillObjectSmoke (i); }
void DoStaticSmoke (tObject *objP) { int i, j; vmsVector pos, offs, dir; i = (int) OBJ_IDX (objP); if (!(SHOW_SMOKE && gameOpts->render.smoke.bStatic)) { if (gameData.smoke.objects [i] >= 0) KillObjectSmoke (i); return; } if (gameData.smoke.objects [i] < 0) { tRgbaColorf color; int bColor; color.red = (float) objP->rType.smokeInfo.color.red / 255.0f; color.green = (float) objP->rType.smokeInfo.color.green / 255.0f; color.blue = (float) objP->rType.smokeInfo.color.blue / 255.0f; if ((bColor = (color.red + color.green + color.blue > 0))) color.alpha = (float) objP->rType.smokeInfo.color.alpha / 255.0f; VmVecCopyScale (&dir, &objP->position.mOrient.fVec, objP->rType.smokeInfo.nSpeed * 2 * F1_0 / 55); SetSmokeObject (i, CreateSmoke (&objP->position.vPos, &dir, NULL, objP->nSegment, 1, -objP->rType.smokeInfo.nParts, -PARTICLE_SIZE (objP->rType.smokeInfo.nSize [gameOpts->render.smoke.bDisperse], 2.0f), -1, 3, STATIC_SMOKE_PART_LIFE * objP->rType.smokeInfo.nLife, objP->rType.smokeInfo.nDrift, 2, i, bColor ? &color : NULL, 1, objP->rType.smokeInfo.nSide - 1)); SetSmokeBrightness (gameData.smoke.objects [i], objP->rType.smokeInfo.nBrightness); } if (objP->rType.smokeInfo.nSide <= 0) { //don't vary emitter position for smoke emitting faces i = objP->rType.smokeInfo.nDrift >> 4; i += objP->rType.smokeInfo.nSize [0] >> 2; i /= 2; if (!(j = i - i / 2)) j = 2; i /= 2; offs.p.x = (F1_0 / 4 - d_rand ()) * (d_rand () % j + i); offs.p.y = (F1_0 / 4 - d_rand ()) * (d_rand () % j + i); offs.p.z = (F1_0 / 4 - d_rand ()) * (d_rand () % j + i); VmVecAdd (&pos, &objP->position.vPos, &offs); SetSmokePos (gameData.smoke.objects [i], &pos, NULL, objP->nSegment); }
//------------------------------------------------------------------------------ //frees up an CObject. Generally, ReleaseObject () should be called to get //rid of an CObject. This function deallocates the CObject entry after //the CObject has been unlinked void FreeObject (int nObject) { CObject *objP = OBJECTS + nObject; #if DBG if ((nObject < 0) || (nObject >= LEVEL_OBJECTS)) return; if (nObject == nDbgObj) { //PrintLog ("freeing object #%d\n", nObject); nDbgObj = nDbgObj; if (dbgObjInstances > 0) dbgObjInstances--; else nDbgObj = nDbgObj; } #endif objP->Unlink (); DelObjChildrenN (nObject); DelObjChildN (nObject); gameData.objs.bWantEffect [nObject] = 0; #if 1 OBJECTS [nObject].RequestEffects (DESTROY_SMOKE | DESTROY_LIGHTNINGS); #else SEM_ENTER (SEM_SMOKE) KillObjectSmoke (nObject); SEM_LEAVE (SEM_SMOKE) SEM_ENTER (SEM_LIGHTNING) lightningManager.DestroyForObject (OBJECTS + nObject); SEM_LEAVE (SEM_LIGHTNING) #endif lightManager.Delete (-1, -1, nObject); gameData.objs.freeList [--gameData.objs.nObjects] = nObject; Assert (gameData.objs.nObjects >= 0); if (nObject == gameData.objs.nLastObject [0]) while (OBJECTS [--gameData.objs.nLastObject [0]].info.nType == OBJ_NONE); #if DBG if (dbgObjP && (OBJ_IDX (dbgObjP) == nObject)) dbgObjP = NULL; #endif }
int NetworkVerifyPlayers (void) { int i, j, t, bCoop = IsCoopGame; int nPlayers, nPlayerObjs [MAX_PLAYERS], bHaveReactor = !bCoop; tObject *objP; tPlayer *playerP; for (j = 0, playerP = gameData.multiplayer.players; j < MAX_PLAYERS; j++, playerP++) nPlayerObjs [j] = playerP->connected ? playerP->nObject : -1; #if 0 if (gameData.app.nGameMode & GM_MULTI_ROBOTS) #endif // bHaveReactor = 1; // multiplayer maps do not need a control center ... nPlayers = 0; FORALL_OBJS (objP, i) { i = OBJ_IDX (objP); t = objP->info.nType; if (t == OBJ_GHOST) { for (j = 0; j < MAX_PLAYERS; j++) { if (nPlayerObjs [j] == i) { nPlayers++; break; } } } else if (t == OBJ_PLAYER) { if (!(i && bCoop)) nPlayers++; } else if (t == OBJ_COOP) { if (bCoop) nPlayers++; } else if (bCoop) { if ((t == OBJ_REACTOR) || ((t == OBJ_ROBOT) && ROBOTINFO (objP->info.nId).bossFlag)) bHaveReactor = 1; } if (nPlayers >= gameData.multiplayer.nMaxPlayers) return 1; }
void DeadPlayerEnd (void) { if (!gameStates.app.bPlayerIsDead) return; if (gameData.demo.nState == ND_STATE_RECORDING) NDRecordRestoreCockpit (); gameStates.app.bPlayerIsDead = 0; gameStates.app.bPlayerExploded = 0; if (gameData.objs.deadPlayerCamera) { ReleaseObject (OBJ_IDX (gameData.objs.deadPlayerCamera)); gameData.objs.deadPlayerCamera = NULL; } CGenericCockpit::Rewind (); gameData.objs.viewerP = viewerSaveP; gameData.objs.consoleP->SetType (OBJ_PLAYER); gameData.objs.consoleP->info.nFlags = nPlayerFlagsSave; Assert ((nControlTypeSave == CT_FLYING) || (nControlTypeSave == CT_SLEW)); gameData.objs.consoleP->info.controlType = nControlTypeSave; gameData.objs.consoleP->info.renderType = nRenderTypeSave; LOCALPLAYER.flags &= ~PLAYER_FLAGS_INVULNERABLE; gameStates.app.bPlayerEggsDropped = 0; }