Main Page | Alphabetical List | Compound List | File List | Compound Members | File Members

Weapons.c

Go to the documentation of this file.
00001 /****************************************************************************************/
00002 /*  Weapons.c                                                                           */
00003 /*                                                                                      */
00004 /*  Author: John Pollard                                                                */
00005 /*  Description:                                                                        */
00006 /*                                                                                      */
00007 /*  Copyright (c) 1997, 1999, Eclipse Entertainment; All rights reserved.               */
00008 /*                                                                                      */
00009 /*  See the accompanying file LICENSE.TXT for terms on the use of this library.         */
00010 /*  This library is distributed in the hope that it will be useful but WITHOUT          */
00011 /*  ANY WARRANTY OF ANY KIND and without any implied warranty of MERCHANTABILITY        */
00012 /*  or FITNESS FOR ANY PURPOSE.  Refer to LICENSE.TXT for more details.                 */
00013 /*                                                                                      */
00014 /****************************************************************************************/
00015 #include <Windows.h>
00016 #include <Assert.h>
00017 
00018 #include "GMain.h"
00019 #include "Quatern.h"
00020 
00021 geBoolean               Client_Control(GenVSI *VSI, void *PlayerData, float Time);
00022 void                    *GetDMSpawn(GenVSI *VSI);
00023 void                    SetupPlayerXForm(GenVSI *VSI, void *PlayerData, float Time);
00024 
00025 #define BLASTER_RADIUS                  150.0f
00026 #define BLASTER_POWER                   250.0f
00027 #define BLASTER_POWER_RADIUS    200.0f
00028 
00029 #define GRENADE_RADIUS                  350.0f
00030 #define GRENADE_POWER                   400.0f  
00031 #define GRENADE_POWER_RADIUS    400.0f  
00032 
00033 #define ROCKET_RADIUS                   320.0f
00034 #define ROCKET_POWER                    500.0f
00035 #define ROCKET_POWER_RADIUS             450.0f
00036 
00037 //=====================================================================================
00038 //      SwitchToNextBestWeapon
00039 //=====================================================================================
00040 void SwitchToNextBestWeapon(GenVSI *VSI, void *PlayerData)
00041 {
00042         int32                   i;
00043         int32                   BestWeapon;
00044         GPlayer                 *Player;
00045 
00046         Player = (GPlayer*)PlayerData;
00047 
00048         //assert(Player->ClientHandle != CLIENT_NULL_HANDLE);
00049 
00050         BestWeapon = -1;
00051         
00052         for (i=0; i<5; i++)
00053         {
00054                 Player->CurrentWeapon++;
00055                 Player->CurrentWeapon %= 4;
00056                 
00057                 if ((!Player->InventoryHas[Player->CurrentWeapon] || Player->Inventory[Player->CurrentWeapon] <= 0) && Player->CurrentWeapon != 0)
00058                         continue;
00059 
00060                 if (Player->CurrentWeapon > BestWeapon)
00061                         BestWeapon = Player->CurrentWeapon;
00062         }
00063 
00064         assert(BestWeapon >= 0 && BestWeapon < 5);
00065 
00066         if (BestWeapon == -1)           // Should'nt happen, but... Assert will get it if it does...
00067                 BestWeapon = 0;
00068         
00069         if (Player->ClientHandle != CLIENT_NULL_HANDLE)
00070                 GenVSI_SetClientWeapon(VSI, Player->ClientHandle, (uint16)BestWeapon);
00071 }
00072 
00073 //=====================================================================================
00074 //      ValidateWeapon
00075 //=====================================================================================
00076 void ValidateWeapon(GenVSI *VSI, void *PlayerData)
00077 {
00078         int32                   i;
00079         GPlayer                 *Player;
00080 
00081         assert(PlayerData);
00082         
00083         Player = (GPlayer*)PlayerData;
00084 
00085         //assert(Player->ClientHandle != CLIENT_NULL_HANDLE);
00086 
00087         for (i=0; i<5; i++)
00088         {
00089                 if (!Player->InventoryHas[Player->CurrentWeapon] && Player->CurrentWeapon != 0)
00090                 {
00091                         Player->CurrentWeapon++;
00092                         Player->CurrentWeapon %= 4;
00093                         continue;
00094                 }
00095                 
00096                 assert(Player->CurrentWeapon >= 0 && Player->CurrentWeapon <= 3);
00097 
00098                 if (Player->ClientHandle != CLIENT_NULL_HANDLE)
00099                         GenVSI_SetClientWeapon(VSI, Player->ClientHandle, Player->CurrentWeapon);
00100                 return;
00101         }
00102         
00103         // Should'nt get here!!!!!  There is allways the default weapon...
00104         assert(!"No best weapon!!!");
00105 
00106         if (Player->ClientHandle != CLIENT_NULL_HANDLE)
00107                 GenVSI_SetClientWeapon(VSI, Player->ClientHandle, 0);
00108 }
00109 
00110 //=====================================================================================
00111 //      Player_Dying
00112 //=====================================================================================
00113 static geBoolean Player_Dying(GenVSI *VSI, void *PlayerData, float Time)
00114 {
00115         GPlayer                 *Player;
00116         GenVSI_CMove    *Move;
00117 
00118         Player = (GPlayer*)PlayerData;
00119 
00120         assert(Player->ClientHandle != CLIENT_NULL_HANDLE);
00121 
00122         Player->MotionIndex = ACTOR_MOTION_PLAYER_DIE;
00123         AnimatePlayer(VSI, Player, Player->MotionIndex, Time, GE_FALSE);
00124 
00125         Move = GenVSI_GetClientMove(VSI, Player->ClientHandle);
00126 
00127         Player->Roll -= 2.0f*Time;
00128 
00129         if (Player->Roll < -(3.14159f/2.0f))
00130         {
00131                 Player->Roll = -(3.14159f/2.0f);
00132 
00133                 if (Move->ButtonBits & HOST_BUTTON_FIRE)
00134                 {
00135                         GPlayer *DMStart;
00136                         
00137                         DMStart = (GPlayer*)GetDMSpawn(VSI);
00138 
00139                         Player->Roll = 0.0f;            // Make him stand right side up again
00140                         Player->Control = Client_Control;
00141                         //Player->Dead = GE_FALSE;
00142                         Player->State = PSTATE_Normal;          // Back to normal now...
00143                         Player->ViewIndex = 0;
00144                         Player->MotionIndex = ACTOR_MOTION_PLAYER_RUN;
00145                         Player->FrameTime = 0.0f;
00146 
00147                         Player->ViewFlags &= ~VIEW_TYPE_FORCE_XFORM;
00148 
00149                         Player->XForm = DMStart->XForm;
00150                         GenVSI_SpawnFx(VSI, FX_EXPLODE2, &Player->XForm.Translation, SOUND_INDEX_PLAYER_SPAWN);
00151 
00152                         return GE_TRUE;
00153                 }
00154         }
00155 
00156         SetupPlayerXForm(VSI, Player, Time);
00157 
00158         PlayerPhysics(VSI, Player, PLAYER_GROUND_FRICTION, PLAYER_AIR_FRICTION, PLAYER_LIQUID_FRICTION, PLAYER_GRAVITY, 1.0f, GE_FALSE, Time);
00159 
00160         return GE_TRUE;
00161 }
00162 
00163 #define NUM_DIE_MSGS            4
00164 static int32 CurrentDieMsg = 0;
00165 
00166 static char DieMsgs[NUM_DIE_MSGS][128] = 
00167 {
00168         " can't handle life anymore",
00169         " is a loser",
00170         " puts a gun to his head",
00171         " had a nervous breakdown",
00172 };
00173 
00174 #define NUM_KILL_MSGS           5
00175 static int32 CurrentKillMsg = 0;
00176 
00177 static char KillMsgs[NUM_KILL_MSGS<<1][128] = 
00178 {
00179         " hit ", " with an ugly stick",
00180         " lays the smack down on ", "...",
00181         " cracked ", "'s head open",
00182         " hit ", " with an ugly forest",
00183         " put a load in ", "'s head",
00184 };
00185 
00186 //=====================================================================================
00187 //      KillPlayer
00188 //=====================================================================================
00189 geBoolean KillPlayer(GenVSI *VSI, void *PlayerData, void *TargetData, float Time)
00190 {
00191         GPlayer                         *Owner;
00192         GPlayer                         *Player;
00193         GPlayer                         *Target;
00194     void Bot_Dying(void);
00195     void Bot_ActorDying(void);
00196 
00197         Player = (GPlayer*)PlayerData;
00198         Target = (GPlayer*)TargetData;
00199 
00200         Target->Health = 100;
00201 
00202         if (Target->DammageFlags == 0)
00203                 return GE_TRUE;
00204 
00205         // Actors don't have a client handle
00206         if (Target->ClientHandle != CLIENT_NULL_HANDLE)
00207                 GenVSI_SetClientHealth(VSI, Target->ClientHandle, Target->Health);
00208 
00209         if (Player && Player->Owner->ClientHandle != CLIENT_NULL_HANDLE)
00210         {
00211                 Owner = Player->Owner;          
00212         
00213                 if (!Owner)
00214                 {
00215                         GenVSI_ConsolePrintf(VSI, "KillPlayer:  Stray weapon!\n");
00216                         return GE_TRUE;
00217                 }
00218 
00219                 if (Owner == Target)    // We just killed ourself!!
00220                 {
00221                         GenVSI_ConsoleHeaderPrintf(VSI, Owner->ClientHandle, GE_TRUE, "%s%s", Owner->ClassName, DieMsgs[CurrentDieMsg]);
00222                         Owner->Score--;
00223 
00224                         CurrentDieMsg++;
00225                         CurrentDieMsg%=NUM_DIE_MSGS;
00226                 }
00227                 else
00228                 {
00229                         GenVSI_ConsoleHeaderPrintf(VSI, Owner->ClientHandle, GE_TRUE, "%s%s%s%s", Owner->ClassName, KillMsgs[CurrentKillMsg<<1], Target->ClassName, KillMsgs[(CurrentKillMsg<<1)+1]);
00230                         Owner->Score++;
00231 
00232                         CurrentKillMsg++;
00233                         CurrentKillMsg%=NUM_KILL_MSGS;
00234                 }
00235 
00236                 GenVSI_SetClientScore(VSI, Owner->ClientHandle, Owner->Score);
00237         }
00238 
00239         //Target->Dead = GE_TRUE;
00240         Target->State = PSTATE_Dead;
00241         //??bot Hack - talk to john
00242         if (strcmp(Target->ClassName, "Bot_Actor") == 0)
00243                 Target->Control = (void*)Bot_ActorDying;
00244         else
00245         if (GenVSI_IsClientBot(VSI, Target->ClientHandle))
00246                 Target->Control = (void*)Bot_Dying;
00247         else
00248                 Target->Control = Player_Dying;
00249         Target->Velocity.Y += 700.0f;
00250         Target->MotionIndex = ACTOR_MOTION_PLAYER_DIE;
00251         Target->FrameTime = 0.0f;
00252 
00253         // Play dying sound...
00254         GenVSI_PlaySound(VSI, SOUND_INDEX_DIE, &Target->XForm.Translation);
00255 
00256         Target->ViewFlags |= VIEW_TYPE_FORCE_XFORM;
00257 
00258         // Update the targets inventory (won't have nothin anymore...)
00259         {
00260                 int32           i;
00261 
00262                 // TODO:  Create a new player, and copy over inventory for a backpack...
00263                 for (i=1; i<MAX_PLAYER_ITEMS; i++)
00264                 {
00265                         Target->Inventory[i] = 0;
00266                         Target->InventoryHas[i] = GE_FALSE;
00267                         // Actors don't have a client handle
00268                         if (Target->ClientHandle != CLIENT_NULL_HANDLE)
00269                                 UpdateClientInventory(VSI, Target, i);
00270                 }
00271 
00272                 Target->CurrentWeapon = 0;
00273                 // Actors don't have a client handle
00274                 if (Target->ClientHandle != CLIENT_NULL_HANDLE)
00275                         GenVSI_SetClientWeapon(VSI, Target->ClientHandle, Target->CurrentWeapon);
00276         }
00277 
00278         return GE_TRUE;
00279 }
00280 
00281 //=====================================================================================
00282 //      DammagePlayer
00283 //=====================================================================================
00284 geBoolean DammagePlayer(GenVSI *VSI, void *PlayerData, void *TargetData, int32 Amount, float Power, float Time)
00285 {
00286         geVec3d         Vect, Pos;
00287         int32           DammageSound;
00288         GPlayer         *Player, *Target;
00289         float           Amountf, ArmorRatio;
00290         extern geBoolean GodMode;
00291 
00292         Player = (GPlayer*)PlayerData;
00293         Target = (GPlayer*)TargetData;
00294 
00295         if (VSI->Mode != MODE_Server)
00296                 return GE_TRUE;
00297 
00298         //if (Target->Dead)
00299         //      return GE_TRUE;
00300         if (Target->State == PSTATE_Dead)                               // Ignore dead players...
00301                 return GE_TRUE;
00302         if (Target->State == PSTATE_DeadOnGround)               // Ignore dead players...
00303                 return GE_TRUE;
00304 
00305         if (Target->DammageFlags == 0)
00306                 return GE_TRUE;
00307         //if (Target->ClientHandle == CLIENT_NULL_HANDLE)                       // For now, only hurt client players for deathmatch...
00308         //      return GE_TRUE;
00309 
00310         Amountf = (float)Amount;
00311 
00312         // Dammage -= ((Armor/MAX_ARMOR)*0.5)*Dammaga
00313         ArmorRatio = (float)Target->Inventory[ITEM_ARMOR] / (float)MAX_ARMOR;
00314         Amountf -= (ArmorRatio * MAX_ARMOR_PROTECTION) * Amountf;
00315 
00316         if (Amountf < 0.0f)
00317                 Amountf = 0.0f;
00318 
00319         Target->Inventory[ITEM_ARMOR] -= Amount;
00320 
00321         if (Target->Inventory[ITEM_ARMOR] < 0)
00322                 Target->Inventory[ITEM_ARMOR] = 0;
00323 
00324         // Actors don't have a client handle
00325         if (Target->ClientHandle != CLIENT_NULL_HANDLE)         
00326                 UpdateClientInventory(VSI, Target, ITEM_ARMOR);
00327 
00328         // debug godmode
00329         if (!GodMode || GenVSI_IsClientBot(VSI, Target->ClientHandle))
00330                 Target->Health -= (int32)Amountf;
00331         else
00332                 return GE_FALSE;
00333 
00334         if (Player)
00335         {
00336                 if (Player->Owner == Target)    // Don't hurt ourselves as much
00337                         Amountf *= 0.5f;
00338 
00339                 // Knock the target opposite of the player hitting the target
00340                 Pos = Target->XForm.Translation;
00341                 Pos.Y += 100.0f;
00342                 geVec3d_Subtract(&Pos, &Player->XForm.Translation, &Vect);
00343                 geVec3d_Normalize(&Vect);
00344         
00345                 geVec3d_AddScaled(&Target->Velocity, &Vect, Power, &Target->Velocity);
00346         }
00347 
00348         if (Target->Health <= 0)
00349         {
00350                 if (!KillPlayer(VSI, Player, Target, Time))
00351                         return GE_FALSE;
00352         }
00353 
00354         // Actors don't have a client handle
00355         if (Target->ClientHandle != CLIENT_NULL_HANDLE)         
00356                 GenVSI_SetClientHealth(VSI, Target->ClientHandle, Target->Health);
00357 
00358         Target->MotionIndex = ACTOR_MOTION_PLAYER_HIT;
00359         Target->FrameTime = 0.0f;
00360 
00361         if      ((rand() % 100) > 90)
00362                 DammageSound = (rand()%2) + SOUND_INDEX_HURT3;
00363         else
00364                 DammageSound = (rand()%2) + SOUND_INDEX_HURT1;
00365 
00366         GenVSI_PlaySound(VSI, (uint16)DammageSound, &Target->XForm.Translation);
00367 
00368         return GE_TRUE;
00369 }
00370 
00371 //=====================================================================================
00372 //      RadiusDammage
00373 //=====================================================================================
00374 static geBoolean RadiusDammage(GenVSI *VSI, void *PlayerData, int32 Amount, float Power, float Radius, float Time)
00375 {
00376         GPlayer                 *Hit;
00377         geVec3d                 Pos, Pos2;
00378         GPlayer                 *Player;
00379         geWorld                 *World;
00380 
00381         Player = (GPlayer*)PlayerData;
00382 
00383         if (VSI->Mode != MODE_Server)
00384                 return GE_TRUE;
00385         
00386         Pos = Player->XForm.Translation;
00387 
00388         // Sweep through all the players in radius and do radius dammage...
00389         Hit = NULL;
00390 
00391         World = GenVSI_GetWorld(VSI);
00392 
00393         while (1)
00394         {
00395                 GE_Collision Collision;
00396 
00397                 Hit = GenVSI_GetNextPlayerInRadius(VSI, Player, Hit, NULL, Radius);
00398 
00399                 if (!Hit)
00400                         break;
00401 
00402                 //Console_Printf(Server->Host->Console, "Found player in radius: %s\n", Hit->ClassName);
00403                 //if (Hit->ClientHandle == CLIENT_NULL_HANDLE)
00404                 //      continue;
00405                 if (!(Hit->DammageFlags & DAMMAGE_TYPE_RADIUS))
00406                         continue;
00407 
00408                 Pos2 = Hit->XForm.Translation;
00409 
00410                 if (World)
00411                         if (geWorld_Collision(World, NULL, NULL, &Pos, &Pos2, GE_CONTENTS_CANNOT_OCCUPY, GE_COLLIDE_MODELS, 0, NULL, NULL, &Collision))
00412                                 continue;
00413 
00414                 if (Hit == Player->Owner)               // To allow rocket jumps
00415                 {
00416                         Power *= 2.65f;
00417                 }
00418 
00419                 if (!DammagePlayer(VSI, Player, Hit, Amount, Power, Time))
00420                         return GE_FALSE;
00421         }
00422 
00423         return GE_TRUE;
00424 }
00425 
00426 //=====================================================================================
00427 //=====================================================================================
00428 geBoolean Grenade_Control(GenVSI *VSI, void *PlayerData, float Time)
00429 {
00430         geVec3d                 NewPos;
00431         geVec3d                 Mins;
00432         geVec3d                 Maxs;
00433         GE_Contents             Contents;
00434         GPlayer                 *Player;
00435         geWorld                 *World;
00436         GE_Collision    Col;
00437         CData                   Data;
00438         void                    *ThisSelfCollisionCB;
00439 
00440 
00441         World = GenVSI_GetWorld(VSI);
00442         
00443         Player = (GPlayer*)PlayerData;
00444 
00445         Mins = Player->Mins;
00446         Maxs = Player->Maxs;
00447 
00448         if (Player->Time > 1.0f)                // Give the user 1 sec till it starts to collide with himself...
00449                 ThisSelfCollisionCB = SelfCollisionCB2;
00450         else
00451                 ThisSelfCollisionCB = SelfCollisionCB;
00452 
00453         Player->Time += Time;
00454         
00455         Data.VSI = VSI;
00456         Data.Player = Player;
00457 
00458         geVec3d_AddScaled(&Player->XForm.Translation, &Player->Velocity, Time, &NewPos);
00459 
00460         // Make bounce sound
00461         if (geWorld_Collision(World, &Mins, &Maxs, &Player->XForm.Translation, &NewPos, GE_CONTENTS_CANNOT_OCCUPY, GE_COLLIDE_MODELS, 0, ThisSelfCollisionCB, &Data, &Col))
00462         {
00463                 geVec3d         Vect;
00464 
00465                 geVec3d_Subtract(&Col.Impact, &NewPos, &Vect);
00466 
00467                 if (geVec3d_Length(&Vect) > 5.0f)
00468                         GenVSI_PlaySound(VSI, 3, &Player->XForm.Translation);
00469         }
00470 
00471         if (geWorld_Collision(World, &Mins, &Maxs, &Player->XForm.Translation, &NewPos, GE_CONTENTS_CANNOT_OCCUPY, GE_COLLIDE_ACTORS, 0xffffffff, ThisSelfCollisionCB, &Data, &Col))
00472         {
00473                 if (Col.Actor)
00474                 {
00475                         GPlayer         *PlayerHit;
00476 
00477                         PlayerHit = (GPlayer*)GenVSI_ActorToPlayer(VSI, Col.Actor);
00478 
00479                         if (PlayerHit)
00480                         {
00481                                 // Do radius dammage
00482                                 DammagePlayer(VSI, Player, PlayerHit, 25, GRENADE_POWER, Time);
00483                                 RadiusDammage(VSI, Player, 20, GRENADE_POWER_RADIUS, GRENADE_RADIUS, Time);
00484 
00485                                 Player->XForm.Translation.Y += 40.0f;
00486                                 GenVSI_SpawnFx(VSI, FX_EXPLODE1, &Player->XForm.Translation, 1);
00487 
00488                         }
00489 
00490                         // Remove the player...
00491                         GenVSI_DestroyPlayer(VSI, PlayerData);
00492                         return GE_TRUE;
00493                 }
00494         }
00495         
00496         if (geWorld_GetContents(World, &Player->XForm.Translation, &Player->Mins, &Player->Maxs, GE_COLLIDE_ACTORS, 0xffffffff, ThisSelfCollisionCB, &Data, &Contents))
00497         {
00498                 if (Contents.Actor)
00499                 {
00500                         GPlayer         *PlayerHit;
00501 
00502                         PlayerHit = (GPlayer*)GenVSI_ActorToPlayer(VSI, Contents.Actor);
00503 
00504                         if (PlayerHit)
00505                         {
00506                                 // Do radius dammage
00507                                 DammagePlayer(VSI, Player, PlayerHit, 25, GRENADE_POWER, Time);
00508                                 RadiusDammage(VSI, Player, 20, GRENADE_POWER_RADIUS, GRENADE_RADIUS, Time);
00509                                 
00510                                 Player->XForm.Translation.Y += 40.0f;
00511                                 GenVSI_SpawnFx(VSI,  FX_EXPLODE1, &Player->XForm.Translation, 1);
00512                         
00513                                 // Remove the player...
00514                                 GenVSI_DestroyPlayer(VSI, PlayerData);
00515                                 return GE_TRUE;
00516                         }
00517                 }
00518         }
00519         
00520         // Run the physics on the Grenade
00521         PlayerPhysics(VSI, Player, 0.75f, 0.65f, 2.1f, 1000.0f, 1.8f, GE_TRUE, Time);
00522 
00523         Player->VPos = Player->XForm.Translation;
00524         
00525         if (Player->Time >= 3.5f)               // Grenade last for 3 secs
00526         {
00527                 // Do radius dammage
00528                 RadiusDammage(VSI, Player, 35, GRENADE_POWER_RADIUS, GRENADE_RADIUS, Time);
00529 
00530                 Player->XForm.Translation.Y += 40.0f;
00531                 GenVSI_SpawnFx(VSI, FX_EXPLODE1, &Player->XForm.Translation, 1);
00532                 // Remove the player...
00533                 GenVSI_DestroyPlayer(VSI, Player);
00534 
00535         }
00536 
00537         return GE_TRUE;
00538 }
00539 
00540 //=====================================================================================
00541 //      FireGrenade
00542 //=====================================================================================
00543 void FireGrenade(GenVSI *VSI, void *PlayerData, float Time)
00544 {
00545         GPlayer                 *Weapon;
00546         geVec3d                 In;
00547         GPlayer                 *Player;
00548 
00549         Player = (GPlayer*)PlayerData;
00550         
00551         if (!Player->Inventory[ITEM_GRENADES] || !Player->InventoryHas[ITEM_GRENADES])
00552         {
00553                 SwitchToNextBestWeapon(VSI, Player);
00554                 return;
00555         }
00556         
00557         Weapon = (GPlayer*)GenVSI_SpawnPlayer(VSI, "Weapon_Grenade");
00558 
00559         if (!Weapon)
00560         {
00561                 GenVSI_ConsolePrintf(VSI, "FireGrenade:  Failed to spawn player.\n");
00562                 return;
00563         }
00564 
00565         Player->Inventory[ITEM_GRENADES]--;
00566         
00567         if (Player->Inventory[ITEM_GRENADES] < 0)
00568         {
00569                 SwitchToNextBestWeapon(VSI, Player);
00570                 Player->Inventory[ITEM_GRENADES] = 0;
00571         }
00572         
00573         //UpdateClientInventory(VSI, Player, ITEM_GRENADES);
00574 
00575         // Setup the callbacks for this weapon
00576         Weapon->Control = Grenade_Control;
00577         Weapon->Blocked = NULL;
00578         Weapon->Trigger = NULL;
00579         Weapon->Time = 0.0f;
00580         Weapon->Owner = Player;
00581         Weapon->PingTime = Player->PingTime;
00582 
00583         Weapon->ControlIndex = 7;
00584 
00585         Weapon->ViewFlags = VIEW_TYPE_ACTOR | VIEW_TYPE_LIGHT | VIEW_TYPE_COLLIDEMODEL;
00586         Weapon->ViewIndex = ACTOR_INDEX_GRENADE_AMMO;
00587         Weapon->FxFlags = FX_SMOKE_TRAIL;
00588         Weapon->Scale = 1.0f;
00589         Weapon->MotionIndex = MOTION_INDEX_NONE;
00590         
00591         geVec3d_Set(&Weapon->Mins, -10.0f, -10.0f, -10.0f);
00592         geVec3d_Set(&Weapon->Maxs,  10.0f,  10.0f,  10.0f);
00593 
00594         Weapon->XForm = Player->XForm;
00595 
00596         geVec3d_Add(&Weapon->XForm.Translation, &Player->GunOffset, &Weapon->XForm.Translation);
00597 
00598         Weapon->XForm.Translation.Y -= 30.0f;
00599 
00600         geXForm3d_GetIn(&Weapon->XForm, &In);
00601 
00602         In.Y += 0.2f;
00603         geVec3d_Scale(&In, 1100.0f, &Weapon->Velocity);
00604 
00605         GenVSI_PlaySound(VSI, SOUND_INDEX_GRENADE, &Player->XForm.Translation);
00606 
00607         Player->NextWeaponTime = GenVSI_GetTime(VSI) + 0.5f;
00608         //Player->NextThinkTime = Server->Host->Time+0.5f;              // 0.5 sec between firing...
00609 
00610         Player->VPos = Player->XForm.Translation;
00611 }
00612 
00613 //=====================================================================================
00614 //      Rocket_Control
00615 //=====================================================================================
00616 geBoolean Rocket_Control(GenVSI *VSI, void *PlayerData, float Time)
00617 {
00618         geVec3d                 In, Front, Back;
00619         geXForm3d               DestXForm;
00620         GE_Collision    Collide;
00621         float                   Speed;
00622         GPlayer                 *Player;
00623         geWorld                 *World;
00624         CData                   Data;
00625 
00626         Player = (GPlayer*)PlayerData;
00627 
00628         Player->Time += Time;
00629         
00630         Speed = Player->Time*3600.0f;
00631 
00632         if (Speed > 4000.0f)
00633                 Speed = 4000.0f;
00634 
00635         geXForm3d_Copy(&Player->XForm, &DestXForm);
00636 
00637         geXForm3d_GetIn(&Player->XForm, &In);
00638         geVec3d_Scale(&In, -Speed*Time, &In);           // - speed since xform was rotated 180!!!
00639         geXForm3d_Translate(&DestXForm, In.X, In.Y, In.Z);
00640 
00641         Front = Player->XForm.Translation;
00642         Back = DestXForm.Translation;
00643 
00644         geXForm3d_Copy(&DestXForm, &Player->XForm);
00645 
00646         World = GenVSI_GetWorld(VSI);
00647 
00648         assert(World);
00649 
00650         Data.VSI = VSI;
00651         Data.Player = Player;//->Owner;
00652 
00653         if (geWorld_Collision(  World, NULL, NULL, &Front, &Back, 
00654                                                         GE_CONTENTS_CANNOT_OCCUPY, GE_COLLIDE_MODELS|GE_COLLIDE_ACTORS, 
00655                                                         0xffffffff, SelfCollisionCB, &Data, &Collide))
00656         {
00657                 Player->XForm.Translation = Collide.Impact;
00658                 geVec3d_AddScaled(&Player->XForm.Translation, &Collide.Plane.Normal, 40.0f, &Player->XForm.Translation);
00659 
00660                 GenVSI_SpawnFx(VSI, FX_EXPLODE1, &Player->XForm.Translation, 1);
00661 
00662                 if (Collide.Model)
00663                 {
00664                         GPlayer         *Target;
00665 
00666                         Target = (GPlayer*)geWorld_ModelGetUserData(Collide.Model);
00667                         if (Target && Target->Trigger && (Target->ViewFlags & VIEW_TYPE_PHYSOB))
00668                         {
00669                                 geXForm3d_GetIn(&Player->XForm, &In);
00670                                 Player->Velocity = In;
00671                                 geVec3d_Scale(&In, -1000.f, &Player->Velocity);
00672                                 Target->Trigger(VSI, Target, Player, (void*)&Collide);
00673                         }
00674                 }
00675 
00676                 if (Collide.Actor)
00677                 {
00678                         GPlayer         *PlayerHit;
00679 
00680                         PlayerHit = (GPlayer*)GenVSI_ActorToPlayer(VSI, Collide.Actor);
00681 
00682                         // Only radius dammage will hurt the player that shot the rocket...
00683                         if (PlayerHit && PlayerHit != Player->Owner)    
00684                                 DammagePlayer(VSI, Player, PlayerHit, 35, ROCKET_POWER, Time);
00685                         
00686                         // Do radius dammage
00687                         RadiusDammage(VSI, Player, 30, ROCKET_POWER_RADIUS, ROCKET_RADIUS, Time);
00688 
00689                         GenVSI_DestroyPlayer(VSI, PlayerData);
00690                         return GE_TRUE;
00691                 }
00692 
00693                 // Do radius dammage
00694                 RadiusDammage(VSI, Player, 40, ROCKET_POWER_RADIUS, ROCKET_RADIUS, Time);
00695                 GenVSI_DestroyPlayer(VSI, PlayerData);
00696 
00697                 return GE_TRUE;
00698         }
00699         
00700         Player->VPos = Player->XForm.Translation;
00701 
00702         if (Player->Time >= 20.0f)                              // Kill it after 20 seconds
00703                 GenVSI_DestroyPlayer(VSI, PlayerData);
00704 
00705         return GE_TRUE;
00706 }
00707 
00708 
00709 //=====================================================================================
00710 //      FireRocket
00711 //=====================================================================================
00712 void FireRocket(GenVSI *VSI, void *PlayerData, float Time)
00713 {
00714         GPlayer                 *Weapon;
00715         geVec3d                 Up, In, Rt, Front, Back, Impact;
00716         geQuaternion    Quat;
00717         geXForm3d               RotXForm;
00718         GE_Collision    Collision;
00719         geWorld                 *World;
00720         GPlayer                 *Player;
00721         CData                   Data;
00722 
00723         Player = (GPlayer*)PlayerData;
00724         
00725         if (Player->Inventory[ITEM_ROCKETS] <= 0 || !Player->InventoryHas[ITEM_ROCKETS])
00726         {
00727                 SwitchToNextBestWeapon(VSI, Player);
00728                 return;
00729         }
00730         
00731         Weapon = GenVSI_SpawnPlayer(VSI, "Weapon_Rocket");
00732 
00733         if (!Weapon)
00734         {
00735                 GenVSI_ConsolePrintf(VSI, "FireRocket:  Failed to add player.\n");
00736                 return;
00737         }
00738 
00739         Player->Inventory[ITEM_ROCKETS]--;
00740         
00741         if (Player->Inventory[ITEM_ROCKETS] < 0)
00742         {
00743                 SwitchToNextBestWeapon(VSI, Player);
00744                 Player->Inventory[ITEM_ROCKETS] = 0;
00745         }
00746         
00747         //UpdateClientInventory(VSI, Player, ITEM_ROCKETS);
00748 
00749         // Setup the callbacks for this weapon
00750         Weapon->Control = Rocket_Control;
00751         Weapon->Blocked = NULL;
00752         Weapon->Trigger = NULL;
00753         Weapon->Owner = Player;
00754         Weapon->Time = 0.0f;
00755         Weapon->PingTime = Player->PingTime;
00756 
00757         geVec3d_Set(&Weapon->Mins, -10.0f, -10.0f, -10.0f);
00758         geVec3d_Set(&Weapon->Maxs,  10.0f,  10.0f,  10.0f);
00759 
00760         Weapon->ControlIndex = 6;
00761 
00762         Weapon->ViewFlags = (VIEW_TYPE_ACTOR | VIEW_TYPE_LIGHT);
00763         Weapon->ViewIndex = ACTOR_INDEX_ROCKET_AMMO;
00764         Weapon->FxFlags = FX_SMOKE_TRAIL;               // Make some smoke follow rocket
00765         Weapon->Scale = 1.0f;
00766         Weapon->MotionIndex = MOTION_INDEX_NONE;
00767 
00768         Weapon->XForm = Player->XForm;
00769         
00770         geVec3d_Add(&Weapon->XForm.Translation, &Player->GunOffset, &Weapon->XForm.Translation);
00771 
00772         geXForm3d_GetIn(&Weapon->XForm, &In);
00773         geXForm3d_GetUp(&Weapon->XForm, &Up);
00774         geXForm3d_GetLeft(&Weapon->XForm, &Rt);
00775 
00776         Front = Weapon->XForm.Translation;
00777 
00778         geVec3d_AddScaled(&Front, &In, 20000.0f, &Back);
00779 
00780         World = GenVSI_GetWorld(VSI);
00781 
00782         assert(World);
00783 
00784         Data.VSI = VSI;
00785         Data.Player = Player;
00786 
00787         // Find out what direction the rocket needs to go to hit the target in the center of the screen
00788         if (geWorld_Collision(World, NULL, NULL, &Front, &Back, GE_CONTENTS_CANNOT_OCCUPY, GE_COLLIDE_MODELS, 0xffffffff, SelfCollisionCB, &Data, &Collision))
00789 
00790                 Impact = Collision.Impact;
00791         else
00792                 Impact = Back;
00793 
00794         // Position the rocket under the lower left arm
00795         geVec3d_AddScaled(&Front, &In, 70.0f, &Front);
00796         geVec3d_AddScaled(&Front, &Up, -30.0f, &Front);
00797         geVec3d_AddScaled(&Front, &Rt, -28.0f, &Front);
00798 
00799         XFormFromVector(&Front, &Impact, 0.0f, &Weapon->XForm);
00800         
00801         // HACK!!! Rocket is backwards, so rotate about up vector 180
00802         // Rotate the thing 180
00803         Up.X = 0.0f;
00804         Up.Y = 1.0f;
00805         Up.Z = 0.0f;
00806         geQuaternion_SetFromAxisAngle(&Quat, &Up, 3.14159f);
00807         geQuaternion_ToMatrix(&Quat, &RotXForm);
00808         geXForm3d_Multiply(&Weapon->XForm, &RotXForm, &Weapon->XForm);
00809 
00810         // Play the "take off" sound
00811         GenVSI_PlaySound(VSI, 0, &Player->XForm.Translation);
00812 
00813         Player->NextWeaponTime = GenVSI_GetTime(VSI) + 0.8f;
00814 
00815         Player->VPos = Player->XForm.Translation;
00816 }
00817 
00818 //=====================================================================================
00819 //      Blaster_Control
00820 //=====================================================================================
00821 geBoolean Blaster_Control(GenVSI *VSI, void *PlayerData, float Time)
00822 {
00823         geVec3d                 In, Front, Back;
00824         geXForm3d               DestXForm;
00825         GE_Collision    Collide;
00826         float                   Speed;
00827         GPlayer                 *Player;
00828         geWorld                 *World;
00829         CData                   Data;
00830 
00831         Player = (GPlayer*)PlayerData;
00832 
00833         Player->Time += Time;
00834         
00835         Speed = Player->Time*3600.0f;
00836 
00837         if (Speed > 4000.0f)
00838                 Speed = 4000.0f;
00839 
00840         geXForm3d_Copy(&Player->XForm, &DestXForm);
00841 
00842         geXForm3d_GetIn(&Player->XForm, &In);
00843         geVec3d_Scale(&In, Speed*Time, &In);    
00844         geXForm3d_Translate(&DestXForm, In.X, In.Y, In.Z);
00845 
00846         geXForm3d_GetIn(&Player->XForm, &In);
00847         geVec3d_Scale(&In, 500.f, &Player->Velocity);
00848 
00849         Front = Player->XForm.Translation;
00850         Back = DestXForm.Translation;
00851 
00852         geXForm3d_Copy(&DestXForm, &Player->XForm);
00853 
00854         World = GenVSI_GetWorld(VSI);
00855 
00856         assert(World);
00857 
00858         Data.VSI = VSI;
00859         Data.Player = Player;
00860 
00861         if (geWorld_Collision(World, NULL, NULL, &Front, &Back, GE_CONTENTS_CANNOT_OCCUPY, GE_COLLIDE_MODELS|GE_COLLIDE_ACTORS, 0xffffffff, SelfCollisionCB, &Data, &Collide))
00862         {
00863                 Player->XForm.Translation = Collide.Impact;
00864                 geVec3d_AddScaled(&Player->XForm.Translation, &Collide.Plane.Normal, 40.0f, &Player->XForm.Translation);
00865 
00866                 if (Collide.Model)
00867                 {
00868                         GPlayer         *Target;
00869 
00870                         Target = (GPlayer*)geWorld_ModelGetUserData(Collide.Model);
00871                         if (Target && Target->Trigger && Target->ViewFlags & VIEW_TYPE_PHYSOB)
00872                         {                               
00873                                 Target->Trigger(VSI, Target, Player, (void*)&Collide);
00874                         }
00875                 }
00876 
00877                 //if (VSI->Mode == MODE_Server)
00878                 {
00879                         if (Collide.Actor)
00880                         {
00881                                 GPlayer         *PlayerHit;
00882                                 PlayerHit = GenVSI_ActorToPlayer(VSI, Collide.Actor);
00883 
00884                                 // Only radius dammage will hurt the player that shot the rocket...
00885                                 if (PlayerHit && PlayerHit != Player->Owner)    
00886                                         DammagePlayer(VSI, Player, PlayerHit, 15, BLASTER_POWER,Time);
00887                         }
00888                         else
00889                                 RadiusDammage(VSI, Player, 10, BLASTER_POWER_RADIUS, BLASTER_RADIUS, Time);
00890                 }
00891 
00892                 GenVSI_SpawnFx(VSI, FX_EXPLODE2, &Player->XForm.Translation, SOUND_INDEX_BLASTER_BANG);
00893                 GenVSI_DestroyPlayer(VSI, PlayerData);
00894         }
00895         
00896         //if (Player->Time >= 25.0f)                            // Kill it after 20 seconds
00897         //      GenVSI_DestroyPlayer(VSI, PlayerData);
00898 
00899         Player->VPos = Player->XForm.Translation;
00900 
00901         return GE_TRUE;
00902 }
00903 
00904 //=====================================================================================
00905 //      FireBlaster
00906 //=====================================================================================
00907 void FireBlaster(GenVSI *VSI, void *PlayerData, float Time)
00908 {
00909         GPlayer                 *Weapon;
00910         geVec3d                 Up, In, Rt, Front, Back, Impact;
00911         GE_Collision    Collision;
00912         geWorld                 *World;
00913         GPlayer                 *Player;
00914 
00915         Player = (GPlayer*)PlayerData;
00916         
00917         Weapon = GenVSI_SpawnPlayer(VSI, "Weapon_Blaster");
00918 
00919         if (!Weapon)
00920         {
00921                 GenVSI_ConsolePrintf(VSI, "FireBlaster:  Failed to add player.\n");
00922                 return;
00923         }
00924 
00925         // Setup the callbacks for this weapon
00926         Weapon->Control = Blaster_Control;
00927         Weapon->Blocked = NULL;
00928         Weapon->Trigger = NULL;
00929         Weapon->Owner = Player;
00930         Weapon->Time = 0.0f;
00931         Weapon->PingTime = Player->PingTime;
00932 
00933         geVec3d_Set(&Weapon->Mins, -10.0f, -10.0f, -10.0f);
00934         geVec3d_Set(&Weapon->Maxs,  10.0f,  10.0f,  10.0f);
00935 
00936         Weapon->ControlIndex = 5;
00937 
00938         Weapon->ViewFlags = (VIEW_TYPE_SPRITE | VIEW_TYPE_LIGHT);
00939         Weapon->ViewIndex = TEXTURE_INDEX_WEAPON2;
00940         Weapon->Scale = 2.5f;
00941         Weapon->FxFlags = FX_PARTICLE_TRAIL;            // Make some particles follow Weapon_Blaster
00942 
00943         Weapon->XForm = Player->XForm;
00944         
00945         geVec3d_Add(&Weapon->XForm.Translation, &Player->GunOffset, &Weapon->XForm.Translation);
00946 
00947         geXForm3d_GetIn(&Weapon->XForm, &In);
00948         geXForm3d_GetUp(&Weapon->XForm, &Up);
00949         geXForm3d_GetLeft(&Weapon->XForm, &Rt);
00950 
00951         Front = Weapon->XForm.Translation;
00952 
00953         geVec3d_AddScaled(&Front, &In, 10000.0f, &Back);
00954 
00955         World = GenVSI_GetWorld(VSI);
00956         assert(World);
00957 
00958         // Find out what direction the rocket needs to go to hit the target in the center of the screen
00959         if (geWorld_Collision(World, NULL, NULL, &Front, &Back, GE_CONTENTS_CANNOT_OCCUPY, GE_COLLIDE_ALL, 0, NULL, NULL, &Collision))
00960                 Impact = Collision.Impact;
00961         else
00962                 Impact = Back;
00963 
00964         // Position the Weapon_Blaster under the lower left arm
00965         geVec3d_AddScaled(&Front, &In, 70.0f, &Front);
00966         geVec3d_AddScaled(&Front, &Up, -10.0f, &Front);
00967         geVec3d_AddScaled(&Front, &Rt, -10.0f, &Front);
00968 
00969         XFormFromVector(&Front, &Impact, 0.0f, &Weapon->XForm);
00970 
00971         // HACK!!! Rocket is backwards, so rotate about up vector 180
00972         // Rotate the thing 180
00973 
00974         // Play the "take off" sound
00975         GenVSI_PlaySound(VSI, SOUND_INDEX_BLASTER, &Player->XForm.Translation);
00976 
00977         Player->NextWeaponTime = GenVSI_GetTime(VSI) + 0.6f;
00978 
00979         Player->VPos = Player->XForm.Translation;
00980 }
00981 
00982 //=====================================================================================
00983 //      Shredder_Control
00984 //=====================================================================================
00985 geBoolean Shredder_Control(GenVSI *VSI, void *PlayerData, float Time)
00986 {
00987         GPlayer                 *Player;
00988 
00989         Player = (GPlayer*)PlayerData;
00990 
00991         Player->Time += Time;
00992 
00993         if (Player->Time > 0.25f)
00994         {
00995                 Player->Owner->Weapon = NULL;
00996                 GenVSI_DestroyPlayer(VSI, PlayerData);
00997                 return GE_TRUE;
00998         }
00999 
01000         Player->XForm = Player->Owner->XForm;
01001 
01002         geVec3d_Add(&Player->XForm.Translation, &Player->Owner->GunOffset, &Player->XForm.Translation);
01003 
01004         Player->VPos = Player->XForm.Translation;
01005 
01006         return GE_TRUE;
01007 }
01008 
01009 //=====================================================================================
01010 //      FireShredder
01011 //=====================================================================================
01012 void FireShredder(GenVSI *VSI, void *PlayerData, float Time)
01013 {
01014         GPlayer                 *Weapon;
01015         GE_Collision    Collision;
01016         geVec3d                 Front, Back, In;
01017         GPlayer                 *Player;
01018         geWorld                 *World;
01019         CData                   Data;
01020 
01021         Player = (GPlayer*)PlayerData;
01022 
01023         if (Player->Inventory[ITEM_SHREDDER] <= 0 || !Player->InventoryHas[ITEM_SHREDDER])
01024         {
01025                 SwitchToNextBestWeapon(VSI, Player);
01026                 return;
01027         }
01028 
01029         if (!Player->Weapon)            // Check to see if allready firing
01030         {
01031                 Weapon = GenVSI_SpawnPlayer(VSI, "Weapon_Shredder");
01032 
01033                 if (!Weapon)
01034                 {
01035                         GenVSI_ConsolePrintf(VSI, "FireShredder:  Failed to add player.\n");
01036                         return;
01037                 }
01038         }
01039         else
01040                 return;
01041 
01042         Player->Inventory[ITEM_SHREDDER]-= 5;
01043 
01044         if (Player->Inventory[ITEM_SHREDDER] < 0)
01045         {
01046                 SwitchToNextBestWeapon(VSI, Player);
01047                 Player->Inventory[ITEM_SHREDDER] = 0;
01048         }
01049 
01050         // Setup the callbacks for this weapon
01051         Weapon->Control = Shredder_Control;
01052         //Weapon->ControlIndex = 8;
01053         Weapon->Blocked = NULL;
01054         Weapon->Trigger = NULL;
01055         Weapon->Owner = Player;
01056         Player->Weapon = Weapon;
01057         Weapon->Time = 0.0f;
01058 
01059         Weapon->ViewFlags = VIEW_TYPE_NONE;
01060         Weapon->ViewIndex = VIEW_INDEX_NONE;
01061         Weapon->FxFlags = FX_SHREDDER;  
01062 
01063         geVec3d_Set(&Weapon->Mins, -1.0f, -1.0f, -1.0f);
01064         geVec3d_Set(&Weapon->Maxs,  1.0f,  1.0f,  1.0f);
01065 
01066         Weapon->XForm = Player->XForm;
01067 
01068         geVec3d_Add(&Weapon->XForm.Translation, &Player->GunOffset, &Weapon->XForm.Translation);
01069 
01070         // Play the sound
01071         GenVSI_PlaySound(VSI, SOUND_INDEX_SHREDDER, &Player->XForm.Translation);
01072 
01073         Front = Weapon->XForm.Translation;
01074         geXForm3d_GetIn(&Weapon->XForm, &In);
01075         geVec3d_AddScaled(&Front, &In, 10000.0f, &Back);
01076 
01077         World = GenVSI_GetWorld(VSI);
01078 
01079         assert(World);
01080 
01081         Data.VSI = VSI;
01082         Data.Player = Player;
01083 
01084         if (geWorld_Collision(World, NULL, NULL, &Front, &Back, GE_CONTENTS_CANNOT_OCCUPY, GE_COLLIDE_ACTORS, 0xffffffff, SelfCollisionCB, &Data, &Collision))
01085         {
01086                 if (Collision.Actor)
01087                 {
01088                         GPlayer         *PlayerHit;
01089 
01090                         PlayerHit = GenVSI_ActorToPlayer(VSI, Collision.Actor);
01091 
01092                         if (PlayerHit)
01093                                 DammagePlayer(VSI, Weapon, PlayerHit, 25, 90.0f, Time);
01094                 }
01095 
01096                 if (Collision.Model)
01097                 {
01098                         GPlayer         *Target;
01099 
01100                         Target = (GPlayer*)geWorld_ModelGetUserData(Collision.Model);
01101                         if (Target && Target->Trigger && (Target->ViewFlags & VIEW_TYPE_PHYSOB))
01102                         {
01103                                 geXForm3d_GetIn(&Player->XForm, &In);
01104                                 Player->Velocity = In;
01105                                 geVec3d_Scale(&In, 1000.f, &Player->Velocity);
01106                                 Target->Trigger(VSI, Target, Player, (void*)&Collision);
01107                         }
01108                 }
01109         }
01110 
01111         Player->VPos = Player->XForm.Translation;
01112 
01113         Player->NextWeaponTime = GenVSI_GetTime(VSI) + 0.0f;
01114 }
01115 
01116 //=====================================================================================
01117 //      FireWeapon
01118 //=====================================================================================
01119 geBoolean FireWeapon(GenVSI *VSI, void *PlayerData, float Time)
01120 {
01121         GPlayer                 *Player;
01122 
01123         assert(PlayerData);
01124 
01125         Player = (GPlayer*)PlayerData;
01126 
01127         if (GenVSI_GetTime(VSI) < Player->NextWeaponTime)
01128                 return GE_TRUE;
01129         
01130         ValidateWeapon(VSI, PlayerData);
01131 
01132         switch (Player->CurrentWeapon)
01133         {
01134                 case 0:
01135                         FireBlaster(VSI, Player, Time);
01136                         break;
01137                 case 1:
01138                         FireGrenade(VSI, Player, Time);
01139                         break;
01140                 case 2:
01141                         FireRocket(VSI, Player, Time);
01142                         break;
01143                 case 3:
01144                         FireShredder(VSI, Player, Time);
01145                         break;
01146         }
01147 
01148         return GE_TRUE;
01149 }

Generated on Tue Sep 30 12:36:39 2003 for GTestAndEngine by doxygen 1.3.2