00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
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
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
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)
00067 BestWeapon = 0;
00068
00069 if (Player->ClientHandle != CLIENT_NULL_HANDLE)
00070 GenVSI_SetClientWeapon(VSI, Player->ClientHandle, (uint16)BestWeapon);
00071 }
00072
00073
00074
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
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
00104 assert(!"No best weapon!!!");
00105
00106 if (Player->ClientHandle != CLIENT_NULL_HANDLE)
00107 GenVSI_SetClientWeapon(VSI, Player->ClientHandle, 0);
00108 }
00109
00110
00111
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;
00140 Player->Control = Client_Control;
00141
00142 Player->State = PSTATE_Normal;
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
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
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)
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
00240 Target->State = PSTATE_Dead;
00241
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
00254 GenVSI_PlaySound(VSI, SOUND_INDEX_DIE, &Target->XForm.Translation);
00255
00256 Target->ViewFlags |= VIEW_TYPE_FORCE_XFORM;
00257
00258
00259 {
00260 int32 i;
00261
00262
00263 for (i=1; i<MAX_PLAYER_ITEMS; i++)
00264 {
00265 Target->Inventory[i] = 0;
00266 Target->InventoryHas[i] = GE_FALSE;
00267
00268 if (Target->ClientHandle != CLIENT_NULL_HANDLE)
00269 UpdateClientInventory(VSI, Target, i);
00270 }
00271
00272 Target->CurrentWeapon = 0;
00273
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
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
00299
00300 if (Target->State == PSTATE_Dead)
00301 return GE_TRUE;
00302 if (Target->State == PSTATE_DeadOnGround)
00303 return GE_TRUE;
00304
00305 if (Target->DammageFlags == 0)
00306 return GE_TRUE;
00307
00308
00309
00310 Amountf = (float)Amount;
00311
00312
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
00325 if (Target->ClientHandle != CLIENT_NULL_HANDLE)
00326 UpdateClientInventory(VSI, Target, ITEM_ARMOR);
00327
00328
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)
00337 Amountf *= 0.5f;
00338
00339
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
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
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
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
00403
00404
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)
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)
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
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
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
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
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
00514 GenVSI_DestroyPlayer(VSI, PlayerData);
00515 return GE_TRUE;
00516 }
00517 }
00518 }
00519
00520
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)
00526 {
00527
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
00533 GenVSI_DestroyPlayer(VSI, Player);
00534
00535 }
00536
00537 return GE_TRUE;
00538 }
00539
00540
00541
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
00574
00575
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
00609
00610 Player->VPos = Player->XForm.Translation;
00611 }
00612
00613
00614
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);
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;
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
00683 if (PlayerHit && PlayerHit != Player->Owner)
00684 DammagePlayer(VSI, Player, PlayerHit, 35, ROCKET_POWER, Time);
00685
00686
00687 RadiusDammage(VSI, Player, 30, ROCKET_POWER_RADIUS, ROCKET_RADIUS, Time);
00688
00689 GenVSI_DestroyPlayer(VSI, PlayerData);
00690 return GE_TRUE;
00691 }
00692
00693
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)
00703 GenVSI_DestroyPlayer(VSI, PlayerData);
00704
00705 return GE_TRUE;
00706 }
00707
00708
00709
00710
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
00748
00749
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;
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
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
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
00802
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
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
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
00878 {
00879 if (Collide.Actor)
00880 {
00881 GPlayer *PlayerHit;
00882 PlayerHit = GenVSI_ActorToPlayer(VSI, Collide.Actor);
00883
00884
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
00897
00898
00899 Player->VPos = Player->XForm.Translation;
00900
00901 return GE_TRUE;
00902 }
00903
00904
00905
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
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;
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
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
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
00972
00973
00974
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
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
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)
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
01051 Weapon->Control = Shredder_Control;
01052
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
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
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 }