00001 00002 // 00003 // Das Tank - Copyright (C) 2006, 2007 Windsor Schmidt <windsor@windsorworld.net> 00004 // 00005 // This program is free software; you can redistribute it and/or modify it 00006 // under the terms of the GNU General Public License as published by the Free 00007 // Software Foundation; either version 2 of the License, or (at your option) 00008 // any later version. 00009 // 00010 // This program is distributed in the hope that it will be useful, but WITHOUT 00011 // ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 00012 // FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for 00013 // more details. 00014 // 00015 // You should have received a copy of the GNU General Public License along with 00016 // this program; if not, write to the Free Software Foundation, Inc., 59 Temple 00017 // Place, Suite 330, Boston, MA 02111-1307 USA 00018 // 00020 00021 00022 #ifndef STDAFX 00023 #include "stdafx.h" 00024 #endif 00025 00026 00035 void RemoveDeadObjects(CWorld * ThisWorld) 00036 { 00037 CObject * Current = ThisWorld->Objects; 00038 CObject * Other = ThisWorld->Objects; 00039 00040 // for every object 00041 while(Current != NULL) 00042 { 00043 if((Current->iHealth <= 0) && Current->bVisible) // if current object is 'dead' 00044 { 00045 // play the objects 'removal' sound effect 00046 PlaySound(Current->iRemovalSound); 00047 00048 // get ready to create an effect at the dead object's position 00049 Vector vTemp1, vTemp2; 00050 CEffect * NewEffect = NULL; 00051 00052 vTemp1.x = Current->Position.x; // dead object's position 00053 vTemp1.y = Current->Position.y; 00054 vTemp1.z = 0; 00055 00056 vTemp2.x = .04; // dead object's velocity 00057 vTemp2.y = 0; 00058 vTemp2.z = 0; 00059 00060 for(int i=0; i < Current->iRemovalEffects; i++) 00061 { 00062 // see which effect this object wants 00063 switch(Current->iRemovalEffect[i]) 00064 { 00065 case EFFECTID_PSYSTEM: 00066 NewEffect = new CEffect(EFFECTID_PSYSTEM); 00067 NewEffect->PSys = new PSystem(vTemp1, vTemp2 * 0.2, 2*PI, 1.05, 2, 100); 00068 NewEffect->PSys->SetColor(1.0, 0.6, 0.2); 00069 break; 00070 00071 case EFFECTID_SHOCKWAVE: 00072 NewEffect = new CEffect(EFFECTID_SHOCKWAVE); 00073 NewEffect->SWave = new Shockwave(vTemp1, 1); 00074 NewEffect->SWave->SetColor(0.8, 0.3, 0.6); 00075 break; 00076 00077 case EFFECTID_MINISHOCK: 00078 NewEffect = new CEffect(EFFECTID_MINISHOCK); 00079 NewEffect->MShock = new MiniShock(vTemp1, 1); 00080 NewEffect->MShock->SetColor(0.8, 0.3, 0.6); 00081 break; 00082 00083 case EFFECTID_TILESTORM: 00084 NewEffect = new CEffect(EFFECTID_TILESTORM); 00085 NewEffect->TStorm = new TileStorm(vTemp1, vTemp2, 2*PI, 1.005, 2, 12, TEXID_EZRAS_HEAD); 00086 break; 00087 00088 case EFFECTID_TILEANIM: 00089 NewEffect = new CEffect(EFFECTID_TILEANIM); 00090 NewEffect->TAnim = new TileAnim(vTemp1,0,Current->iLingerTime, 00091 Current->iRemovalAnim,200, 0, false); 00092 break; 00093 } 00094 00095 // add the new effect 00096 Current->ParentWorld->AddEffect(NewEffect); 00097 } 00098 00099 // special case when object explodes 00100 if(Current->iType == TYPEID_SUPER_BULLET) 00101 { 00102 DamageRadius(ThisWorld, Current->Position, 2, Current->iDamage); 00103 } 00104 00105 // special case when object explodes 00106 if(Current->iType == TYPEID_TNT_BLOCK) 00107 { 00108 DamageRadius(ThisWorld, Current->Position, 5, Current->iDamage); 00109 } 00110 00111 // special case when the dead object is a tank (player) 00112 if(Current->iType == TYPEID_TANK) 00113 { 00114 // play a nice sound effect 00115 PlaySound(SOUNDID_SCREAM); 00116 00117 // zero input before turning off player input =) 00118 for(int i=0; i<8; i++) 00119 { 00120 ThisWorld->Player[0]->iInput[i] = false; 00121 ThisWorld->Player[1]->iInput[i] = false; 00122 } 00123 00124 // stop the player 00125 Current->Velocity.x = 0; 00126 Current->Velocity.y = 0; 00127 Current->Velocity.z = 0; 00128 00129 ThisWorld->bTakeInput = false; 00130 ThisWorld->iStartingState = STARTINGSTATE_VICTORY; 00131 00132 Current->bVisible = false; 00133 00134 // clean up any bullets still on the playfield 00135 Current = ThisWorld->Objects; 00136 while(Current != NULL) 00137 { 00138 if(Current->Owner != NULL) 00139 { 00140 Current->Owner->iOwnCount --; 00141 Other = Current->Next; // place holder (next object in list) 00142 ThisWorld->RemoveObject(Current); // kill this object 00143 Current = Other; // and continue with place holder 00144 } 00145 else 00146 { 00147 Current = Current->Next; // object had no owner, continue to next object 00148 } 00149 } 00150 break; 00151 00152 } 00153 else 00154 { 00155 Other = Current->Next; // place holder (next object in list) 00156 ThisWorld->RemoveObject(Current); // kill this object 00157 Current = Other; // and continue with place holder 00158 } 00159 } 00160 else 00161 { 00162 Current = Current->Next; // object had health, continue to next object 00163 } 00164 } 00165 } 00166 00167 00175 void GameLogicDamage(CObject * Obj, CObject * ObjRef) 00176 { 00177 PlaySound(Obj->iDamageSound); 00178 Obj->iHealth -= ObjRef->iDamage; 00179 if(Obj->iHealth > MAX_HEALTH) { Obj->iHealth = MAX_HEALTH; } // clamp to a max value 00180 } 00181 00182 00188 void GameLogicDamageVal(CObject * Obj, int damageVal) 00189 { 00190 PlaySound(Obj->iDamageSound); 00191 Obj->iHealth -= damageVal; 00192 } 00193 00194 00200 void GameLogicEquip(CObject * Obj, CObject * ObjRef) 00201 { 00202 switch(ObjRef->iType) // which powerup was it? 00203 { 00204 case TYPEID_POWERUP_PS: 00205 PlaySound(SOUNDID_POWERUP); 00206 Obj->iWeapon = WEAPONID_PEA_SHOT; 00207 Obj->iAmmo = DEFAULT_PS_AMMO; 00208 break; 00209 00210 case TYPEID_POWERUP_BS: 00211 PlaySound(SOUNDID_POWERUP); 00212 Obj->iWeapon = WEAPONID_BOUNCY_SHOT; 00213 Obj->iAmmo = DEFAULT_BS_AMMO; 00214 break; 00215 00216 case TYPEID_POWERUP_SB: 00217 PlaySound(SOUNDID_POWERUP); 00218 Obj->iWeapon = WEAPONID_SUPER_BULLET; 00219 Obj->iAmmo = DEFAULT_SB_AMMO; 00220 break; 00221 00222 case TYPEID_POWERUP_LM: 00223 PlaySound(SOUNDID_POWERUP); 00224 Obj->iWeapon = WEAPONID_LAND_MINE; 00225 Obj->iAmmo = DEFAULT_LM_AMMO; 00226 break; 00227 00228 case TYPEID_POWERUP_HS: 00229 PlaySound(SOUNDID_POWERUP); 00230 Obj->iWeapon = WEAPONID_HEAT_SEEKER; 00231 Obj->iAmmo = DEFAULT_HS_AMMO; 00232 break; 00233 } 00234 ObjRef->iHealth = 0; // kill the powerup so it's removed from the game 00235 } 00236 00237 00245 void GameLogicFire(CObject * Obj) 00246 { 00247 int thisType = 0; // the object type of our new projectile 00248 Vector vTemp3; 00249 Vector vTemp1; // used to figure muzzle flash position 00250 Vector vTemp2; // used to figure muzzle flash trajectory 00251 00252 if(Obj->iAmmo == 0) // no ammo 00253 { 00254 PlaySound(SOUNDID_CLICK); 00255 return; 00256 } 00257 00258 CObject * NewObject; // pointer to hold the weapon object before we insert it in the list 00259 CEffect * NewEffect; // pointer to hold the weapon object before we insert it in the list 00260 00261 switch(Obj->iWeapon) // play a sound effect 00262 { 00263 case WEAPONID_NULL: 00264 break; 00265 00266 case WEAPONID_PEA_SHOT: 00267 PlaySound(SOUNDID_FIRE_PS); 00268 NewObject = new CObject(TYPEID_PEA_SHOT, Obj->ParentWorld); 00269 NewObject->Position.x = Obj->Position.x + cos(Obj->fSubAngle * (2*PI/360)) * 1.7; 00270 NewObject->Position.y = Obj->Position.y + sin(Obj->fSubAngle * (2*PI/360)) * 1.7; 00271 NewObject->fAngle = Obj->fAngle; 00272 NewObject->Velocity.x = cos(Obj->fSubAngle * (2*PI/360)) * .2; 00273 NewObject->Velocity.y = sin(Obj->fSubAngle * (2*PI/360)) * .2; 00274 NewObject->iTexture = TEXID_PEA_SHOT; 00275 NewObject->iDamageSound = SOUNDID_HIT; 00276 NewObject->iRemovalSound = SOUNDID_CRUNCH; 00277 NewObject->iRemovalEffects = 1; 00278 NewObject->iRemovalEffect[0] = EFFECTID_MINISHOCK; 00279 break; 00280 00281 case WEAPONID_BOUNCY_SHOT: 00282 PlaySound(SOUNDID_FIRE_BS); 00283 NewObject = new CObject(TYPEID_BOUNCY_SHOT, Obj->ParentWorld); 00284 NewObject->Position.x = Obj->Position.x + cos(Obj->fSubAngle * (2*PI/360)) * 1.7; 00285 NewObject->Position.y = Obj->Position.y + sin(Obj->fSubAngle * (2*PI/360)) * 1.7; 00286 NewObject->fAngle = Obj->fAngle; 00287 NewObject->Velocity.x = cos(Obj->fSubAngle * (2*PI/360)) * .4; 00288 NewObject->Velocity.y = sin(Obj->fSubAngle * (2*PI/360)) * .4; 00289 NewObject->iDamageSound = SOUNDID_HIT; 00290 NewObject->iRemovalSound = SOUNDID_CRUNCH; 00291 NewObject->iRemovalEffects = 1; 00292 NewObject->iRemovalEffect[0] = EFFECTID_MINISHOCK; 00293 break; 00294 00295 case WEAPONID_SUPER_BULLET: 00296 PlaySound(SOUNDID_FIRE_SB); 00297 NewObject = new CObject(TYPEID_SUPER_BULLET, Obj->ParentWorld); 00298 NewObject->Position.x = Obj->Position.x + cos(Obj->fSubAngle * (2*PI/360)) * 1.7; 00299 NewObject->Position.y = Obj->Position.y + sin(Obj->fSubAngle * (2*PI/360)) * 1.7; 00300 NewObject->fAngle = Obj->fAngle; 00301 NewObject->Velocity.x = cos(Obj->fSubAngle * (2*PI/360)) * .3; 00302 NewObject->Velocity.y = sin(Obj->fSubAngle * (2*PI/360)) * .3; 00303 NewObject->iDamageSound = SOUNDID_HIT; 00304 NewObject->iRemovalSound = SOUNDID_EXPLOSION; 00305 NewObject->iRemovalEffects = 1; 00306 NewObject->iRemovalEffect[0] = EFFECTID_PSYSTEM; 00307 00308 vTemp3.x = cos((DegreesToRadians(Obj->fSubAngle))); 00309 vTemp3.y = sin((DegreesToRadians(Obj->fSubAngle))); 00310 vTemp3.Normalize(); 00311 00312 Obj->Velocity -= vTemp3 * 0.5; 00313 00314 break; 00315 00316 case WEAPONID_LAND_MINE: 00317 PlaySound(SOUNDID_FIRE_LM); 00318 NewObject = new CObject(TYPEID_LAND_MINE, Obj->ParentWorld); 00319 NewObject->Position.x = Obj->Position.x - cos(Obj->fSubAngle * (2*PI/360)) * 1.7; 00320 NewObject->Position.y = Obj->Position.y - sin(Obj->fSubAngle * (2*PI/360)) * 1.7; 00321 NewObject->fAngle = Obj->fAngle; 00322 NewObject->iRemovalSound = SOUNDID_EXPLOSION; 00323 break; 00324 00325 case WEAPONID_HEAT_SEEKER: 00326 PlaySound(SOUNDID_FIRE_HS); 00327 NewObject = new CObject(TYPEID_HEAT_SEEKER, Obj->ParentWorld); 00328 NewObject->Position.x = Obj->Position.x + cos(Obj->fSubAngle * (2*PI/360)) * 1.7; 00329 NewObject->Position.y = Obj->Position.y + sin(Obj->fSubAngle * (2*PI/360)) * 1.7; 00330 NewObject->fAngle = Obj->fAngle; 00331 NewObject->Velocity.x = cos(Obj->fSubAngle * (2*PI/360)) * .06; 00332 NewObject->Velocity.y = sin(Obj->fSubAngle * (2*PI/360)) * .06; 00333 NewObject->iDamageSound = SOUNDID_HIT; 00334 NewObject->iRemovalSound = SOUNDID_EXPLOSION; 00335 break; 00336 } 00337 00338 // decrease the amount of ammo this object has 00339 Obj->iAmmo--; 00340 00341 if(Obj->iAmmo < -1) { Obj->iAmmo = -1; } // clamp neg value otherwise it looks goofy 00342 00343 // reset to pea shooter if object has run out of ammo 00344 if(Obj->iAmmo == 0) 00345 { 00346 Obj->iWeapon = WEAPONID_PEA_SHOT; 00347 Obj->iAmmo = -1; 00348 } 00349 00350 // set the owner of this bullet 00351 NewObject->Owner = Obj; 00352 // and increase the player's object ownership count by one 00353 Obj->iOwnCount++; 00354 // set object's tint color to match it's owners (red tank gets red bullets) 00355 NewObject->iTint = Obj->iTint; 00356 // add bullet to world 00357 Obj->ParentWorld->AddObject(NewObject); 00358 00359 vTemp1.x = NewObject->Position.x; 00360 vTemp1.y = NewObject->Position.y; 00361 vTemp1.z = 0; 00362 00363 vTemp2.x = 0.005; 00364 vTemp2.y = 0; 00365 vTemp2.z = 0; 00366 00367 vTemp2 = VRotate2D(DegreesToRadians(Obj->fAngle), vTemp2); 00368 00369 NewEffect = new CEffect(EFFECTID_PSYSTEM); 00370 NewEffect->PSys = new PSystem(vTemp1, vTemp2, 0.01, 1.01, 1, 50); 00371 NewEffect->PSys->SetColor(1,.6,.2); 00372 00373 Obj->ParentWorld->AddEffect(NewEffect); 00374 }
Copyright Windsor Schmidt 2006 - All rights reserved.