00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023 #include "g_local.h"
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039 #define RESPAWN_ARMOR 25
00040 #define RESPAWN_HEALTH 35
00041 #define RESPAWN_AMMO 40
00042 #define RESPAWN_HOLDABLE 60
00043 #define RESPAWN_MEGAHEALTH 35//120
00044 #define RESPAWN_POWERUP 120
00045
00046
00047
00048
00049 int Pickup_Powerup( gentity_t *ent, gentity_t *other ) {
00050 int quantity;
00051 int i;
00052 gclient_t *client;
00053
00054 if ( !other->client->ps.powerups[ent->item->giTag] ) {
00055
00056
00057 other->client->ps.powerups[ent->item->giTag] =
00058 level.time - ( level.time % 1000 );
00059 }
00060
00061 if ( ent->count ) {
00062 quantity = ent->count;
00063 } else {
00064 quantity = ent->item->quantity;
00065 }
00066
00067 other->client->ps.powerups[ent->item->giTag] += quantity * 1000;
00068
00069
00070 for ( i = 0 ; i < level.maxclients ; i++ ) {
00071 vec3_t delta;
00072 float len;
00073 vec3_t forward;
00074 trace_t tr;
00075
00076 client = &level.clients[i];
00077 if ( client == other->client ) {
00078 continue;
00079 }
00080 if ( client->pers.connected == CON_DISCONNECTED ) {
00081 continue;
00082 }
00083 if ( client->ps.stats[STAT_HEALTH] <= 0 ) {
00084 continue;
00085 }
00086
00087
00088
00089 if ( g_gametype.integer >= GT_TEAM && other->client->sess.sessionTeam == client->sess.sessionTeam ) {
00090 continue;
00091 }
00092
00093
00094 VectorSubtract( ent->s.pos.trBase, client->ps.origin, delta );
00095 len = VectorNormalize( delta );
00096 if ( len > 192 ) {
00097 continue;
00098 }
00099
00100
00101 AngleVectors( client->ps.viewangles, forward, NULL, NULL );
00102 if ( DotProduct( delta, forward ) < 0.4 ) {
00103 continue;
00104 }
00105
00106
00107 trap_Trace( &tr, client->ps.origin, NULL, NULL, ent->s.pos.trBase, ENTITYNUM_NONE, CONTENTS_SOLID );
00108 if ( tr.fraction != 1.0 ) {
00109 continue;
00110 }
00111
00112
00113 client->ps.persistant[PERS_PLAYEREVENTS] ^= PLAYEREVENT_DENIEDREWARD;
00114 }
00115 return RESPAWN_POWERUP;
00116 }
00117
00118
00119
00120 #ifdef MISSIONPACK
00121 int Pickup_PersistantPowerup( gentity_t *ent, gentity_t *other ) {
00122 int clientNum;
00123 char userinfo[MAX_INFO_STRING];
00124 float handicap;
00125 int max;
00126
00127 other->client->ps.stats[STAT_PERSISTANT_POWERUP] = ent->item - bg_itemlist;
00128 other->client->persistantPowerup = ent;
00129
00130 switch( ent->item->giTag ) {
00131 case PW_GUARD:
00132 clientNum = other->client->ps.clientNum;
00133 trap_GetUserinfo( clientNum, userinfo, sizeof(userinfo) );
00134 handicap = atof( Info_ValueForKey( userinfo, "handicap" ) );
00135 if( handicap<=0.0f || handicap>100.0f) {
00136 handicap = 100.0f;
00137 }
00138 max = (int)(2 * handicap);
00139
00140 other->health = max;
00141 other->client->ps.stats[STAT_HEALTH] = max;
00142 other->client->ps.stats[STAT_MAX_HEALTH] = max;
00143 other->client->ps.stats[STAT_ARMOR] = max;
00144 other->client->pers.maxHealth = max;
00145
00146 break;
00147
00148 case PW_SCOUT:
00149 clientNum = other->client->ps.clientNum;
00150 trap_GetUserinfo( clientNum, userinfo, sizeof(userinfo) );
00151 handicap = atof( Info_ValueForKey( userinfo, "handicap" ) );
00152 if( handicap<=0.0f || handicap>100.0f) {
00153 handicap = 100.0f;
00154 }
00155 other->client->pers.maxHealth = handicap;
00156 other->client->ps.stats[STAT_ARMOR] = 0;
00157 break;
00158
00159 case PW_DOUBLER:
00160 clientNum = other->client->ps.clientNum;
00161 trap_GetUserinfo( clientNum, userinfo, sizeof(userinfo) );
00162 handicap = atof( Info_ValueForKey( userinfo, "handicap" ) );
00163 if( handicap<=0.0f || handicap>100.0f) {
00164 handicap = 100.0f;
00165 }
00166 other->client->pers.maxHealth = handicap;
00167 break;
00168 case PW_AMMOREGEN:
00169 clientNum = other->client->ps.clientNum;
00170 trap_GetUserinfo( clientNum, userinfo, sizeof(userinfo) );
00171 handicap = atof( Info_ValueForKey( userinfo, "handicap" ) );
00172 if( handicap<=0.0f || handicap>100.0f) {
00173 handicap = 100.0f;
00174 }
00175 other->client->pers.maxHealth = handicap;
00176 memset(other->client->ammoTimes, 0, sizeof(other->client->ammoTimes));
00177 break;
00178 default:
00179 clientNum = other->client->ps.clientNum;
00180 trap_GetUserinfo( clientNum, userinfo, sizeof(userinfo) );
00181 handicap = atof( Info_ValueForKey( userinfo, "handicap" ) );
00182 if( handicap<=0.0f || handicap>100.0f) {
00183 handicap = 100.0f;
00184 }
00185 other->client->pers.maxHealth = handicap;
00186 break;
00187 }
00188
00189 return -1;
00190 }
00191
00192
00193 #endif
00194
00195 int Pickup_Holdable( gentity_t *ent, gentity_t *other ) {
00196
00197 other->client->ps.stats[STAT_HOLDABLE_ITEM] = ent->item - bg_itemlist;
00198
00199 if( ent->item->giTag == HI_KAMIKAZE ) {
00200 other->client->ps.eFlags |= EF_KAMIKAZE;
00201 }
00202
00203 return RESPAWN_HOLDABLE;
00204 }
00205
00206
00207
00208
00209 void Add_Ammo (gentity_t *ent, int weapon, int count)
00210 {
00211 ent->client->ps.ammo[weapon] += count;
00212 if ( ent->client->ps.ammo[weapon] > 200 ) {
00213 ent->client->ps.ammo[weapon] = 200;
00214 }
00215 }
00216
00217 int Pickup_Ammo (gentity_t *ent, gentity_t *other)
00218 {
00219 int quantity;
00220
00221 if ( ent->count ) {
00222 quantity = ent->count;
00223 } else {
00224 quantity = ent->item->quantity;
00225 }
00226
00227 Add_Ammo (other, ent->item->giTag, quantity);
00228
00229 return RESPAWN_AMMO;
00230 }
00231
00232
00233
00234
00235 int Pickup_Weapon (gentity_t *ent, gentity_t *other) {
00236 int quantity;
00237
00238 if ( ent->count < 0 ) {
00239 quantity = 0;
00240 } else {
00241 if ( ent->count ) {
00242 quantity = ent->count;
00243 } else {
00244 quantity = ent->item->quantity;
00245 }
00246
00247
00248 if ( ! (ent->flags & FL_DROPPED_ITEM) && g_gametype.integer != GT_TEAM ) {
00249
00250
00251 if ( other->client->ps.ammo[ ent->item->giTag ] < quantity ) {
00252 quantity = quantity - other->client->ps.ammo[ ent->item->giTag ];
00253 } else {
00254 quantity = 1;
00255 }
00256 }
00257 }
00258
00259
00260 other->client->ps.stats[STAT_WEAPONS] |= ( 1 << ent->item->giTag );
00261
00262 Add_Ammo( other, ent->item->giTag, quantity );
00263
00264 if (ent->item->giTag == WP_GRAPPLING_HOOK)
00265 other->client->ps.ammo[ent->item->giTag] = -1;
00266
00267
00268 if ( g_gametype.integer == GT_TEAM ) {
00269 return g_weaponTeamRespawn.integer;
00270 }
00271
00272 return g_weaponRespawn.integer;
00273 }
00274
00275
00276
00277
00278 int Pickup_Health (gentity_t *ent, gentity_t *other) {
00279 int max;
00280 int quantity;
00281
00282
00283 #ifdef MISSIONPACK
00284 if( other->client && bg_itemlist[other->client->ps.stats[STAT_PERSISTANT_POWERUP]].giTag == PW_GUARD ) {
00285 max = other->client->ps.stats[STAT_MAX_HEALTH];
00286 }
00287 else
00288 #endif
00289 if ( ent->item->quantity != 5 && ent->item->quantity != 100 ) {
00290 max = other->client->ps.stats[STAT_MAX_HEALTH];
00291 } else {
00292 max = other->client->ps.stats[STAT_MAX_HEALTH] * 2;
00293 }
00294
00295 if ( ent->count ) {
00296 quantity = ent->count;
00297 } else {
00298 quantity = ent->item->quantity;
00299 }
00300
00301 other->health += quantity;
00302
00303 if (other->health > max ) {
00304 other->health = max;
00305 }
00306 other->client->ps.stats[STAT_HEALTH] = other->health;
00307
00308 if ( ent->item->quantity == 100 ) {
00309 return RESPAWN_MEGAHEALTH;
00310 }
00311
00312 return RESPAWN_HEALTH;
00313 }
00314
00315
00316
00317 int Pickup_Armor( gentity_t *ent, gentity_t *other ) {
00318 #ifdef MISSIONPACK
00319 int upperBound;
00320
00321 other->client->ps.stats[STAT_ARMOR] += ent->item->quantity;
00322
00323 if( other->client && bg_itemlist[other->client->ps.stats[STAT_PERSISTANT_POWERUP]].giTag == PW_GUARD ) {
00324 upperBound = other->client->ps.stats[STAT_MAX_HEALTH];
00325 }
00326 else {
00327 upperBound = other->client->ps.stats[STAT_MAX_HEALTH] * 2;
00328 }
00329
00330 if ( other->client->ps.stats[STAT_ARMOR] > upperBound ) {
00331 other->client->ps.stats[STAT_ARMOR] = upperBound;
00332 }
00333 #else
00334 other->client->ps.stats[STAT_ARMOR] += ent->item->quantity;
00335 if ( other->client->ps.stats[STAT_ARMOR] > other->client->ps.stats[STAT_MAX_HEALTH] * 2 ) {
00336 other->client->ps.stats[STAT_ARMOR] = other->client->ps.stats[STAT_MAX_HEALTH] * 2;
00337 }
00338 #endif
00339
00340 return RESPAWN_ARMOR;
00341 }
00342
00343
00344
00345
00346
00347
00348
00349
00350 void RespawnItem( gentity_t *ent ) {
00351
00352 if (ent->team) {
00353 gentity_t *master;
00354 int count;
00355 int choice;
00356
00357 if ( !ent->teammaster ) {
00358 G_Error( "RespawnItem: bad teammaster");
00359 }
00360 master = ent->teammaster;
00361
00362 for (count = 0, ent = master; ent; ent = ent->teamchain, count++)
00363 ;
00364
00365 choice = rand() % count;
00366
00367 for (count = 0, ent = master; count < choice; ent = ent->teamchain, count++)
00368 ;
00369 }
00370
00371 ent->r.contents = CONTENTS_TRIGGER;
00372 ent->s.eFlags &= ~EF_NODRAW;
00373 ent->r.svFlags &= ~SVF_NOCLIENT;
00374 trap_LinkEntity (ent);
00375
00376 if ( ent->item->giType == IT_POWERUP ) {
00377
00378 gentity_t *te;
00379
00380
00381 if (ent->speed) {
00382 te = G_TempEntity( ent->s.pos.trBase, EV_GENERAL_SOUND );
00383 }
00384 else {
00385 te = G_TempEntity( ent->s.pos.trBase, EV_GLOBAL_SOUND );
00386 }
00387 te->s.eventParm = G_SoundIndex( "sound/items/poweruprespawn.wav" );
00388 te->r.svFlags |= SVF_BROADCAST;
00389 }
00390
00391 if ( ent->item->giType == IT_HOLDABLE && ent->item->giTag == HI_KAMIKAZE ) {
00392
00393 gentity_t *te;
00394
00395
00396 if (ent->speed) {
00397 te = G_TempEntity( ent->s.pos.trBase, EV_GENERAL_SOUND );
00398 }
00399 else {
00400 te = G_TempEntity( ent->s.pos.trBase, EV_GLOBAL_SOUND );
00401 }
00402 te->s.eventParm = G_SoundIndex( "sound/items/kamikazerespawn.wav" );
00403 te->r.svFlags |= SVF_BROADCAST;
00404 }
00405
00406
00407 G_AddEvent( ent, EV_ITEM_RESPAWN, 0 );
00408
00409 ent->nextthink = 0;
00410 }
00411
00412
00413
00414
00415
00416
00417
00418 void Touch_Item (gentity_t *ent, gentity_t *other, trace_t *trace) {
00419 int respawn;
00420 qboolean predict;
00421
00422 if (!other->client)
00423 return;
00424 if (other->health < 1)
00425 return;
00426
00427
00428 if ( !BG_CanItemBeGrabbed( g_gametype.integer, &ent->s, &other->client->ps ) ) {
00429 return;
00430 }
00431
00432 G_LogPrintf( "Item: %i %s\n", other->s.number, ent->item->classname );
00433
00434 predict = other->client->pers.predictItemPickup;
00435
00436
00437 switch( ent->item->giType ) {
00438 case IT_WEAPON:
00439 respawn = Pickup_Weapon(ent, other);
00440
00441 break;
00442 case IT_AMMO:
00443 respawn = Pickup_Ammo(ent, other);
00444
00445 break;
00446 case IT_ARMOR:
00447 respawn = Pickup_Armor(ent, other);
00448 break;
00449 case IT_HEALTH:
00450 respawn = Pickup_Health(ent, other);
00451 break;
00452 case IT_POWERUP:
00453 respawn = Pickup_Powerup(ent, other);
00454 predict = qfalse;
00455 break;
00456 #ifdef MISSIONPACK
00457 case IT_PERSISTANT_POWERUP:
00458 respawn = Pickup_PersistantPowerup(ent, other);
00459 break;
00460 #endif
00461 case IT_TEAM:
00462 respawn = Pickup_Team(ent, other);
00463 break;
00464 case IT_HOLDABLE:
00465 respawn = Pickup_Holdable(ent, other);
00466 break;
00467 default:
00468 return;
00469 }
00470
00471 if ( !respawn ) {
00472 return;
00473 }
00474
00475
00476 if (predict) {
00477 G_AddPredictableEvent( other, EV_ITEM_PICKUP, ent->s.modelindex );
00478 } else {
00479 G_AddEvent( other, EV_ITEM_PICKUP, ent->s.modelindex );
00480 }
00481
00482
00483 if ( ent->item->giType == IT_POWERUP || ent->item->giType == IT_TEAM) {
00484
00485 if (!ent->speed) {
00486 gentity_t *te;
00487
00488 te = G_TempEntity( ent->s.pos.trBase, EV_GLOBAL_ITEM_PICKUP );
00489 te->s.eventParm = ent->s.modelindex;
00490 te->r.svFlags |= SVF_BROADCAST;
00491 } else {
00492 gentity_t *te;
00493
00494 te = G_TempEntity( ent->s.pos.trBase, EV_GLOBAL_ITEM_PICKUP );
00495 te->s.eventParm = ent->s.modelindex;
00496
00497 te->r.svFlags |= SVF_SINGLECLIENT;
00498 te->r.singleClient = other->s.number;
00499 }
00500 }
00501
00502
00503 G_UseTargets (ent, other);
00504
00505
00506 if ( ent->wait == -1 ) {
00507 ent->r.svFlags |= SVF_NOCLIENT;
00508 ent->s.eFlags |= EF_NODRAW;
00509 ent->r.contents = 0;
00510 ent->unlinkAfterEvent = qtrue;
00511 return;
00512 }
00513
00514
00515 if ( ent->wait ) {
00516 respawn = ent->wait;
00517 }
00518
00519
00520 if ( ent->random ) {
00521 respawn += crandom() * ent->random;
00522 if ( respawn < 1 ) {
00523 respawn = 1;
00524 }
00525 }
00526
00527
00528 if ( ent->flags & FL_DROPPED_ITEM ) {
00529 ent->freeAfterEvent = qtrue;
00530 }
00531
00532
00533
00534
00535 ent->r.svFlags |= SVF_NOCLIENT;
00536 ent->s.eFlags |= EF_NODRAW;
00537 ent->r.contents = 0;
00538
00539
00540
00541
00542
00543 if ( respawn <= 0 ) {
00544 ent->nextthink = 0;
00545 ent->think = 0;
00546 } else {
00547 ent->nextthink = level.time + respawn * 1000;
00548 ent->think = RespawnItem;
00549 }
00550 trap_LinkEntity( ent );
00551 }
00552
00553
00554
00555
00556
00557
00558
00559
00560
00561
00562
00563 gentity_t *LaunchItem( gitem_t *item, vec3_t origin, vec3_t velocity ) {
00564 gentity_t *dropped;
00565
00566 dropped = G_Spawn();
00567
00568 dropped->s.eType = ET_ITEM;
00569 dropped->s.modelindex = item - bg_itemlist;
00570 dropped->s.modelindex2 = 1;
00571
00572 dropped->classname = item->classname;
00573 dropped->item = item;
00574 VectorSet (dropped->r.mins, -ITEM_RADIUS, -ITEM_RADIUS, -ITEM_RADIUS);
00575 VectorSet (dropped->r.maxs, ITEM_RADIUS, ITEM_RADIUS, ITEM_RADIUS);
00576 dropped->r.contents = CONTENTS_TRIGGER;
00577
00578 dropped->touch = Touch_Item;
00579
00580 G_SetOrigin( dropped, origin );
00581 dropped->s.pos.trType = TR_GRAVITY;
00582 dropped->s.pos.trTime = level.time;
00583 VectorCopy( velocity, dropped->s.pos.trDelta );
00584
00585 dropped->s.eFlags |= EF_BOUNCE_HALF;
00586 #ifdef MISSIONPACK
00587 if ((g_gametype.integer == GT_CTF || g_gametype.integer == GT_1FCTF) && item->giType == IT_TEAM) {
00588 #else
00589 if (g_gametype.integer == GT_CTF && item->giType == IT_TEAM) {
00590 #endif
00591 dropped->think = Team_DroppedFlagThink;
00592 dropped->nextthink = level.time + 30000;
00593 Team_CheckDroppedItem( dropped );
00594 } else {
00595 dropped->think = G_FreeEntity;
00596 dropped->nextthink = level.time + 30000;
00597 }
00598
00599 dropped->flags = FL_DROPPED_ITEM;
00600
00601 trap_LinkEntity (dropped);
00602
00603 return dropped;
00604 }
00605
00606
00607
00608
00609
00610
00611
00612
00613 gentity_t *Drop_Item( gentity_t *ent, gitem_t *item, float angle ) {
00614 vec3_t velocity;
00615 vec3_t angles;
00616
00617 VectorCopy( ent->s.apos.trBase, angles );
00618 angles[YAW] += angle;
00619 angles[PITCH] = 0;
00620
00621 AngleVectors( angles, velocity, NULL, NULL );
00622 VectorScale( velocity, 150, velocity );
00623 velocity[2] += 200 + crandom() * 50;
00624
00625 return LaunchItem( item, ent->s.pos.trBase, velocity );
00626 }
00627
00628
00629
00630
00631
00632
00633
00634
00635
00636 void Use_Item( gentity_t *ent, gentity_t *other, gentity_t *activator ) {
00637 RespawnItem( ent );
00638 }
00639
00640
00641
00642
00643
00644
00645
00646
00647
00648
00649
00650 void FinishSpawningItem( gentity_t *ent ) {
00651 trace_t tr;
00652 vec3_t dest;
00653
00654 VectorSet( ent->r.mins, -ITEM_RADIUS, -ITEM_RADIUS, -ITEM_RADIUS );
00655 VectorSet( ent->r.maxs, ITEM_RADIUS, ITEM_RADIUS, ITEM_RADIUS );
00656
00657 ent->s.eType = ET_ITEM;
00658 ent->s.modelindex = ent->item - bg_itemlist;
00659 ent->s.modelindex2 = 0;
00660
00661 ent->r.contents = CONTENTS_TRIGGER;
00662 ent->touch = Touch_Item;
00663
00664 ent->use = Use_Item;
00665
00666 if ( ent->spawnflags & 1 ) {
00667
00668 G_SetOrigin( ent, ent->s.origin );
00669 } else {
00670
00671 VectorSet( dest, ent->s.origin[0], ent->s.origin[1], ent->s.origin[2] - 4096 );
00672 trap_Trace( &tr, ent->s.origin, ent->r.mins, ent->r.maxs, dest, ent->s.number, MASK_SOLID );
00673 if ( tr.startsolid ) {
00674 G_Printf ("FinishSpawningItem: %s startsolid at %s\n", ent->classname, vtos(ent->s.origin));
00675 G_FreeEntity( ent );
00676 return;
00677 }
00678
00679
00680 ent->s.groundEntityNum = tr.entityNum;
00681
00682 G_SetOrigin( ent, tr.endpos );
00683 }
00684
00685
00686 if ( ( ent->flags & FL_TEAMSLAVE ) || ent->targetname ) {
00687 ent->s.eFlags |= EF_NODRAW;
00688 ent->r.contents = 0;
00689 return;
00690 }
00691
00692
00693 if ( ent->item->giType == IT_POWERUP ) {
00694 float respawn;
00695
00696 respawn = 45 + crandom() * 15;
00697 ent->s.eFlags |= EF_NODRAW;
00698 ent->r.contents = 0;
00699 ent->nextthink = level.time + respawn * 1000;
00700 ent->think = RespawnItem;
00701 return;
00702 }
00703
00704
00705 trap_LinkEntity (ent);
00706 }
00707
00708
00709 qboolean itemRegistered[MAX_ITEMS];
00710
00711
00712
00713
00714
00715
00716 void G_CheckTeamItems( void ) {
00717
00718
00719 Team_InitGame();
00720
00721 if( g_gametype.integer == GT_CTF ) {
00722 gitem_t *item;
00723
00724
00725 item = BG_FindItem( "Red Flag" );
00726 if ( !item || !itemRegistered[ item - bg_itemlist ] ) {
00727 G_Printf( S_COLOR_YELLOW "WARNING: No team_CTF_redflag in map" );
00728 }
00729 item = BG_FindItem( "Blue Flag" );
00730 if ( !item || !itemRegistered[ item - bg_itemlist ] ) {
00731 G_Printf( S_COLOR_YELLOW "WARNING: No team_CTF_blueflag in map" );
00732 }
00733 }
00734 #ifdef MISSIONPACK
00735 if( g_gametype.integer == GT_1FCTF ) {
00736 gitem_t *item;
00737
00738
00739 item = BG_FindItem( "Red Flag" );
00740 if ( !item || !itemRegistered[ item - bg_itemlist ] ) {
00741 G_Printf( S_COLOR_YELLOW "WARNING: No team_CTF_redflag in map" );
00742 }
00743 item = BG_FindItem( "Blue Flag" );
00744 if ( !item || !itemRegistered[ item - bg_itemlist ] ) {
00745 G_Printf( S_COLOR_YELLOW "WARNING: No team_CTF_blueflag in map" );
00746 }
00747 item = BG_FindItem( "Neutral Flag" );
00748 if ( !item || !itemRegistered[ item - bg_itemlist ] ) {
00749 G_Printf( S_COLOR_YELLOW "WARNING: No team_CTF_neutralflag in map" );
00750 }
00751 }
00752
00753 if( g_gametype.integer == GT_OBELISK ) {
00754 gentity_t *ent;
00755
00756
00757 ent = NULL;
00758 ent = G_Find( ent, FOFS(classname), "team_redobelisk" );
00759 if( !ent ) {
00760 G_Printf( S_COLOR_YELLOW "WARNING: No team_redobelisk in map" );
00761 }
00762
00763 ent = NULL;
00764 ent = G_Find( ent, FOFS(classname), "team_blueobelisk" );
00765 if( !ent ) {
00766 G_Printf( S_COLOR_YELLOW "WARNING: No team_blueobelisk in map" );
00767 }
00768 }
00769
00770 if( g_gametype.integer == GT_HARVESTER ) {
00771 gentity_t *ent;
00772
00773
00774 ent = NULL;
00775 ent = G_Find( ent, FOFS(classname), "team_redobelisk" );
00776 if( !ent ) {
00777 G_Printf( S_COLOR_YELLOW "WARNING: No team_redobelisk in map" );
00778 }
00779
00780 ent = NULL;
00781 ent = G_Find( ent, FOFS(classname), "team_blueobelisk" );
00782 if( !ent ) {
00783 G_Printf( S_COLOR_YELLOW "WARNING: No team_blueobelisk in map" );
00784 }
00785
00786 ent = NULL;
00787 ent = G_Find( ent, FOFS(classname), "team_neutralobelisk" );
00788 if( !ent ) {
00789 G_Printf( S_COLOR_YELLOW "WARNING: No team_neutralobelisk in map" );
00790 }
00791 }
00792 #endif
00793 }
00794
00795
00796
00797
00798
00799
00800 void ClearRegisteredItems( void ) {
00801 memset( itemRegistered, 0, sizeof( itemRegistered ) );
00802
00803
00804 RegisterItem( BG_FindItemForWeapon( WP_MACHINEGUN ) );
00805 RegisterItem( BG_FindItemForWeapon( WP_GAUNTLET ) );
00806 #ifdef MISSIONPACK
00807 if( g_gametype.integer == GT_HARVESTER ) {
00808 RegisterItem( BG_FindItem( "Red Cube" ) );
00809 RegisterItem( BG_FindItem( "Blue Cube" ) );
00810 }
00811 #endif
00812 }
00813
00814
00815
00816
00817
00818
00819
00820
00821 void RegisterItem( gitem_t *item ) {
00822 if ( !item ) {
00823 G_Error( "RegisterItem: NULL" );
00824 }
00825 itemRegistered[ item - bg_itemlist ] = qtrue;
00826 }
00827
00828
00829
00830
00831
00832
00833
00834
00835
00836
00837 void SaveRegisteredItems( void ) {
00838 char string[MAX_ITEMS+1];
00839 int i;
00840 int count;
00841
00842 count = 0;
00843 for ( i = 0 ; i < bg_numItems ; i++ ) {
00844 if ( itemRegistered[i] ) {
00845 count++;
00846 string[i] = '1';
00847 } else {
00848 string[i] = '0';
00849 }
00850 }
00851 string[ bg_numItems ] = 0;
00852
00853 G_Printf( "%i items registered\n", count );
00854 trap_SetConfigstring(CS_ITEMS, string);
00855 }
00856
00857
00858
00859
00860
00861
00862 int G_ItemDisabled( gitem_t *item ) {
00863
00864 char name[128];
00865
00866 Com_sprintf(name, sizeof(name), "disable_%s", item->classname);
00867 return trap_Cvar_VariableIntegerValue( name );
00868 }
00869
00870
00871
00872
00873
00874
00875
00876
00877
00878
00879
00880 void G_SpawnItem (gentity_t *ent, gitem_t *item) {
00881 G_SpawnFloat( "random", "0", &ent->random );
00882 G_SpawnFloat( "wait", "0", &ent->wait );
00883
00884 RegisterItem( item );
00885 if ( G_ItemDisabled(item) )
00886 return;
00887
00888 ent->item = item;
00889
00890
00891 ent->nextthink = level.time + FRAMETIME * 2;
00892 ent->think = FinishSpawningItem;
00893
00894 ent->physicsBounce = 0.50;
00895
00896 if ( item->giType == IT_POWERUP ) {
00897 G_SoundIndex( "sound/items/poweruprespawn.wav" );
00898 G_SpawnFloat( "noglobalsound", "0", &ent->speed);
00899 }
00900
00901 #ifdef MISSIONPACK
00902 if ( item->giType == IT_PERSISTANT_POWERUP ) {
00903 ent->s.generic1 = ent->spawnflags;
00904 }
00905 #endif
00906 }
00907
00908
00909
00910
00911
00912
00913
00914
00915 void G_BounceItem( gentity_t *ent, trace_t *trace ) {
00916 vec3_t velocity;
00917 float dot;
00918 int hitTime;
00919
00920
00921 hitTime = level.previousTime + ( level.time - level.previousTime ) * trace->fraction;
00922 BG_EvaluateTrajectoryDelta( &ent->s.pos, hitTime, velocity );
00923 dot = DotProduct( velocity, trace->plane.normal );
00924 VectorMA( velocity, -2*dot, trace->plane.normal, ent->s.pos.trDelta );
00925
00926
00927 VectorScale( ent->s.pos.trDelta, ent->physicsBounce, ent->s.pos.trDelta );
00928
00929
00930 if ( trace->plane.normal[2] > 0 && ent->s.pos.trDelta[2] < 40 ) {
00931 trace->endpos[2] += 1.0;
00932 SnapVector( trace->endpos );
00933 G_SetOrigin( ent, trace->endpos );
00934 ent->s.groundEntityNum = trace->entityNum;
00935 return;
00936 }
00937
00938 VectorAdd( ent->r.currentOrigin, trace->plane.normal, ent->r.currentOrigin);
00939 VectorCopy( ent->r.currentOrigin, ent->s.pos.trBase );
00940 ent->s.pos.trTime = level.time;
00941 }
00942
00943
00944
00945
00946
00947
00948
00949
00950 void G_RunItem( gentity_t *ent ) {
00951 vec3_t origin;
00952 trace_t tr;
00953 int contents;
00954 int mask;
00955
00956
00957 if ( ent->s.groundEntityNum == -1 ) {
00958 if ( ent->s.pos.trType != TR_GRAVITY ) {
00959 ent->s.pos.trType = TR_GRAVITY;
00960 ent->s.pos.trTime = level.time;
00961 }
00962 }
00963
00964 if ( ent->s.pos.trType == TR_STATIONARY ) {
00965
00966 G_RunThink( ent );
00967 return;
00968 }
00969
00970
00971 BG_EvaluateTrajectory( &ent->s.pos, level.time, origin );
00972
00973
00974 if ( ent->clipmask ) {
00975 mask = ent->clipmask;
00976 } else {
00977 mask = MASK_PLAYERSOLID & ~CONTENTS_BODY;
00978 }
00979 trap_Trace( &tr, ent->r.currentOrigin, ent->r.mins, ent->r.maxs, origin,
00980 ent->r.ownerNum, mask );
00981
00982 VectorCopy( tr.endpos, ent->r.currentOrigin );
00983
00984 if ( tr.startsolid ) {
00985 tr.fraction = 0;
00986 }
00987
00988 trap_LinkEntity( ent );
00989
00990
00991 G_RunThink( ent );
00992
00993 if ( tr.fraction == 1 ) {
00994 return;
00995 }
00996
00997
00998 contents = trap_PointContents( ent->r.currentOrigin, -1 );
00999 if ( contents & CONTENTS_NODROP ) {
01000 if (ent->item && ent->item->giType == IT_TEAM) {
01001 Team_FreeEntity(ent);
01002 } else {
01003 G_FreeEntity( ent );
01004 }
01005 return;
01006 }
01007
01008 G_BounceItem( ent, &tr );
01009 }
01010