?? bullets.cpp
字號:
/*Copyright (C) 2003 Parallel RealitiesThis program is free software; you can redistribute it and/ormodify it under the terms of the GNU General Public Licenseas published by the Free Software Foundation; either version 2of the License, or (at your option) any later version.This program is distributed in the hope that it will be useful,but WITHOUT ANY WARRANTY; without even the implied warranty ofMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.See the GNU General Public License for more details.You should have received a copy of the GNU General Public Licensealong with this program; if not, write to the Free SoftwareFoundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.*/#include "bullets.h"void addBullet(object *theWeapon, object *attacker, int y, int dy){ object *bullet; signed char imageIndex; int tempX, tempY, steps; bullet = new object; if (attacker == &player) currentGame.shots++; bullet->next = NULL; bullet->active = 1; bullet->x = attacker->x - ((attacker->image[0]->w / 2) * attacker->face); bullet->y = attacker->y + y; bullet->flags = theWeapon->flags; bullet->shield = 300; // bullets live for (approximately) 5 seconds // Timed explosions live between 1 and 3 seconds if (bullet->flags & WF_TIMEDEXPLOSION) bullet->shield = 60 + ((rand() % 3) * 60); if (attacker->face == 0) { bullet->dx = theWeapon->speed; if ((currentGame.area == 18) || (currentGame.area == 24)) bullet->dx += fabs(engine.ssx); } else { bullet->dx = (0 - theWeapon->speed); } if (bullet->flags & WF_VARIABLE_SPEED) { bullet->dx = Math::rrand(100, 200); bullet->dx /= 10; if (attacker->face == 1) bullet->dx = 0 - bullet->dx; } bullet->dy = dy; if (bullet->flags & WF_SCATTER) { bullet->dy = Math::rrand(-200, 200); if (bullet->dy != 0) bullet->dy /= 200; } if (attacker->flags & FL_WEAPCO) bullet->flags += WF_WEAPCO; else bullet->flags += WF_FRIEND; bullet->owner = attacker->owner; bullet->id = theWeapon->id; bullet->damage = theWeapon->damage; if (bullet->id == WT_CHARGER) { bullet->damage = attacker->ammo[1]; if (bullet->damage < 50) { bullet->damage = 1; bullet->id = WT_PLASMA; } } bullet->target = NULL; if (attacker->flags & FL_FRIEND) imageIndex = 0; else imageIndex = 1; // Use the enemy's images if applicable if (bullet->id != WT_ROCKET) bullet->image[0] = theWeapon->image[imageIndex]; else bullet->image[0] = theWeapon->image[attacker->face]; if (bullet->flags & WF_AIMED) { tempX = (int)fabs(attacker->target->x - attacker->x); tempY = (int)fabs(attacker->target->y - attacker->y); steps = max(tempX, tempY); if (steps == 0) steps = 12; if (!(bullet->flags & WF_TIMEDEXPLOSION)) steps /= 8; else steps /= 6 + (rand() % 6); tempX = (int)(attacker->target->x - attacker->x); tempY = (int)(attacker->target->y - attacker->y); bullet->dx = tempX / steps; bullet->dy = tempY / steps; } if (attacker->classDef == CD_ASTEROID) { bullet->dx = Math::rrand(-20, 20); bullet->dy = Math::rrand(-20, 20); bullet->image[0] = graphics.shape[4]; } engine.bulletTail->next = bullet; engine.bulletTail = bullet;}/*Fill in later...*/void fireBullet(object *attacker, int weaponType){ if (attacker->reload[weaponType] > 0) return; int y = (attacker->image[0]->h) / 5; // Remove some ammo from the player if ((attacker == &player) && (weaponType == 1) && (!engine.cheatAmmo)) player.ammo[1]--; object *theWeapon = &weapon[attacker->weaponType[weaponType]]; switch(theWeapon->id) { case WT_PLASMA: case WT_SPREAD: case WT_DIRECTIONAL: playSound(SFX_PLASMA); break; case WT_ROCKET: playSound(SFX_MISSILE); break; case WT_LASER: playSound(SFX_LASER); break; case WT_CHARGER: playSound(SFX_PLASMA3); break; } if (theWeapon->flags & WF_STRAIGHT) { switch (theWeapon->ammo[0]) { case 1: addBullet(theWeapon, attacker, y * 3, 0); break; case 2: addBullet(theWeapon, attacker, y * 2, 0); addBullet(theWeapon, attacker, y * 4, 0); break; case 3: addBullet(theWeapon, attacker, y * 2, 0); addBullet(theWeapon, attacker, y * 3, 0); addBullet(theWeapon, attacker, y * 4, 0); break; case 4: addBullet(theWeapon, attacker, y, 0); addBullet(theWeapon, attacker, y * 2, 0); addBullet(theWeapon, attacker, y * 4, 0); addBullet(theWeapon, attacker, y * 5, 0); break; case 5: for (int i = 1 ; i < 6; i++) addBullet(theWeapon, attacker, y * i, 0); break; } } else if (theWeapon->flags & WF_THIN_SPREAD) { addBullet(theWeapon, attacker, y * 2, -1); if (theWeapon->ammo[0] == 3) { addBullet(theWeapon, attacker, y * 3, 0); } else { addBullet(theWeapon, attacker, y * 2, 0); addBullet(theWeapon, attacker, y * 4, 0); } addBullet(theWeapon, attacker, y * 4, 1); } else if (theWeapon->flags & WF_WIDE_SPREAD) { addBullet(theWeapon, attacker, y * 1, -2); addBullet(theWeapon, attacker, y * 2, -1); addBullet(theWeapon, attacker, y * 3, 0); addBullet(theWeapon, attacker, y * 4, 1); addBullet(theWeapon, attacker, y * 5, 2); } // Reset the weapon reload time. Double it if it is not friendly or a boss or Kline attacker->reload[weaponType] = theWeapon->reload[0]; if ((attacker->flags & FL_WEAPCO) && (attacker != &enemy[WC_BOSS]) && (attacker != &enemy[WC_KLINE]) && (theWeapon->id != W_LASER)) attacker->reload[weaponType] *= 2; if ((engine.cheatAmmo) || (theWeapon->id == WT_LASER)) return; if ((attacker == &player) && (weaponType == 0)) { if (player.ammo[0] > 0) { player.ammo[0]--; if (player.ammo[0] == 0) { player.weaponType[0] = W_PLAYER_WEAPON; weapon[W_PLAYER_WEAPON2] = weapon[W_PLAYER_WEAPON]; // reset to weapon 1 defaults } } }}/*Used for homing missiles. When a missile is active and it is told to home inon an enemy, it will attempt to randomly grab one every frame if it does notalready have a target. If the target it is currently chasing is killed, it willbegin to look for a new one (done in doBullets()). The homing missile will makeone attempt per call (one call per frame) to find a suitable target. If the targetit picks is dead or outside the screen range, then it returns NULL. A suitabletarget will be returned as the object address.*/object *getRandomEnemy(object *bullet){ int i; if (bullet->owner->flags & FL_WEAPCO) { i = (rand() % 10); if (i < 1) return &player; } i = rand() % MAX_ALIENS; if ((enemy[i].shield < 1) || (!enemy[i].active)) return NULL; if ((bullet->owner->flags & FL_WEAPCO) && (enemy[i].flags & FL_WEAPCO)) return NULL; if ((bullet->owner->flags & FL_FRIEND) && (enemy[i].flags & FL_FRIEND)) return NULL; if (abs((int)bullet->x - (int)enemy[i].target->x) > 800) return NULL; if (abs((int)bullet->y - (int)enemy[i].target->y) > 200) return NULL; return &enemy[i];}/*Fill in later...*/void destroyAlien(object *bullet, object *theEnemy){ playSound(SFX_EXPLOSION); // Chain reaction destruction if needed if (theEnemy->flags & FL_DAMAGEOWNER) { theEnemy->owner->shield -= theEnemy->maxShield; if (theEnemy->owner->shield < 1) destroyAlien(bullet, theEnemy->owner); } if (theEnemy->flags & FL_FRIEND) { if (theEnemy->classDef == CD_PHOEBE) currentGame.wingMate1Ejects++; else if (theEnemy->classDef == CD_URSULA) currentGame.wingMate2Ejects++; // Phoebe cannot eject on the rescue mission if (currentGame.area != 7) { if ((theEnemy->classDef == CD_PHOEBE) || (theEnemy->classDef == CD_URSULA)) setInfoLine(">> Ally has ejected! <<\n", FONT_RED); else setInfoLine(">> Friendly craft has been destroy!! <<\n", FONT_RED); } } if (bullet->owner == &player) { // Once again, stop point leeching if (currentGame.area != MAX_MISSIONS - 1) currentGame.cash += theEnemy->score; currentGame.cashEarned += theEnemy->score; currentGame.totalKills++; } else if (bullet->owner->classDef == CD_PHOEBE) { currentGame.wingMate1Kills++; } else if (bullet->owner->classDef == CD_URSULA) { currentGame.wingMate2Kills++; } else { currentGame.totalOtherKills++; } if ((bullet->owner->classDef == CD_PHOEBE) || (bullet->owner->classDef == CD_URSULA)) { if ((rand() % 8) == 0) { getKillMessage(bullet->owner); } } updateMissionRequirements(M_DESTROY_TARGET_TYPE, theEnemy->classDef, 1); updateMissionRequirements(M_PROTECT_TARGET, theEnemy->classDef, 1); if (rand() % 100 <= theEnemy->collectChance) { unsigned char value; if ((rand() % 10) == 0) theEnemy->collectValue *= 2; while (theEnemy->collectValue > 0) { value = (10 + (rand() % theEnemy->collectValue)); if (value > theEnemy->collectValue) value =theEnemy->collectValue; addCollectable(theEnemy->x, theEnemy->y, theEnemy->collectType, value, 600); theEnemy->collectValue -= value; } } // Make it explode immediately if (theEnemy->classDef == CD_ASTEROID) { theEnemy->shield = -999; if ((currentGame.area == 10) && (theEnemy != &enemy[0]) && (currentMission.completed1[0] == 0) && (currentMission.targetValue1[1] == 1)) engine.targetArrowTimer = 120; } if ((theEnemy->classDef == CD_KRASS) && (bullet->owner == &player)) setRadioMessage(FACE_CHRIS, "My NAME is CHRIS!!!!!!!!", 1); if (theEnemy->classDef == CD_KLINE) { setRadioMessage(FACE_KLINE, "It was an honor... to have fought you...", 1); theEnemy->dx = theEnemy->dy = 0; theEnemy->maxShield = 1500; theEnemy->shield = -200; }}char checkPlayerShockDamage(float x, float y, int radius){ // Don't let the player be hurt by an explosion after they have completed // all the mission objectives. That would be *really* annoying! if ((engine.cheatShield) || (engine.missionCompleteTimer != 0)) return 0; float distX = fabs(x - player.x); float distY = fabs(y - player.y); if ((distX <= 50) && (distY <= 50)) {
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -