// ------------------------------------------------------------------------------------ // Return: // Bits set: // HAS_WEAPON_FLAG // HAS_ENERGY_FLAG // HAS_AMMO_FLAG // See weapon[HA] for bit values int PlayerHasWeapon (int nWeapon, int bSecondary, int nPlayer, int bAll) { int returnValue = 0; int nWeaponIndex; tPlayer *playerP = gameData.multiplayer.players + ((nPlayer < 0) ? gameData.multiplayer.nLocalPlayer : nPlayer); // Hack! If energy goes negative, you can't fire a weapon that doesn't require energy. // But energy should not go negative (but it does), so find out why it does! if (gameStates.app.bD1Mission && (nWeapon >= SUPER_WEAPON)) return 0; if (playerP->energy < 0) playerP->energy = 0; if (!bSecondary) { nWeaponIndex = primaryWeaponToWeaponInfo [nWeapon]; if (nWeapon == SUPER_LASER_INDEX) { if ((playerP->primaryWeaponFlags & (1 << LASER_INDEX)) && (bAll || (playerP->laserLevel > MAX_LASER_LEVEL))) returnValue |= HAS_WEAPON_FLAG; } else if (nWeapon == LASER_INDEX) { if ((playerP->primaryWeaponFlags & (1 << LASER_INDEX)) && (bAll || (playerP->laserLevel <= MAX_LASER_LEVEL))) returnValue |= HAS_WEAPON_FLAG; } else if (nWeapon == SPREADFIRE_INDEX) { if ((playerP->primaryWeaponFlags & (1 << nWeapon)) && (bAll || !(extraGameInfo [0].bSmartWeaponSwitch && (playerP->primaryWeaponFlags & (1 << HELIX_INDEX))))) returnValue |= HAS_WEAPON_FLAG; } else if (nWeapon == VULCAN_INDEX) { if ((playerP->primaryWeaponFlags & (1 << nWeapon)) && (bAll || !(extraGameInfo [0].bSmartWeaponSwitch && (playerP->primaryWeaponFlags & (1 << GAUSS_INDEX))))) returnValue |= HAS_WEAPON_FLAG; } else { if (playerP->primaryWeaponFlags & (1 << nWeapon)) returnValue |= HAS_WEAPON_FLAG; } // Special case: Gauss cannon uses vulcan ammo. if (nWeapon == GAUSS_INDEX) { if (WI_ammo_usage (nWeaponIndex) <= playerP->primaryAmmo [VULCAN_INDEX]) returnValue |= HAS_AMMO_FLAG; } else if (WI_ammo_usage (nWeaponIndex) <= playerP->primaryAmmo [nWeapon]) returnValue |= HAS_AMMO_FLAG; if (nWeapon == OMEGA_INDEX) { // Hack: Make sure tPlayer has energy to omega if (playerP->energy || gameData.omega.xCharge) returnValue |= HAS_ENERGY_FLAG; } else { /* if (nWeapon == SUPER_LASER_INDEX) { if (playerP->energy || gameData.omega.xCharge) returnValue |= HAS_ENERGY_FLAG; } */ if (WI_energy_usage (nWeaponIndex) <= playerP->energy) returnValue |= HAS_ENERGY_FLAG; } } else { nWeaponIndex = secondaryWeaponToWeaponInfo [nWeapon]; if (playerP->secondaryWeaponFlags & (1 << nWeapon)) returnValue |= HAS_WEAPON_FLAG; if (WI_ammo_usage (nWeaponIndex) <= playerP->secondaryAmmo [nWeapon]) returnValue |= HAS_AMMO_FLAG; if (WI_energy_usage(nWeaponIndex) <= playerP->energy) returnValue |= HAS_ENERGY_FLAG; } return returnValue; }
int LocalPlayerFireGun (void) { CPlayerData* playerP = gameData.multiplayer.players + gameData.multiplayer.nLocalPlayer; fix xEnergyUsed; int nAmmoUsed, nPrimaryAmmo; int nWeaponIndex; int rVal = 0; int nRoundsPerShot = 1; int bGatling = (gameData.weapons.nPrimary == GAUSS_INDEX) ? 2 : (gameData.weapons.nPrimary == VULCAN_INDEX) ? 1 : 0; fix addval; static int nSpreadfireToggle = 0; static int nHelixOrient = 0; if (gameStates.app.bPlayerIsDead) return 0; if (gameStates.app.bD2XLevel && (SEGMENTS [OBJECTS [playerP->nObject].info.nSegment].m_nType == SEGMENT_IS_NODAMAGE)) return 0; nWeaponIndex = primaryWeaponToWeaponInfo [gameData.weapons.nPrimary]; xEnergyUsed = WI_energy_usage (nWeaponIndex); if (gameData.weapons.nPrimary == OMEGA_INDEX) xEnergyUsed = 0; // Omega consumes energy when recharging, not when firing. if (gameStates.app.nDifficultyLevel < 2) xEnergyUsed = FixMul (xEnergyUsed, I2X (gameStates.app.nDifficultyLevel + 2) / 4); // MK, 01/26/96, Helix use 2x energy in multiplayer. bitmaps.tbl parm should have been reduced for single player. if (nWeaponIndex == HELIX_INDEX) if (IsMultiGame) xEnergyUsed *= 2; nAmmoUsed = WI_ammo_usage (nWeaponIndex); addval = 2 * gameData.time.xFrame; if (addval > I2X (1)) addval = I2X (1); if (!bGatling) nPrimaryAmmo = playerP->primaryAmmo [gameData.weapons.nPrimary]; else { if ((gameOpts->sound.bHires [0] == 2) && gameOpts->sound.bGatling && gameStates.app.bHaveExtraGameInfo [IsMultiGame] && EGI_FLAG (bGatlingSpeedUp, 1, 0, 0) && (gameData.weapons.firing [0].nDuration < GATLING_DELAY)) return 0; nPrimaryAmmo = playerP->primaryAmmo [VULCAN_INDEX]; } if ((playerP->energy < xEnergyUsed) || (nPrimaryAmmo < nAmmoUsed)) AutoSelectWeapon (0, 1); // Make sure the CPlayerData can fire from this weapon. if ((gameData.laser.xLastFiredTime + 2 * gameData.time.xFrame < gameData.time.xGame) || (gameData.time.xGame < gameData.laser.xLastFiredTime)) gameData.laser.xNextFireTime = gameData.time.xGame; gameData.laser.xLastFiredTime = gameData.time.xGame; while (gameData.laser.xNextFireTime <= gameData.time.xGame) { if ((playerP->energy >= xEnergyUsed) && (nPrimaryAmmo >= nAmmoUsed)) { int nLaserLevel, flags = 0; if (gameStates.app.cheats.bLaserRapidFire == 0xBADA55) gameData.laser.xNextFireTime += I2X (1) / 25; else gameData.laser.xNextFireTime += WI_fire_wait (nWeaponIndex); nLaserLevel = LOCALPLAYER.laserLevel; if (gameData.weapons.nPrimary == SPREADFIRE_INDEX) { if (nSpreadfireToggle) flags |= LASER_SPREADFIRE_TOGGLED; nSpreadfireToggle = !nSpreadfireToggle; } if (gameData.weapons.nPrimary == HELIX_INDEX) { nHelixOrient++; flags |= ((nHelixOrient & LASER_HELIX_MASK) << LASER_HELIX_SHIFT); } if (LOCALPLAYER.flags & PLAYER_FLAGS_QUAD_LASERS) flags |= LASER_QUAD; #if 1 int fired = FireWeapon ((short) LOCALPLAYER.nObject, (ubyte) gameData.weapons.nPrimary, nLaserLevel, flags, nRoundsPerShot); if (fired) { rVal += fired; if (bGatling) { if (nAmmoUsed > playerP->primaryAmmo [VULCAN_INDEX]) nAmmoUsed = playerP->primaryAmmo [VULCAN_INDEX]; playerP->primaryAmmo [VULCAN_INDEX] -= nAmmoUsed; gameData.multiplayer.weaponStates [gameData.multiplayer.nLocalPlayer].nAmmoUsed += nAmmoUsed; if (gameData.multiplayer.weaponStates [gameData.multiplayer.nLocalPlayer].nAmmoUsed >= VULCAN_AMMO_AMOUNT) { if (gameStates.app.bHaveExtraGameInfo [IsMultiGame]) MaybeDropNetPowerup (-1, POW_VULCAN_AMMO, FORCE_DROP); gameData.multiplayer.weaponStates [gameData.multiplayer.nLocalPlayer].nAmmoUsed -= VULCAN_AMMO_AMOUNT; } MultiSendAmmo (); } else { playerP->energy -= (xEnergyUsed * fired) / gameData.weapons.info [nWeaponIndex].fireCount; if (playerP->energy < 0) playerP->energy = 0; } } #else rVal += FireWeapon ((short) LOCALPLAYER.nObject, (ubyte) gameData.weapons.nPrimary, nLaserLevel, flags, nRoundsPerShot); playerP->energy -= (xEnergyUsed * rVal) / gameData.weapons.info [nWeaponIndex].fireCount; if (playerP->energy < 0) playerP->energy = 0; if (rVal && ((gameData.weapons.nPrimary == VULCAN_INDEX) || (gameData.weapons.nPrimary == GAUSS_INDEX))) { if (nAmmoUsed > playerP->primaryAmmo [VULCAN_INDEX]) playerP->primaryAmmo [VULCAN_INDEX] = 0; else playerP->primaryAmmo [VULCAN_INDEX] -= nAmmoUsed; } #endif AutoSelectWeapon (0, 1); // Make sure the CPlayerData can fire from this weapon. } else { AutoSelectWeapon (0, 1); // Make sure the CPlayerData can fire from this weapon. StopPrimaryFire (); break; // Couldn't fire weapon, so abort. } } gameData.laser.nGlobalFiringCount = 0; return rVal; }