//----------------------------------------------------------------------------- int MaybeBuddyFireSmart(short objnum) { object *objP = &gameData.objs.objects[objnum]; object *buddyObjP = &gameData.objs.objects[gameData.escort.nObjNum]; fix dist; short weapon_objnum; dist = VmVecDistQuick(&buddyObjP->pos, &objP->pos); if (dist > F1_0*80) return 0; if (!ObjectToObjectVisibility(buddyObjP, objP, FQ_TRANSWALL)) return 0; #if TRACE con_printf (CON_DEBUG, "Buddy firing smart missile in frame %i\n", gameData.app.nFrameCount); #endif BuddyMessage(TXT_BUDDY_WHAMMO); weapon_objnum = CreateNewLaserEasy( &buddyObjP->orient.fvec, &buddyObjP->pos, objnum, SMART_ID, 1); if (weapon_objnum != -1) BashBuddyWeaponInfo(weapon_objnum); return 1; }
// ----------------------------------------------------------------------------- int MaybeBuddyFireMega(short objnum) { object *objP = gameData.objs.objects + objnum; object *buddyObjP = gameData.objs.objects + gameData.escort.nObjNum; fix dist, dot; vms_vector vec_to_robot; int weapon_objnum; VmVecSub(&vec_to_robot, &buddyObjP->pos, &objP->pos); dist = VmVecNormalizeQuick(&vec_to_robot); if (dist > F1_0*100) return 0; dot = VmVecDot(&vec_to_robot, &buddyObjP->orient.fvec); if (dot < F1_0/2) return 0; if (!ObjectToObjectVisibility(buddyObjP, objP, FQ_TRANSWALL)) return 0; if (gameData.weapons.info[MEGA_ID].render_type == 0) { #if TRACE con_printf(CON_VERBOSE, "Buddy can't fire mega (shareware)\n"); #endif BuddyMessage(TXT_BUDDY_CLICK); return 0; } #if TRACE con_printf (CON_DEBUG, "Buddy firing mega in frame %i\n", gameData.app.nFrameCount); #endif BuddyMessage(TXT_BUDDY_GAHOOGA); weapon_objnum = CreateNewLaserEasy( &buddyObjP->orient.fvec, &buddyObjP->pos, objnum, MEGA_ID, 1); if (weapon_objnum != -1) BashBuddyWeaponInfo(weapon_objnum); return 1; }
void RenderObjectShadows (void) { tObject *objP = OBJECTS; int i, j, bSee; tObject fakePlayerPos = *gameData.objs.viewerP; for (i = 0; i <= gameData.objs.nLastObject [0]; i++, objP++) if (objP == gameData.objs.consoleP) RenderObject (objP, 0, 0); else if ((objP->info.nType == OBJ_PLAYER) || (gameOpts->render.shadows.bRobots && (objP->info.nType == OBJ_ROBOT))) { for (j = gameData.render.mine.nRenderSegs; j--;) { fakePlayerPos.info.nSegment = gameData.render.mine.nSegRenderList [j]; COMPUTE_SEGMENT_CENTER_I (&fakePlayerPos.info.position.vPos, fakePlayerPos.info.nSegment); bSee = ObjectToObjectVisibility (objP, &fakePlayerPos, FQ_TRANSWALL); if (bSee) { RenderObject (objP, 0, 0); break; } } } }
void RenderObjectShadows (void) { CObject *objP; //int i; int j, bSee; CObject fakePlayerPos = *gameData.objs.viewerP; FORALL_ACTOR_OBJS (objP, i) if (objP == gameData.objs.consoleP) RenderObject (objP, 0, 0); else if ((objP->info.nType == OBJ_PLAYER) || (gameOpts->render.shadows.bRobots && (objP->info.nType == OBJ_ROBOT))) { for (j = gameData.render.mine.nRenderSegs; j--;) { fakePlayerPos.info.nSegment = gameData.render.mine.nSegRenderList [j]; fakePlayerPos.info.position.vPos = SEGMENTS [fakePlayerPos.info.nSegment].Center (); bSee = ObjectToObjectVisibility (objP, &fakePlayerPos, FQ_TRANSWALL); if (bSee) { RenderObject (objP, 0, 0); break; } } } }
CObject* CreateExplosion (CObject* parentP, short nSegment, CFixVector& vPos, fix xSize, ubyte nVClip, fix xMaxDamage, fix xMaxDistance, fix xMaxForce, short nParent) { short nObject; CObject *explObjP, *objP; fix dist, force, damage; CFixVector vHit, vForce; int nType, id; int flash = parentP ? static_cast<int> (gameData.weapons.info [parentP->info.nId].flash) : 0; nObject = CreateFireball (nVClip, nSegment, vPos, xSize, RT_FIREBALL); if (nObject < 0) { #if TRACE console.printf (1, "Can'nType create CObject in /*Object*/CreateExplosionSub.\n"); #endif return NULL; } explObjP = OBJECTS + nObject; //now set explosion-specific data explObjP->info.xLifeLeft = gameData.eff.vClips [0][nVClip].xTotalTime; explObjP->cType.explInfo.nSpawnTime = -1; explObjP->cType.explInfo.nDeleteObj = -1; explObjP->cType.explInfo.nDeleteTime = -1; if (xMaxDamage <= 0) return explObjP; // -- now legal for xBadAss explosions on a CWall. Assert (this != NULL); FORALL_OBJS (objP, i) { nType = objP->info.nType; id = objP->info.nId; // Weapons used to be affected by xBadAss explosions, but this introduces serious problems. // When a smart bomb blows up, if one of its children goes right towards a nearby CWall, it will // blow up, blowing up all the children. So I remove it. MK, 09/11/94 if (objP == parentP) continue; if (objP->info.nFlags & OF_SHOULD_BE_DEAD) continue; if (nType == OBJ_WEAPON) { if (!WeaponIsMine (objP->info.nId)) continue; } else if (nType == OBJ_ROBOT) { if (nParent < 0) continue; if ((OBJECTS [nParent].info.nType == OBJ_ROBOT) && (OBJECTS [nParent].info.nId == id)) continue; } else if ((nType != OBJ_REACTOR) && (nType != OBJ_PLAYER)) continue; dist = CFixVector::Dist (objP->info.position.vPos, explObjP->info.position.vPos); // Make damage be from 'xMaxDamage' to 0.0, where 0.0 is 'xMaxDistance' away; if (dist >= xMaxDistance) continue; if (!ObjectToObjectVisibility (explObjP, objP, FQ_TRANSWALL)) continue; damage = xMaxDamage - FixMulDiv (dist, xMaxDamage, xMaxDistance); force = xMaxForce - FixMulDiv (dist, xMaxForce, xMaxDistance); // Find the force vector on the CObject CFixVector::NormalizedDir(vForce, objP->info.position.vPos, explObjP->info.position.vPos); vForce *= force; // Find where the point of impact is... (vHit) vHit = explObjP->info.position.vPos - objP->info.position.vPos; vHit *= (FixDiv (objP->info.xSize, objP->info.xSize + dist)); if (nType == OBJ_WEAPON) { objP->ApplyForce (vForce); if (WeaponIsMine (objP->info.nId) && (FixMul (dist, force) > I2X (8000))) { //prox bombs have chance of blowing up objP->Die (); objP->ExplodeBadassWeapon (objP->info.position.vPos); } } else if (nType == OBJ_ROBOT) { CFixVector vNegForce; fix xScale = -2 * (7 - gameStates.app.nDifficultyLevel) / 8; objP->ApplyForce (vForce); // If not a boss, stun for 2 seconds at 32 force, 1 second at 16 force if (flash && !ROBOTINFO (objP->info.nId).bossFlag) { tAIStaticInfo *aip = &objP->cType.aiInfo; int nForce = X2I (FixDiv (vForce.Mag () * flash, gameData.time.xFrame) / 128) + 2; if (explObjP->cType.aiInfo.SKIP_AI_COUNT * gameData.time.xFrame >= I2X (1)) aip->SKIP_AI_COUNT--; else { aip->SKIP_AI_COUNT += nForce; objP->mType.physInfo.rotThrust [X] = ((d_rand () - 16384) * nForce) / 16; objP->mType.physInfo.rotThrust [Y] = ((d_rand () - 16384) * nForce) / 16; objP->mType.physInfo.rotThrust [Z] = ((d_rand () - 16384) * nForce) / 16; objP->mType.physInfo.flags |= PF_USES_THRUST; } } vNegForce [X] = vForce [X] * xScale; vNegForce [Y] = vForce [Y] * xScale; vNegForce [Z] = vForce [Z] * xScale; objP->ApplyRotForce (vNegForce); if (objP->info.xShields >= 0) { if (ROBOTINFO (objP->info.nId).bossFlag && bossProps [gameStates.app.bD1Mission][ROBOTINFO (objP->info.nId).bossFlag - BOSS_D2].bInvulKinetic) damage /= 4; if (objP->ApplyDamageToRobot (damage, nParent)) { if (!gameStates.gameplay.bNoBotAI && parentP && (nParent == LOCALPLAYER.nObject)) cockpit->AddPointsToScore (ROBOTINFO (objP->info.nId).scoreValue); } } if (!flash && ROBOTINFO (objP->info.nId).companion) BuddyOuchMessage (damage); } else if (nType == OBJ_REACTOR) { if (objP->info.xShields >= 0) objP->ApplyDamageToReactor (damage, nParent); } else if (nType == OBJ_PLAYER) { CObject* killerP = NULL; CFixVector vRotForce; // Hack!Warning!Test code! if (flash && (objP->info.nId == gameData.multiplayer.nLocalPlayer)) { int fe = min (I2X (4), force * flash / 32); // For four seconds or less if (parentP->cType.laserInfo.parent.nSignature == gameData.objs.consoleP->info.nSignature) { fe /= 2; force /= 2; } if (force > I2X (1)) { paletteManager.SetFlashDuration (fe); force = PK1 + X2I (PK2 * force); paletteManager.BumpEffect (force, force, force); #if TRACE console.printf (CON_DBG, "force = %7.3f, adding %i\n", X2F (force), PK1 + X2I (PK2*force)); #endif } } if (parentP && IsMultiGame && (parentP->info.nType == OBJ_PLAYER)) killerP = parentP; vRotForce = vForce; if (nParent > -1) { killerP = OBJECTS + nParent; if (killerP != gameData.objs.consoleP) // if someone else whacks you, cut force by 2x vRotForce [X] /= 2; vRotForce [Y] /= 2; vRotForce [Z] /= 2; } vRotForce [X] /= 2; vRotForce [Y] /= 2; vRotForce [Z] /= 2; objP->ApplyForce (vForce); objP->ApplyRotForce (vRotForce); if (gameStates.app.nDifficultyLevel == 0) damage /= 4; if (objP->info.xShields >= 0) objP->ApplyDamageToPlayer (killerP, damage); } }
tObject *ObjectCreateExplosionSub (tObject *objP, short nSegment, vmsVector *vPos, fix xSize, ubyte nVClip, fix xMaxDamage, fix xMaxDistance, fix xMaxForce, short nParent) { short nObject; tObject *explObjP, *obj0P; fix dist, force, damage; vmsVector pos_hit, vForce; int i, t, id; nObject = CreateObject (OBJ_FIREBALL, nVClip, -1, nSegment, vPos, &vmdIdentityMatrix, xSize, CT_EXPLOSION, MT_NONE, RT_FIREBALL, 1); if (nObject < 0) { #if TRACE con_printf (1, "Can't create tObject in ObjectCreateExplosionSub.\n"); #endif return NULL; } explObjP = gameData.objs.objects + nObject; //now set explosion-specific data explObjP->lifeleft = gameData.eff.vClips [0][nVClip].xTotalTime; explObjP->cType.explInfo.nSpawnTime = -1; explObjP->cType.explInfo.nDeleteObj = -1; explObjP->cType.explInfo.nDeleteTime = -1; if (xMaxDamage <= 0) return explObjP; // -- now legal for xBadAss explosions on a tWall. Assert (objP != NULL); for (i = 0, obj0P = gameData.objs.objects; i <= gameData.objs.nLastObject; i++, obj0P++) { t = obj0P->nType; id = obj0P->id; // Weapons used to be affected by xBadAss explosions, but this introduces serious problems. // When a smart bomb blows up, if one of its children goes right towards a nearby tWall, it will // blow up, blowing up all the children. So I remove it. MK, 09/11/94 if (obj0P == objP) continue; if (obj0P->flags & OF_SHOULD_BE_DEAD) continue; if (t == OBJ_WEAPON) { if (!WeaponIsMine (obj0P->id)) continue; } else if (t == OBJ_ROBOT) { if (nParent < 0) continue; if ((gameData.objs.objects [nParent].nType == OBJ_ROBOT) && (gameData.objs.objects [nParent].id == id)) continue; } else if ((t != OBJ_REACTOR) && (t != OBJ_PLAYER)) continue; dist = VmVecDistQuick (&obj0P->position.vPos, &explObjP->position.vPos); // Make damage be from 'xMaxDamage' to 0.0, where 0.0 is 'xMaxDistance' away; if (dist >= xMaxDistance) continue; if (!ObjectToObjectVisibility (explObjP, obj0P, FQ_TRANSWALL)) continue; damage = xMaxDamage - FixMulDiv (dist, xMaxDamage, xMaxDistance); force = xMaxForce - FixMulDiv (dist, xMaxForce, xMaxDistance); // Find the force vector on the tObject VmVecNormalizedDirQuick (&vForce, &obj0P->position.vPos, &explObjP->position.vPos); VmVecScale (&vForce, force); // Find where the point of impact is... (pos_hit) VmVecSub (&pos_hit, &explObjP->position.vPos, &obj0P->position.vPos); VmVecScale (&pos_hit, FixDiv (obj0P->size, obj0P->size + dist)); if (t == OBJ_WEAPON) { PhysApplyForce (obj0P, &vForce); if (WeaponIsMine (obj0P->id) && (FixMul (dist, force) > i2f (8000))) { //prox bombs have chance of blowing up KillObject (obj0P); ExplodeBadassWeapon (obj0P, &obj0P->position.vPos); } } else if (t == OBJ_ROBOT) { vmsVector vNegForce; fix xScale = -2 * (7 - gameStates.app.nDifficultyLevel) / 8; PhysApplyForce (obj0P, &vForce); // If not a boss, stun for 2 seconds at 32 force, 1 second at 16 force if (objP && (!ROBOTINFO (obj0P->id).bossFlag) && (gameData.weapons.info [objP->id].flash)) { tAIStatic *aip = &obj0P->cType.aiInfo; int force_val = f2i (FixDiv (VmVecMagQuick (&vForce) * gameData.weapons.info [objP->id].flash, gameData.time.xFrame)/128) + 2; if (explObjP->cType.aiInfo.SKIP_AI_COUNT * gameData.time.xFrame >= F1_0) aip->SKIP_AI_COUNT--; else { aip->SKIP_AI_COUNT += force_val; obj0P->mType.physInfo.rotThrust.p.x = ((d_rand () - 16384) * force_val)/16; obj0P->mType.physInfo.rotThrust.p.y = ((d_rand () - 16384) * force_val)/16; obj0P->mType.physInfo.rotThrust.p.z = ((d_rand () - 16384) * force_val)/16; obj0P->mType.physInfo.flags |= PF_USES_THRUST; } } vNegForce.p.x = vForce.p.x * xScale; vNegForce.p.y = vForce.p.y * xScale; vNegForce.p.z = vForce.p.z * xScale; PhysApplyRot (obj0P, &vNegForce); if (obj0P->shields >= 0) { if (ROBOTINFO (obj0P->id).bossFlag && bossProps [gameStates.app.bD1Mission][ROBOTINFO (obj0P->id).bossFlag-BOSS_D2].bInvulKinetic) damage /= 4; if (ApplyDamageToRobot (obj0P, damage, nParent) && objP && (nParent == LOCALPLAYER.nObject)) AddPointsToScore (ROBOTINFO (obj0P->id).scoreValue); } if (objP && (ROBOTINFO (obj0P->id).companion) && !gameData.weapons.info [objP->id].flash) { int i, count; char szOuch [6*4 + 2]; count = f2i (damage / 8); if (count > 4) count = 4; else if (count <= 0) count = 1; szOuch [0] = 0; for (i = 0; i < count; i++) { strcat (szOuch, TXT_BUDDY_OUCH); strcat (szOuch, " "); } BuddyMessage (szOuch); } } else if (t == OBJ_REACTOR) { if (obj0P->shields >= 0) ApplyDamageToReactor (obj0P, damage, nParent); } else if (t == OBJ_PLAYER) { tObject *killerP = NULL; vmsVector vForce2; // Hack!Warning!Test code! if (objP && gameData.weapons.info [objP->id].flash && obj0P->id==gameData.multiplayer.nLocalPlayer) { int fe = min (F1_0*4, force*gameData.weapons.info [objP->id].flash/32); // For four seconds or less if (objP->cType.laserInfo.nParentSig == gameData.objs.console->nSignature) { fe /= 2; force /= 2; } if (force > F1_0) { gameData.render.xFlashEffect = fe; PALETTE_FLASH_ADD (PK1 + f2i (PK2*force), PK1 + f2i (PK2*force), PK1 + f2i (PK2*force)); #if TRACE con_printf (CONDBG, "force = %7.3f, adding %i\n", f2fl (force), PK1 + f2i (PK2*force)); #endif } } if (objP && IsMultiGame && (objP->nType == OBJ_PLAYER)) killerP = objP; vForce2 = vForce; if (nParent > -1) { killerP = gameData.objs.objects + nParent; if (killerP != gameData.objs.console) // if someone else whacks you, cut force by 2x vForce2.p.x /= 2; vForce2.p.y /= 2; vForce2.p.z /= 2; } vForce2.p.x /= 2; vForce2.p.y /= 2; vForce2.p.z /= 2; PhysApplyForce (obj0P, &vForce); PhysApplyRot (obj0P, &vForce2); if (gameStates.app.nDifficultyLevel == 0) damage /= 4; if (obj0P->shields >= 0) ApplyDamageToPlayer (obj0P, killerP, damage); } } return explObjP; }
//----------------------------------------------------------------------------- // Create the children of a smart bomb, which is a bunch of homing missiles. void CreateSmartChildren (CObject *objP, int nSmartChildren) { tParentInfo parent; int bMakeSound; int nObjects = 0; int objList [MAX_OBJDISTS]; ubyte nBlobId, nObjType = objP->info.nType, nObjId = objP->info.nId; if (nObjType == OBJ_WEAPON) { parent = objP->cType.laserInfo.parent; } else if (nObjType == OBJ_ROBOT) { parent.nType = OBJ_ROBOT; parent.nObject = objP->Index (); } else { Int3 (); // Hey, what kind of CObject is this!? parent.nType = 0; parent.nObject = 0; } if (nObjType == OBJ_WEAPON) { if (gameData.weapons.info [nObjId].children < 1) //if ((nObjId == SMARTMSL_ID) || (nObjId == SMARTMINE_ID) || (nObjId == ROBOT_SMARTMINE_ID) || (nObjId == EARTHSHAKER_ID)) && return; if (nObjId == EARTHSHAKER_ID) BlastNearbyGlass (objP, gameData.weapons.info [EARTHSHAKER_ID].strength [gameStates.app.nDifficultyLevel]); } else if (nObjType != OBJ_ROBOT) // && ((nObjType != OBJ_WEAPON) || (gameData.weapons.info [nObjId].children < 1))) return; int i, nObject; CObject *curObjP; if (IsMultiGame) d_srand (gameStates.app.nRandSeed = 8321L); FORALL_OBJS (curObjP, nObject) { nObject = OBJ_IDX (curObjP); if (curObjP->info.nType == OBJ_PLAYER) { if (nObject == parent.nObject) continue; if ((parent.nType == OBJ_PLAYER) && (IsCoopGame)) continue; if (IsTeamGame && (GetTeam (curObjP->info.nId) == GetTeam (OBJECTS [parent.nObject].info.nId))) continue; if (gameData.multiplayer.players [curObjP->info.nId].flags & PLAYER_FLAGS_CLOAKED) continue; } else if (curObjP->info.nType == OBJ_ROBOT) { if (curObjP->cType.aiInfo.CLOAKED) continue; if (parent.nType == OBJ_ROBOT) // Robot blobs can't track robots. continue; if ((parent.nType == OBJ_PLAYER) && ROBOTINFO (curObjP->info.nId).companion) // Your shots won't track the buddy. continue; } else continue; fix dist = CFixVector::Dist (objP->info.position.vPos, curObjP->info.position.vPos); if (dist < MAX_SMART_DISTANCE) { int oovis = ObjectToObjectVisibility (objP, curObjP, FQ_TRANSWALL); if (oovis) { //ObjectToObjectVisibility (objP, curObjP, FQ_TRANSWALL)) { objList [nObjects++] = nObject; if (nObjects >= MAX_OBJDISTS) { nObjects = MAX_OBJDISTS; break; } } } }