00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012 #include "g_local.h"
00013 #include "bg_saga.h"
00014
00015 #define SIEGEITEM_STARTOFFRADAR 8
00016
00017 static char team1[512];
00018 static char team2[512];
00019
00020 siegePers_t g_siegePersistant = {qfalse, 0, 0};
00021
00022 int imperial_goals_required = 0;
00023 int imperial_goals_completed = 0;
00024 int rebel_goals_required = 0;
00025 int rebel_goals_completed = 0;
00026
00027 int imperial_time_limit = 0;
00028 int rebel_time_limit = 0;
00029
00030 int gImperialCountdown = 0;
00031 int gRebelCountdown = 0;
00032
00033 int rebel_attackers = 0;
00034 int imperial_attackers = 0;
00035
00036 qboolean gSiegeRoundBegun = qfalse;
00037 qboolean gSiegeRoundEnded = qfalse;
00038 qboolean gSiegeRoundWinningTeam = 0;
00039 int gSiegeBeginTime = Q3_INFINITE;
00040
00041 int g_preroundState = 0;
00042
00043 void LogExit( const char *string );
00044 void SetTeamQuick(gentity_t *ent, int team, qboolean doBegin);
00045
00046 static char gParseObjectives[MAX_SIEGE_INFO_SIZE];
00047 static char gObjectiveCfgStr[1024];
00048
00049
00050
00051 void G_SiegeRegisterWeaponsAndHoldables(int team)
00052 {
00053 siegeTeam_t *stm = BG_SiegeFindThemeForTeam(team);
00054
00055 if (stm)
00056 {
00057 int i = 0;
00058 siegeClass_t *scl;
00059 while (i < stm->numClasses)
00060 {
00061 scl = stm->classes[i];
00062
00063 if (scl)
00064 {
00065 int j = 0;
00066 while (j < WP_NUM_WEAPONS)
00067 {
00068 if (scl->weapons & (1 << j))
00069 {
00070 RegisterItem(BG_FindItemForWeapon(j));
00071 }
00072 j++;
00073 }
00074 j = 0;
00075 while (j < HI_NUM_HOLDABLE)
00076 {
00077 if (scl->invenItems & (1 << j))
00078 {
00079 RegisterItem(BG_FindItemForHoldable(j));
00080 }
00081 j++;
00082 }
00083 }
00084 i++;
00085 }
00086 }
00087 }
00088
00089
00090
00091 void SiegeSetCompleteData(int team)
00092 {
00093 trap_SetConfigstring(CS_SIEGE_WINTEAM, va("%i", team));
00094 }
00095
00096 void InitSiegeMode(void)
00097 {
00098 vmCvar_t mapname;
00099 char levelname[512];
00100 char teamIcon[128];
00101 char goalreq[64];
00102 char teams[2048];
00103 char objective[MAX_SIEGE_INFO_SIZE];
00104 char objecStr[8192];
00105 int len = 0;
00106 int i = 0;
00107
00108 int objectiveNumTeam1 = 0;
00109 int objectiveNumTeam2 = 0;
00110 fileHandle_t f;
00111
00112 if (g_gametype.integer != GT_SIEGE)
00113 {
00114 goto failure;
00115 }
00116
00117
00118 SiegeSetCompleteData(0);
00119
00120
00121 if (g_siegeTeamSwitch.integer)
00122 {
00123 trap_SiegePersGet(&g_siegePersistant);
00124 if (g_siegePersistant.beatingTime)
00125 {
00126 trap_SetConfigstring(CS_SIEGE_TIMEOVERRIDE, va("%i", g_siegePersistant.lastTime));
00127 }
00128 else
00129 {
00130 trap_SetConfigstring(CS_SIEGE_TIMEOVERRIDE, "0");
00131 }
00132 }
00133 else
00134 {
00135 trap_SetConfigstring(CS_SIEGE_TIMEOVERRIDE, "0");
00136 }
00137
00138 imperial_goals_completed = 0;
00139 rebel_goals_completed = 0;
00140
00141 trap_Cvar_Register( &mapname, "mapname", "", CVAR_SERVERINFO | CVAR_ROM );
00142
00143 Com_sprintf(levelname, sizeof(levelname), "maps/%s.siege\0", mapname.string);
00144
00145 if (!levelname || !levelname[0])
00146 {
00147 goto failure;
00148 }
00149
00150 len = trap_FS_FOpenFile(levelname, &f, FS_READ);
00151
00152 if (!f || len >= MAX_SIEGE_INFO_SIZE)
00153 {
00154 goto failure;
00155 }
00156
00157 trap_FS_Read(siege_info, len, f);
00158
00159 trap_FS_FCloseFile(f);
00160
00161 siege_valid = 1;
00162
00163
00164 if (BG_SiegeGetPairedValue(siege_info, "preround_state", teams))
00165 {
00166 if (teams[0])
00167 {
00168 g_preroundState = atoi(teams);
00169 }
00170 }
00171
00172 if (BG_SiegeGetValueGroup(siege_info, "Teams", teams))
00173 {
00174 if (g_siegeTeam1.string[0] && Q_stricmp(g_siegeTeam1.string, "none"))
00175 {
00176 strcpy(team1, g_siegeTeam1.string);
00177 }
00178 else
00179 {
00180 BG_SiegeGetPairedValue(teams, "team1", team1);
00181 }
00182
00183 if (g_siegeTeam2.string[0] && Q_stricmp(g_siegeTeam2.string, "none"))
00184 {
00185 strcpy(team2, g_siegeTeam2.string);
00186 }
00187 else
00188 {
00189 BG_SiegeGetPairedValue(teams, "team2", team2);
00190 }
00191 }
00192 else
00193 {
00194 G_Error("Siege teams not defined");
00195 }
00196
00197 if (BG_SiegeGetValueGroup(siege_info, team2, gParseObjectives))
00198 {
00199 if (BG_SiegeGetPairedValue(gParseObjectives, "TeamIcon", teamIcon))
00200 {
00201 trap_Cvar_Set( "team2_icon", teamIcon);
00202 }
00203
00204 if (BG_SiegeGetPairedValue(gParseObjectives, "RequiredObjectives", goalreq))
00205 {
00206 rebel_goals_required = atoi(goalreq);
00207 }
00208 if (BG_SiegeGetPairedValue(gParseObjectives, "Timed", goalreq))
00209 {
00210 rebel_time_limit = atoi(goalreq)*1000;
00211 if (g_siegeTeamSwitch.integer &&
00212 g_siegePersistant.beatingTime)
00213 {
00214 gRebelCountdown = level.time + g_siegePersistant.lastTime;
00215 }
00216 else
00217 {
00218 gRebelCountdown = level.time + rebel_time_limit;
00219 }
00220 }
00221 if (BG_SiegeGetPairedValue(gParseObjectives, "attackers", goalreq))
00222 {
00223 rebel_attackers = atoi(goalreq);
00224 }
00225 }
00226
00227 if (BG_SiegeGetValueGroup(siege_info, team1, gParseObjectives))
00228 {
00229
00230 if (BG_SiegeGetPairedValue(gParseObjectives, "TeamIcon", teamIcon))
00231 {
00232 trap_Cvar_Set( "team1_icon", teamIcon);
00233 }
00234
00235 if (BG_SiegeGetPairedValue(gParseObjectives, "RequiredObjectives", goalreq))
00236 {
00237 imperial_goals_required = atoi(goalreq);
00238 }
00239 if (BG_SiegeGetPairedValue(gParseObjectives, "Timed", goalreq))
00240 {
00241 if (rebel_time_limit)
00242 {
00243 Com_Printf("Tried to set imperial time limit, but there's already a rebel time limit!\nOnly one team can have a time limit.\n");
00244 }
00245 else
00246 {
00247 imperial_time_limit = atoi(goalreq)*1000;
00248 if (g_siegeTeamSwitch.integer &&
00249 g_siegePersistant.beatingTime)
00250 {
00251 gImperialCountdown = level.time + g_siegePersistant.lastTime;
00252 }
00253 else
00254 {
00255 gImperialCountdown = level.time + imperial_time_limit;
00256 }
00257 }
00258 }
00259 if (BG_SiegeGetPairedValue(gParseObjectives, "attackers", goalreq))
00260 {
00261 imperial_attackers = atoi(goalreq);
00262 }
00263 }
00264
00265
00266 BG_SiegeLoadClasses(NULL);
00267
00268 if (!bgNumSiegeClasses)
00269 {
00270 G_Error("Couldn't find any player classes for Siege");
00271 }
00272
00273
00274
00275
00276
00277
00278
00279
00280
00281
00282
00283
00284
00285
00286
00287
00288
00289
00290
00291
00292
00293
00294
00295
00296
00297
00298
00299
00300 BG_SiegeLoadTeams();
00301
00302 if (!bgNumSiegeTeams)
00303 {
00304 G_Error("Couldn't find any player teams for Siege");
00305 }
00306
00307
00308
00309 if (BG_SiegeGetValueGroup(siege_info, team1, gParseObjectives))
00310 {
00311 if (BG_SiegeGetPairedValue(gParseObjectives, "UseTeam", goalreq))
00312 {
00313 BG_SiegeSetTeamTheme(SIEGETEAM_TEAM1, goalreq);
00314 }
00315
00316
00317 i = 1;
00318 strcpy(objecStr, va("Objective%i", i));
00319 while (BG_SiegeGetValueGroup(gParseObjectives, objecStr, objective))
00320 {
00321 objectiveNumTeam1++;
00322 i++;
00323 strcpy(objecStr, va("Objective%i", i));
00324 }
00325 }
00326 if (BG_SiegeGetValueGroup(siege_info, team2, gParseObjectives))
00327 {
00328 if (BG_SiegeGetPairedValue(gParseObjectives, "UseTeam", goalreq))
00329 {
00330 BG_SiegeSetTeamTheme(SIEGETEAM_TEAM2, goalreq);
00331 }
00332
00333
00334 i = 1;
00335 strcpy(objecStr, va("Objective%i", i));
00336 while (BG_SiegeGetValueGroup(gParseObjectives, objecStr, objective))
00337 {
00338 objectiveNumTeam2++;
00339 i++;
00340 strcpy(objecStr, va("Objective%i", i));
00341 }
00342 }
00343
00344
00345 strcpy(gObjectiveCfgStr, "t1");
00346 while (objectiveNumTeam1 > 0)
00347 {
00348 Q_strcat(gObjectiveCfgStr, 1024, "-0");
00349 objectiveNumTeam1--;
00350 }
00351
00352 Q_strcat(gObjectiveCfgStr, 1024, "|t2");
00353 while (objectiveNumTeam2 > 0)
00354 {
00355 Q_strcat(gObjectiveCfgStr, 1024, "-0");
00356 objectiveNumTeam2--;
00357 }
00358
00359
00360 trap_SetConfigstring(CS_SIEGE_OBJECTIVES, gObjectiveCfgStr);
00361
00362
00363 BG_PrecacheSabersForSiegeTeam(SIEGETEAM_TEAM1);
00364 BG_PrecacheSabersForSiegeTeam(SIEGETEAM_TEAM2);
00365
00366 G_SiegeRegisterWeaponsAndHoldables(SIEGETEAM_TEAM1);
00367 G_SiegeRegisterWeaponsAndHoldables(SIEGETEAM_TEAM2);
00368
00369 return;
00370
00371 failure:
00372 siege_valid = 0;
00373 }
00374
00375 void G_SiegeSetObjectiveComplete(int team, int objective, qboolean failIt)
00376 {
00377 char *p = NULL;
00378 int onObjective = 0;
00379
00380 if (team == SIEGETEAM_TEAM1)
00381 {
00382 p = strstr(gObjectiveCfgStr, "t1");
00383 }
00384 else if (team == SIEGETEAM_TEAM2)
00385 {
00386 p = strstr(gObjectiveCfgStr, "t2");
00387 }
00388
00389 if (!p)
00390 {
00391 assert(0);
00392 return;
00393 }
00394
00395
00396
00397 while (p && *p && *p != '|')
00398 {
00399 if (*p == '-')
00400 {
00401 onObjective++;
00402 }
00403
00404 if (onObjective == objective)
00405 {
00406
00407 p++;
00408
00409
00410
00411 if (failIt)
00412 {
00413 *p = '0';
00414 }
00415 else
00416 {
00417 *p = '1';
00418 }
00419 break;
00420 }
00421
00422 p++;
00423 }
00424
00425
00426 trap_SetConfigstring(CS_SIEGE_OBJECTIVES, gObjectiveCfgStr);
00427 }
00428
00429
00430 qboolean G_SiegeGetCompletionStatus(int team, int objective)
00431 {
00432 char *p = NULL;
00433 int onObjective = 0;
00434
00435 if (team == SIEGETEAM_TEAM1)
00436 {
00437 p = strstr(gObjectiveCfgStr, "t1");
00438 }
00439 else if (team == SIEGETEAM_TEAM2)
00440 {
00441 p = strstr(gObjectiveCfgStr, "t2");
00442 }
00443
00444 if (!p)
00445 {
00446 assert(0);
00447 return qfalse;
00448 }
00449
00450
00451
00452 while (p && *p && *p != '|')
00453 {
00454 if (*p == '-')
00455 {
00456 onObjective++;
00457 }
00458
00459 if (onObjective == objective)
00460 {
00461
00462 p++;
00463
00464
00465 if (*p == '1')
00466 {
00467 return qtrue;
00468 }
00469 else
00470 {
00471 return qfalse;
00472 }
00473 break;
00474 }
00475
00476 p++;
00477 }
00478
00479 return qfalse;
00480 }
00481
00482 void UseSiegeTarget(gentity_t *other, gentity_t *en, char *target)
00483 {
00484 gentity_t *t;
00485 gentity_t *ent;
00486
00487 if ( !en || !en->client )
00488 {
00489 ent = other;
00490 }
00491 else
00492 {
00493 ent = en;
00494 }
00495
00496 if (!en)
00497 {
00498 return;
00499 }
00500
00501 if ( !target )
00502 {
00503 return;
00504 }
00505
00506 t = NULL;
00507 while ( (t = G_Find (t, FOFS(targetname), target)) != NULL )
00508 {
00509 if ( t == ent )
00510 {
00511 G_Printf ("WARNING: Entity used itself.\n");
00512 }
00513 else
00514 {
00515 if ( t->use )
00516 {
00517 GlobalUse(t, ent, ent);
00518 }
00519 }
00520 if ( !ent->inuse )
00521 {
00522 G_Printf("entity was removed while using targets\n");
00523 return;
00524 }
00525 }
00526 }
00527
00528 void SiegeBroadcast_OBJECTIVECOMPLETE(int team, int client, int objective)
00529 {
00530 gentity_t *te;
00531 vec3_t nomatter;
00532
00533 VectorClear(nomatter);
00534
00535 te = G_TempEntity( nomatter, EV_SIEGE_OBJECTIVECOMPLETE );
00536 te->r.svFlags |= SVF_BROADCAST;
00537 te->s.eventParm = team;
00538 te->s.weapon = client;
00539 te->s.trickedentindex = objective;
00540 }
00541
00542 void SiegeBroadcast_ROUNDOVER(int winningteam, int winningclient)
00543 {
00544 gentity_t *te;
00545 vec3_t nomatter;
00546
00547 VectorClear(nomatter);
00548
00549 te = G_TempEntity( nomatter, EV_SIEGE_ROUNDOVER );
00550 te->r.svFlags |= SVF_BROADCAST;
00551 te->s.eventParm = winningteam;
00552 te->s.weapon = winningclient;
00553 }
00554
00555 void BroadcastObjectiveCompletion(int team, int objective, int final, int client)
00556 {
00557 if (client != ENTITYNUM_NONE && g_entities[client].client && g_entities[client].client->sess.sessionTeam == team)
00558 {
00559 AddScore(&g_entities[client], g_entities[client].client->ps.origin, SIEGE_POINTS_OBJECTIVECOMPLETED);
00560 }
00561
00562 SiegeBroadcast_OBJECTIVECOMPLETE(team, client, objective);
00563
00564 }
00565
00566 void AddSiegeWinningTeamPoints(int team, int winner)
00567 {
00568 int i = 0;
00569 gentity_t *ent;
00570
00571 while (i < MAX_CLIENTS)
00572 {
00573 ent = &g_entities[i];
00574
00575 if (ent && ent->client && ent->client->sess.sessionTeam == team)
00576 {
00577 if (i == winner)
00578 {
00579 AddScore(ent, ent->client->ps.origin, SIEGE_POINTS_TEAMWONROUND+SIEGE_POINTS_FINALOBJECTIVECOMPLETED);
00580 }
00581 else
00582 {
00583 AddScore(ent, ent->client->ps.origin, SIEGE_POINTS_TEAMWONROUND);
00584 }
00585 }
00586
00587 i++;
00588 }
00589 }
00590
00591 void SiegeClearSwitchData(void)
00592 {
00593 memset(&g_siegePersistant, 0, sizeof(g_siegePersistant));
00594 trap_SiegePersSet(&g_siegePersistant);
00595 }
00596
00597 void SiegeDoTeamAssign(void)
00598 {
00599 int i = 0;
00600 gentity_t *ent;
00601
00602
00603 while (i < MAX_CLIENTS)
00604 {
00605 ent = &g_entities[i];
00606
00607 if (ent->inuse && ent->client &&
00608 ent->client->pers.connected == CON_CONNECTED)
00609 {
00610 if (ent->client->sess.siegeDesiredTeam == SIEGETEAM_TEAM1)
00611 {
00612 ent->client->sess.siegeDesiredTeam = SIEGETEAM_TEAM2;
00613 }
00614 else if (ent->client->sess.siegeDesiredTeam == SIEGETEAM_TEAM2)
00615 {
00616 ent->client->sess.siegeDesiredTeam = SIEGETEAM_TEAM1;
00617 }
00618
00619 if (ent->client->sess.sessionTeam == SIEGETEAM_TEAM1)
00620 {
00621 SetTeamQuick(ent, SIEGETEAM_TEAM2, qfalse);
00622 }
00623 else if (ent->client->sess.sessionTeam == SIEGETEAM_TEAM2)
00624 {
00625 SetTeamQuick(ent, SIEGETEAM_TEAM1, qfalse);
00626 }
00627 }
00628 i++;
00629 }
00630 }
00631
00632 void SiegeTeamSwitch(int winTeam, int winTime)
00633 {
00634 trap_SiegePersGet(&g_siegePersistant);
00635 if (g_siegePersistant.beatingTime)
00636 {
00637
00638
00639
00640
00641 SiegeSetCompleteData(winTeam);
00642 SiegeClearSwitchData();
00643 }
00644 else
00645 {
00646 g_siegePersistant.beatingTime = qtrue;
00647 g_siegePersistant.lastTeam = winTeam;
00648 g_siegePersistant.lastTime = winTime;
00649
00650 trap_SiegePersSet(&g_siegePersistant);
00651 }
00652 }
00653
00654 void SiegeRoundComplete(int winningteam, int winningclient)
00655 {
00656 vec3_t nomatter;
00657 char teamstr[1024];
00658 int originalWinningClient = winningclient;
00659
00660
00661
00662 if (winningclient != ENTITYNUM_NONE && g_entities[winningclient].client &&
00663 g_entities[winningclient].client->sess.sessionTeam != winningteam)
00664 {
00665 winningclient = ENTITYNUM_NONE;
00666 }
00667
00668 VectorClear(nomatter);
00669
00670 SiegeBroadcast_ROUNDOVER(winningteam, winningclient);
00671
00672 AddSiegeWinningTeamPoints(winningteam, winningclient);
00673
00674
00675
00676 if (winningteam == SIEGETEAM_TEAM1)
00677 {
00678 Com_sprintf(teamstr, sizeof(teamstr), team1);
00679 }
00680 else
00681 {
00682 Com_sprintf(teamstr, sizeof(teamstr), team2);
00683 }
00684
00685 trap_SetConfigstring(CS_SIEGE_STATE, va("3|%i", level.time));
00686 gSiegeRoundBegun = qfalse;
00687 gSiegeRoundEnded = qtrue;
00688 gSiegeRoundWinningTeam = winningteam;
00689
00690 if (BG_SiegeGetValueGroup(siege_info, teamstr, gParseObjectives))
00691 {
00692 if (!BG_SiegeGetPairedValue(gParseObjectives, "roundover_target", teamstr))
00693 {
00694 LogExit( "Objectives completed" );
00695 return;
00696 }
00697
00698 if (originalWinningClient == ENTITYNUM_NONE)
00699 {
00700 int i = 0;
00701 gentity_t *ent;
00702
00703 while (i < MAX_CLIENTS)
00704 {
00705 ent = &g_entities[i];
00706
00707 if (ent->inuse)
00708 {
00709 originalWinningClient = ent->s.number;
00710 break;
00711 }
00712
00713 i++;
00714 }
00715 }
00716 G_UseTargets2(&g_entities[originalWinningClient], &g_entities[originalWinningClient], teamstr);
00717 }
00718
00719 if (g_siegeTeamSwitch.integer &&
00720 (imperial_time_limit || rebel_time_limit))
00721 {
00722 int time = 0;
00723 if (imperial_time_limit)
00724 {
00725 time = imperial_time_limit-(gImperialCountdown-level.time);
00726 }
00727 else if (rebel_time_limit)
00728 {
00729 time = rebel_time_limit-(gRebelCountdown-level.time);
00730 }
00731
00732 if (time < 1)
00733 {
00734 time = 1;
00735 }
00736 SiegeTeamSwitch(winningteam, time);
00737 }
00738 else
00739 {
00740 SiegeClearSwitchData();
00741 }
00742 }
00743
00744 void G_ValidateSiegeClassForTeam(gentity_t *ent, int team)
00745 {
00746 siegeClass_t *scl;
00747 siegeTeam_t *stm;
00748 int newClassIndex = -1;
00749 if (ent->client->siegeClass == -1)
00750 {
00751 return;
00752 }
00753
00754 scl = &bgSiegeClasses[ent->client->siegeClass];
00755
00756 stm = BG_SiegeFindThemeForTeam(team);
00757 if (stm)
00758 {
00759 int i = 0;
00760
00761 while (i < stm->numClasses)
00762 {
00763 if (stm->classes[i])
00764 {
00765 if (!Q_stricmp(scl->name, stm->classes[i]->name))
00766 {
00767 return;
00768 }
00769 if (stm->classes[i]->playerClass == scl->playerClass ||
00770 newClassIndex == -1)
00771 {
00772 newClassIndex = i;
00773 }
00774 }
00775 i++;
00776 }
00777
00778 if (newClassIndex != -1)
00779 {
00780 ent->client->siegeClass = BG_SiegeFindClassIndexByName(stm->classes[newClassIndex]->name);
00781 strcpy(ent->client->sess.siegeClass, stm->classes[newClassIndex]->name);
00782 }
00783 }
00784 }
00785
00786
00787 void SetTeamQuick(gentity_t *ent, int team, qboolean doBegin)
00788 {
00789 char userinfo[MAX_INFO_STRING];
00790
00791 trap_GetUserinfo( ent->s.number, userinfo, sizeof( userinfo ) );
00792
00793 if (g_gametype.integer == GT_SIEGE)
00794 {
00795 G_ValidateSiegeClassForTeam(ent, team);
00796 }
00797
00798 ent->client->sess.sessionTeam = team;
00799
00800 if (team == TEAM_SPECTATOR)
00801 {
00802 ent->client->sess.spectatorState = SPECTATOR_FREE;
00803 Info_SetValueForKey(userinfo, "team", "s");
00804 }
00805 else
00806 {
00807 ent->client->sess.spectatorState = SPECTATOR_NOT;
00808 if (team == TEAM_RED)
00809 {
00810 Info_SetValueForKey(userinfo, "team", "r");
00811 }
00812 else if (team == TEAM_BLUE)
00813 {
00814 Info_SetValueForKey(userinfo, "team", "b");
00815 }
00816 else
00817 {
00818 Info_SetValueForKey(userinfo, "team", "?");
00819 }
00820 }
00821
00822 trap_SetUserinfo( ent->s.number, userinfo );
00823
00824 ent->client->sess.spectatorClient = 0;
00825
00826 ent->client->pers.teamState.state = TEAM_BEGIN;
00827
00828 ClientUserinfoChanged( ent->s.number );
00829
00830 if (doBegin)
00831 {
00832 ClientBegin( ent->s.number, qfalse );
00833 }
00834 }
00835
00836 void SiegeRespawn(gentity_t *ent)
00837 {
00838 gentity_t *tent;
00839
00840 if (ent->client->sess.sessionTeam != ent->client->sess.siegeDesiredTeam)
00841 {
00842 SetTeamQuick(ent, ent->client->sess.siegeDesiredTeam, qtrue);
00843 }
00844 else
00845 {
00846 ClientSpawn(ent);
00847
00848 tent = G_TempEntity( ent->client->ps.origin, EV_PLAYER_TELEPORT_IN );
00849 tent->s.clientNum = ent->s.clientNum;
00850 }
00851 }
00852
00853 void SiegeBeginRound(int entNum)
00854 {
00855 char targname[1024];
00856
00857 if (!g_preroundState)
00858 {
00859 int i = 0;
00860 gentity_t *ent;
00861 qboolean spawnEnt = qfalse;
00862
00863
00864 while (i < MAX_CLIENTS)
00865 {
00866 ent = &g_entities[i];
00867
00868 if (ent->inuse && ent->client)
00869 {
00870 if (ent->client->sess.sessionTeam != TEAM_SPECTATOR &&
00871 !(ent->client->ps.pm_flags & PMF_FOLLOW))
00872 {
00873 spawnEnt = qtrue;
00874 }
00875 else if (ent->client->sess.sessionTeam == TEAM_SPECTATOR &&
00876 (ent->client->sess.siegeDesiredTeam == TEAM_RED ||
00877 ent->client->sess.siegeDesiredTeam == TEAM_BLUE))
00878 {
00879 spawnEnt = qtrue;
00880 }
00881 }
00882
00883 if (spawnEnt)
00884 {
00885 SiegeRespawn(ent);
00886
00887 spawnEnt = qfalse;
00888 }
00889 i++;
00890 }
00891 }
00892
00893
00894 if (BG_SiegeGetPairedValue(siege_info, "roundbegin_target", targname))
00895 {
00896 if (targname[0])
00897 {
00898 G_UseTargets2(&g_entities[entNum], &g_entities[entNum], targname);
00899 }
00900 }
00901
00902 trap_SetConfigstring(CS_SIEGE_STATE, va("0|%i", level.time));
00903 }
00904
00905 void SiegeCheckTimers(void)
00906 {
00907 int i=0;
00908 gentity_t *ent;
00909 int numTeam1 = 0;
00910 int numTeam2 = 0;
00911
00912 if (g_gametype.integer != GT_SIEGE)
00913 {
00914 return;
00915 }
00916
00917 if (level.intermissiontime)
00918 {
00919 return;
00920 }
00921
00922 if (gSiegeRoundEnded)
00923 {
00924 return;
00925 }
00926
00927 if (!gSiegeRoundBegun)
00928 {
00929 i = 0;
00930
00931 while (i < MAX_CLIENTS)
00932 {
00933 ent = &g_entities[i];
00934
00935 if (ent && ent->inuse && ent->client &&
00936 ent->client->pers.connected == CON_CONNECTED &&
00937 ent->client->sess.siegeDesiredTeam == SIEGETEAM_TEAM1)
00938 {
00939 numTeam1++;
00940 }
00941 i++;
00942 }
00943
00944 i = 0;
00945
00946 while (i < MAX_CLIENTS)
00947 {
00948 ent = &g_entities[i];
00949
00950 if (ent && ent->inuse && ent->client &&
00951 ent->client->pers.connected == CON_CONNECTED &&
00952 ent->client->sess.siegeDesiredTeam == SIEGETEAM_TEAM2)
00953 {
00954 numTeam2++;
00955 }
00956 i++;
00957 }
00958
00959 if (g_siegeTeamSwitch.integer &&
00960 g_siegePersistant.beatingTime)
00961 {
00962 gImperialCountdown = level.time + g_siegePersistant.lastTime;
00963 gRebelCountdown = level.time + g_siegePersistant.lastTime;
00964 }
00965 else
00966 {
00967 gImperialCountdown = level.time + imperial_time_limit;
00968 gRebelCountdown = level.time + rebel_time_limit;
00969 }
00970 }
00971
00972 if (imperial_time_limit)
00973 {
00974 if (gImperialCountdown < level.time)
00975 {
00976 SiegeRoundComplete(SIEGETEAM_TEAM2, ENTITYNUM_NONE);
00977 imperial_time_limit = 0;
00978 return;
00979 }
00980 }
00981
00982 if (rebel_time_limit)
00983 {
00984 if (gRebelCountdown < level.time)
00985 {
00986 SiegeRoundComplete(SIEGETEAM_TEAM1, ENTITYNUM_NONE);
00987 rebel_time_limit = 0;
00988 return;
00989 }
00990 }
00991
00992 if (!gSiegeRoundBegun)
00993 {
00994 if (!numTeam1 || !numTeam2)
00995 {
00996 gSiegeBeginTime = level.time + SIEGE_ROUND_BEGIN_TIME;
00997 trap_SetConfigstring(CS_SIEGE_STATE, "1");
00998 }
00999 else if (gSiegeBeginTime < level.time)
01000 {
01001 gSiegeRoundBegun = qtrue;
01002 SiegeBeginRound(i);
01003 }
01004 else if (gSiegeBeginTime > (level.time + SIEGE_ROUND_BEGIN_TIME))
01005 {
01006 gSiegeBeginTime = level.time + SIEGE_ROUND_BEGIN_TIME;
01007 }
01008 else
01009 {
01010 trap_SetConfigstring(CS_SIEGE_STATE, va("2|%i", gSiegeBeginTime - SIEGE_ROUND_BEGIN_TIME));
01011 }
01012 }
01013 }
01014
01015 void SiegeObjectiveCompleted(int team, int objective, int final, int client)
01016 {
01017 int goals_completed, goals_required;
01018
01019 if (gSiegeRoundEnded)
01020 {
01021 return;
01022 }
01023
01024
01025 G_SiegeSetObjectiveComplete(team, objective, qfalse);
01026
01027 if (final != -1)
01028 {
01029 if (team == SIEGETEAM_TEAM1)
01030 {
01031 imperial_goals_completed++;
01032 }
01033 else
01034 {
01035 rebel_goals_completed++;
01036 }
01037 }
01038
01039 if (team == SIEGETEAM_TEAM1)
01040 {
01041 goals_completed = imperial_goals_completed;
01042 goals_required = imperial_goals_required;
01043 }
01044 else
01045 {
01046 goals_completed = rebel_goals_completed;
01047 goals_required = rebel_goals_required;
01048 }
01049
01050 if (final == 1 || goals_completed >= goals_required)
01051 {
01052 SiegeRoundComplete(team, client);
01053 }
01054 else
01055 {
01056 BroadcastObjectiveCompletion(team, objective, final, client);
01057 }
01058 }
01059
01060 void siegeTriggerUse(gentity_t *ent, gentity_t *other, gentity_t *activator)
01061 {
01062 char teamstr[64];
01063 char objectivestr[64];
01064 char desiredobjective[MAX_SIEGE_INFO_SIZE];
01065 int clUser = ENTITYNUM_NONE;
01066 int final = 0;
01067 int i = 0;
01068
01069 if (!siege_valid)
01070 {
01071 return;
01072 }
01073
01074 if (!(ent->s.eFlags & EF_RADAROBJECT))
01075 {
01076 ent->s.eFlags |= EF_RADAROBJECT;
01077 return;
01078 }
01079
01080 if (activator && activator->client)
01081 {
01082 clUser = activator->s.number;
01083 }
01084
01085 if (ent->side == SIEGETEAM_TEAM1)
01086 {
01087 Com_sprintf(teamstr, sizeof(teamstr), team1);
01088 }
01089 else
01090 {
01091 Com_sprintf(teamstr, sizeof(teamstr), team2);
01092 }
01093
01094 if (BG_SiegeGetValueGroup(siege_info, teamstr, gParseObjectives))
01095 {
01096 Com_sprintf(objectivestr, sizeof(objectivestr), "Objective%i", ent->objective);
01097
01098 if (BG_SiegeGetValueGroup(gParseObjectives, objectivestr, desiredobjective))
01099 {
01100 if (BG_SiegeGetPairedValue(desiredobjective, "final", teamstr))
01101 {
01102 final = atoi(teamstr);
01103 }
01104
01105 if (BG_SiegeGetPairedValue(desiredobjective, "target", teamstr))
01106 {
01107 while (teamstr[i])
01108 {
01109 if (teamstr[i] == '\r' ||
01110 teamstr[i] == '\n')
01111 {
01112 teamstr[i] = '\0';
01113 }
01114
01115 i++;
01116 }
01117 UseSiegeTarget(other, activator, teamstr);
01118 }
01119
01120 if (ent->target && ent->target[0])
01121 {
01122 UseSiegeTarget(other, activator, ent->target);
01123 }
01124
01125 SiegeObjectiveCompleted(ent->side, ent->objective, final, clUser);
01126 }
01127 }
01128 }
01129
01130
01131
01132
01133
01134
01135
01136
01137 void SP_info_siege_objective (gentity_t *ent)
01138 {
01139 char* s;
01140
01141 if (!siege_valid || g_gametype.integer != GT_SIEGE)
01142 {
01143 G_FreeEntity(ent);
01144 return;
01145 }
01146
01147 ent->use = siegeTriggerUse;
01148 G_SpawnInt( "objective", "0", &ent->objective);
01149 G_SpawnInt( "side", "0", &ent->side);
01150
01151 if (!ent->objective || !ent->side)
01152 {
01153 G_FreeEntity(ent);
01154 G_Printf("ERROR: info_siege_objective without an objective or side value\n");
01155 return;
01156 }
01157
01158
01159 if (!(ent->spawnflags & SIEGEITEM_STARTOFFRADAR))
01160 {
01161 ent->s.eFlags |= EF_RADAROBJECT;
01162 }
01163
01164
01165 ent->r.svFlags |= SVF_BROADCAST;
01166
01167 G_SpawnString( "icon", "", &s );
01168
01169 if (s && s[0])
01170 {
01171
01172
01173 ent->s.genericenemyindex = G_IconIndex(s);
01174 }
01175
01176 ent->s.brokenLimbs = ent->side;
01177 ent->s.frame = ent->objective;
01178 trap_LinkEntity(ent);
01179 }
01180
01181
01182 void SiegeIconUse(gentity_t *ent, gentity_t *other, gentity_t *activator)
01183 {
01184 if (ent->s.eFlags & EF_RADAROBJECT)
01185 {
01186 ent->s.eFlags &= ~EF_RADAROBJECT;
01187 ent->r.svFlags &= ~SVF_BROADCAST;
01188 }
01189 else
01190 {
01191 ent->s.eFlags |= EF_RADAROBJECT;
01192 ent->r.svFlags |= SVF_BROADCAST;
01193 }
01194 }
01195
01196
01197
01198
01199
01200
01201
01202
01203 void SP_info_siege_radaricon (gentity_t *ent)
01204 {
01205 char* s;
01206 int i;
01207
01208 if (!siege_valid || g_gametype.integer != GT_SIEGE)
01209 {
01210 G_FreeEntity(ent);
01211 return;
01212 }
01213
01214 G_SpawnInt("startoff", "0", &i);
01215
01216 if (!i)
01217 {
01218 ent->s.eFlags |= EF_RADAROBJECT;
01219 ent->r.svFlags |= SVF_BROADCAST;
01220 }
01221
01222 G_SpawnString( "icon", "", &s );
01223 if (!s || !s[0])
01224 {
01225 Com_Error(ERR_DROP, "misc_siege_radaricon without an icon");
01226 return;
01227 }
01228
01229 ent->use = SiegeIconUse;
01230
01231 ent->s.genericenemyindex = G_IconIndex(s);
01232
01233 trap_LinkEntity(ent);
01234 }
01235
01236 void decompTriggerUse(gentity_t *ent, gentity_t *other, gentity_t *activator)
01237 {
01238 int final = 0;
01239 char teamstr[1024];
01240 char objectivestr[64];
01241 char desiredobjective[MAX_SIEGE_INFO_SIZE];
01242
01243 if (gSiegeRoundEnded)
01244 {
01245 return;
01246 }
01247
01248 if (!G_SiegeGetCompletionStatus(ent->side, ent->objective))
01249 {
01250 return;
01251 }
01252
01253
01254 G_SiegeSetObjectiveComplete(ent->side, ent->objective, qtrue);
01255
01256
01257 if (ent->side == SIEGETEAM_TEAM1)
01258 {
01259 Com_sprintf(teamstr, sizeof(teamstr), team1);
01260 }
01261 else
01262 {
01263 Com_sprintf(teamstr, sizeof(teamstr), team2);
01264 }
01265
01266 if (BG_SiegeGetValueGroup(siege_info, teamstr, gParseObjectives))
01267 {
01268 Com_sprintf(objectivestr, sizeof(objectivestr), "Objective%i", ent->objective);
01269
01270 if (BG_SiegeGetValueGroup(gParseObjectives, objectivestr, desiredobjective))
01271 {
01272 if (BG_SiegeGetPairedValue(desiredobjective, "final", teamstr))
01273 {
01274 final = atoi(teamstr);
01275 }
01276 }
01277 }
01278
01279
01280 if (final != -1)
01281 {
01282 if (ent->side == SIEGETEAM_TEAM1)
01283 {
01284 imperial_goals_completed--;
01285 }
01286 else
01287 {
01288 rebel_goals_completed--;
01289 }
01290 }
01291 }
01292
01293
01294
01295
01296
01297 void SP_info_siege_decomplete (gentity_t *ent)
01298 {
01299 if (!siege_valid || g_gametype.integer != GT_SIEGE)
01300 {
01301 G_FreeEntity(ent);
01302 return;
01303 }
01304
01305 ent->use = decompTriggerUse;
01306 G_SpawnInt( "objective", "0", &ent->objective);
01307 G_SpawnInt( "side", "0", &ent->side);
01308
01309 if (!ent->objective || !ent->side)
01310 {
01311 G_FreeEntity(ent);
01312 G_Printf("ERROR: info_siege_objective_decomplete without an objective or side value\n");
01313 return;
01314 }
01315 }
01316
01317 void siegeEndUse(gentity_t *ent, gentity_t *other, gentity_t *activator)
01318 {
01319 LogExit("Round ended");
01320 }
01321
01322
01323
01324
01325 void SP_target_siege_end (gentity_t *ent)
01326 {
01327 if (!siege_valid || g_gametype.integer != GT_SIEGE)
01328 {
01329 G_FreeEntity(ent);
01330 return;
01331 }
01332
01333 ent->use = siegeEndUse;
01334 }
01335
01336 #define SIEGE_ITEM_RESPAWN_TIME 20000
01337
01338 void SiegeItemRemoveOwner(gentity_t *ent, gentity_t *carrier)
01339 {
01340 ent->genericValue2 = 0;
01341
01342 ent->genericValue8 = ENTITYNUM_NONE;
01343
01344 if (carrier)
01345 {
01346 carrier->client->holdingObjectiveItem = 0;
01347 carrier->r.svFlags &= ~SVF_BROADCAST;
01348 }
01349 }
01350
01351 static void SiegeItemRespawnEffect(gentity_t *ent, vec3_t newOrg)
01352 {
01353 vec3_t upAng;
01354
01355 if (ent->target5 && ent->target5[0])
01356 {
01357 G_UseTargets2(ent, ent, ent->target5);
01358 }
01359
01360 if (!ent->genericValue10)
01361 {
01362 return;
01363 }
01364
01365 VectorSet(upAng, 0, 0, 1);
01366
01367
01368 G_PlayEffectID(ent->genericValue10, ent->r.currentOrigin, upAng);
01369 G_PlayEffectID(ent->genericValue10, newOrg, upAng);
01370 }
01371
01372 static void SiegeItemRespawnOnOriginalSpot(gentity_t *ent, gentity_t *carrier)
01373 {
01374 SiegeItemRespawnEffect(ent, ent->pos1);
01375 G_SetOrigin(ent, ent->pos1);
01376 SiegeItemRemoveOwner(ent, carrier);
01377
01378
01379 ent->s.time2 = 0;
01380 }
01381
01382 void SiegeItemThink(gentity_t *ent)
01383 {
01384 gentity_t *carrier = NULL;
01385
01386 if (ent->genericValue12)
01387 {
01388 if (ent->health > 0 && ent->health < ent->maxHealth && ent->genericValue14 < level.time)
01389 {
01390 ent->genericValue14 = level.time + ent->genericValue13;
01391 ent->health += ent->genericValue12;
01392 if (ent->health > ent->maxHealth)
01393 {
01394 ent->health = ent->maxHealth;
01395 }
01396 }
01397 }
01398
01399 if (ent->genericValue8 != ENTITYNUM_NONE)
01400 {
01401 carrier = &g_entities[ent->genericValue8];
01402
01403 if (carrier->inuse && carrier->client)
01404 {
01405 VectorCopy(carrier->client->ps.origin, ent->r.currentOrigin);
01406 trap_LinkEntity(ent);
01407 }
01408 }
01409 else if (ent->genericValue1)
01410 {
01411 G_RunExPhys(ent, ent->radius, ent->mass, ent->random, qfalse, NULL, 0);
01412 }
01413
01414
01415 if (ent->genericValue8 < MAX_CLIENTS)
01416 {
01417 ent->s.boltToPlayer = ent->genericValue8+1;
01418 }
01419 else
01420 {
01421 ent->s.boltToPlayer = 0;
01422 }
01423
01424
01425 if (carrier)
01426 {
01427 gentity_t *carrier = &g_entities[ent->genericValue8];
01428
01429
01430
01431 if (!carrier->inuse || !carrier->client ||
01432 (carrier->client->sess.sessionTeam != SIEGETEAM_TEAM1 && carrier->client->sess.sessionTeam != SIEGETEAM_TEAM2) ||
01433 (carrier->client->ps.pm_flags & PMF_FOLLOW))
01434 {
01435 SiegeItemRespawnOnOriginalSpot(ent, NULL);
01436 }
01437 else if (carrier->health < 1)
01438 {
01439 if (ent->target6 && ent->target6[0])
01440 {
01441 G_UseTargets2(ent, ent, ent->target6);
01442 }
01443
01444 if ( trap_PointContents(carrier->client->ps.origin, carrier->s.number) & CONTENTS_NODROP )
01445 {
01446 SiegeItemRespawnOnOriginalSpot(ent, carrier);
01447 }
01448 else
01449 {
01450 G_SetOrigin(ent, carrier->client->ps.origin);
01451 ent->epVelocity[0] = Q_irand(-80, 80);
01452 ent->epVelocity[1] = Q_irand(-80, 80);
01453 ent->epVelocity[2] = Q_irand(40, 80);
01454
01455
01456
01457 ent->genericValue9 = level.time + SIEGE_ITEM_RESPAWN_TIME;
01458
01459 SiegeItemRemoveOwner(ent, carrier);
01460 }
01461 }
01462 }
01463
01464 if (ent->genericValue9 && ent->genericValue9 < level.time)
01465 {
01466 SiegeItemRespawnEffect(ent, ent->pos1);
01467 G_SetOrigin(ent, ent->pos1);
01468 ent->genericValue9 = 0;
01469
01470
01471 ent->s.time2 = 0;
01472 }
01473
01474 ent->nextthink = level.time + FRAMETIME/2;
01475 }
01476
01477 void SiegeItemTouch( gentity_t *self, gentity_t *other, trace_t *trace )
01478 {
01479 if (!other || !other->inuse ||
01480 !other->client || other->s.eType == ET_NPC)
01481 {
01482 if (trace && trace->startsolid)
01483 {
01484 vec3_t escapePos;
01485 VectorCopy(self->r.currentOrigin, escapePos);
01486 escapePos[2] += 1.0f;
01487
01488
01489 G_SetOrigin(self, escapePos);
01490 }
01491 return;
01492 }
01493
01494 if (other->health < 1)
01495 {
01496 return;
01497 }
01498
01499 if (other->client->holdingObjectiveItem)
01500 {
01501 return;
01502 }
01503
01504 if ( other->client->ps.pm_type == PM_SPECTATOR )
01505 {
01506 return;
01507 }
01508
01509 if (self->genericValue2)
01510 {
01511 return;
01512 }
01513
01514 if (self->genericValue6 == other->client->sess.sessionTeam)
01515 {
01516 return;
01517 }
01518
01519 if (!gSiegeRoundBegun)
01520 {
01521 return;
01522 }
01523
01524 if (self->noise_index)
01525 {
01526 G_Sound(other, CHAN_AUTO, self->noise_index);
01527 }
01528
01529 self->genericValue2 = 1;
01530
01531 other->client->holdingObjectiveItem = self->s.number;
01532 other->r.svFlags |= SVF_BROADCAST;
01533 self->genericValue8 = other->s.number;
01534
01535 self->genericValue9 = 0;
01536
01537 if (self->target2 && self->target2[0] && (!self->genericValue4 || !self->genericValue5))
01538 {
01539 G_UseTargets2(self, self, self->target2);
01540 self->genericValue5 = 1;
01541 }
01542
01543
01544 self->s.time2 = 0xFFFFFFFF;
01545 }
01546
01547 void SiegeItemPain(gentity_t *self, gentity_t *attacker, int damage)
01548 {
01549
01550 self->s.time2 = level.time;
01551 }
01552
01553 void SiegeItemDie( gentity_t *self, gentity_t *inflictor, gentity_t *attacker, int damage, int meansOfDeath )
01554 {
01555 self->takedamage = qfalse;
01556
01557 if (self->genericValue3)
01558 {
01559 vec3_t upAng;
01560
01561 VectorSet(upAng, 0, 0, 1);
01562 G_PlayEffectID(self->genericValue3, self->r.currentOrigin, upAng);
01563 }
01564
01565 self->neverFree = qfalse;
01566 self->think = G_FreeEntity;
01567 self->nextthink = level.time;
01568
01569
01570 if (self->target4 && self->target4[0])
01571 {
01572 G_UseTargets2(self, self, self->target4);
01573 }
01574 }
01575
01576 void SiegeItemUse(gentity_t *ent, gentity_t *other, gentity_t *activator)
01577 {
01578 if (ent->spawnflags & SIEGEITEM_STARTOFFRADAR)
01579 {
01580 ent->s.eFlags |= EF_RADAROBJECT;
01581
01582 if (!(ent->s.eFlags & EF_NODRAW))
01583 {
01584 return;
01585 }
01586 }
01587 else
01588 {
01589 ent->s.eFlags |= EF_RADAROBJECT;
01590 }
01591
01592 if (ent->genericValue11 || !ent->takedamage)
01593 {
01594 ent->r.contents = CONTENTS_TRIGGER;
01595 ent->clipmask = CONTENTS_SOLID|CONTENTS_TERRAIN;
01596 if (ent->genericValue11)
01597 {
01598 ent->touch = SiegeItemTouch;
01599 }
01600 }
01601 else
01602 {
01603 ent->r.contents = MASK_PLAYERSOLID;
01604 ent->clipmask = MASK_PLAYERSOLID;
01605 }
01606
01607 ent->think = SiegeItemThink;
01608 ent->nextthink = level.time + FRAMETIME/2;
01609
01610
01611 ent->s.eFlags &= ~EF_NODRAW;
01612
01613 if (ent->paintarget && ent->paintarget[0])
01614 {
01615 gentity_t *targ = G_Find (NULL, FOFS(targetname), ent->paintarget);
01616
01617 if (targ && targ->inuse)
01618 {
01619 G_SetOrigin(ent, targ->r.currentOrigin);
01620 trap_LinkEntity(ent);
01621 }
01622 }
01623 }
01624
01625
01626
01627
01628
01629
01630
01631
01632
01633
01634
01635
01636
01637
01638
01639
01640
01641
01642
01643
01644
01645
01646
01647
01648
01649
01650
01651
01652
01653
01654
01655
01656
01657
01658
01659
01660
01661
01662
01663
01664
01665
01666
01667
01668
01669
01670
01671
01672
01673
01674
01675
01676 void SP_misc_siege_item (gentity_t *ent)
01677 {
01678 int canpickup;
01679 int noradar;
01680 char *s;
01681
01682 if (!siege_valid || g_gametype.integer != GT_SIEGE)
01683 {
01684 G_FreeEntity(ent);
01685 return;
01686 }
01687
01688 if (!ent->model || !ent->model[0])
01689 {
01690 G_Error("You must specify a model for misc_siege_item types.");
01691 }
01692
01693 G_SpawnInt("canpickup", "1", &canpickup);
01694 G_SpawnInt("usephysics", "1", &ent->genericValue1);
01695
01696 if (ent->genericValue1)
01697 {
01698 ent->s.eFlags |= EF_CLIENTSMOOTH;
01699 }
01700
01701 G_SpawnInt("noradar", "0", &noradar);
01702
01703 if (!noradar && !(ent->spawnflags & SIEGEITEM_STARTOFFRADAR))
01704 {
01705 ent->s.eFlags |= EF_RADAROBJECT;
01706 }
01707
01708
01709 ent->r.svFlags |= SVF_BROADCAST;
01710
01711 G_SpawnInt("pickuponlyonce", "1", &ent->genericValue4);
01712
01713 G_SpawnInt("teamnotouch", "0", &ent->genericValue6);
01714 G_SpawnInt("teamnocomplete", "0", &ent->genericValue7);
01715
01716
01717 G_SpawnFloat("mass", "0.09", &ent->mass);
01718 G_SpawnFloat("gravity", "3.0", &ent->radius);
01719 G_SpawnFloat("bounce", "1.3", &ent->random);
01720
01721 G_SpawnString( "pickupsound", "", &s );
01722
01723 if (s && s[0])
01724 {
01725 ent->noise_index = G_SoundIndex(s);
01726 }
01727
01728 G_SpawnString( "deathfx", "", &s );
01729
01730 if (s && s[0])
01731 {
01732 ent->genericValue3 = G_EffectIndex(s);
01733 }
01734
01735 G_SpawnString( "respawnfx", "", &s );
01736
01737 if (s && s[0])
01738 {
01739 ent->genericValue10 = G_EffectIndex(s);
01740 }
01741
01742 G_SpawnString( "icon", "", &s );
01743
01744 if (s && s[0])
01745 {
01746
01747
01748 ent->s.genericenemyindex = G_IconIndex(s);
01749 }
01750
01751 ent->s.modelindex = G_ModelIndex(ent->model);
01752
01753
01754 if (!Q_stricmp(&ent->model[strlen(ent->model) - 4], ".glm"))
01755 {
01756 ent->s.modelGhoul2 = 1;
01757 }
01758
01759 ent->s.eType = ET_GENERAL;
01760
01761
01762 G_SpawnVector("mins", "-16 -16 -24", ent->r.mins);
01763 G_SpawnVector("maxs", "16 16 32", ent->r.maxs);
01764
01765 VectorCopy(ent->s.origin, ent->pos1);
01766 G_SetOrigin(ent, ent->s.origin);
01767
01768 VectorCopy(ent->s.angles, ent->r.currentAngles);
01769 VectorCopy(ent->s.angles, ent->s.apos.trBase);
01770
01771 G_SpawnInt("forcelimit", "0", &ent->genericValue15);
01772
01773 if (ent->health > 0)
01774 {
01775 int t;
01776
01777 ent->pain = SiegeItemPain;
01778 ent->die = SiegeItemDie;
01779 ent->takedamage = qtrue;
01780
01781 G_SpawnInt( "showhealth", "0", &t );
01782 if (t)
01783 {
01784 ent->maxHealth = ent->health;
01785 G_ScaleNetHealth(ent);
01786
01787 G_SpawnInt( "health_chargeamt", "0", &ent->genericValue12);
01788 G_SpawnInt( "health_chargerate", "0", &ent->genericValue13);
01789 }
01790 }
01791 else
01792 {
01793 ent->takedamage = qfalse;
01794 }
01795
01796 if (ent->spawnflags & SIEGEITEM_STARTOFFRADAR)
01797 {
01798 ent->use = SiegeItemUse;
01799 }
01800 else if (ent->targetname && ent->targetname[0])
01801 {
01802 ent->s.eFlags |= EF_NODRAW;
01803 ent->genericValue11 = canpickup;
01804 ent->use = SiegeItemUse;
01805 ent->s.eFlags &= ~EF_RADAROBJECT;
01806 }
01807
01808 if ( (!ent->targetname || !ent->targetname[0]) ||
01809 (ent->spawnflags & SIEGEITEM_STARTOFFRADAR) )
01810 {
01811 if (canpickup || !ent->takedamage)
01812 {
01813 ent->r.contents = CONTENTS_TRIGGER;
01814 ent->clipmask = CONTENTS_SOLID|CONTENTS_TERRAIN;
01815 if (canpickup)
01816 {
01817 ent->touch = SiegeItemTouch;
01818 }
01819 }
01820 else
01821 {
01822 ent->r.contents = MASK_PLAYERSOLID;
01823 ent->clipmask = MASK_PLAYERSOLID;
01824 }
01825
01826 ent->think = SiegeItemThink;
01827 ent->nextthink = level.time + FRAMETIME/2;
01828 }
01829
01830 ent->genericValue8 = ENTITYNUM_NONE;
01831
01832 ent->neverFree = qtrue;
01833
01834 trap_LinkEntity(ent);
01835 }
01836
01837
01838
01839
01840
01841
01842
01843
01844
01845 void G_SiegeClientExData(gentity_t *msgTarg)
01846 {
01847 gentity_t *ent;
01848 int count = 0;
01849 int i = 0;
01850 char str[MAX_STRING_CHARS];
01851 char scratch[MAX_STRING_CHARS];
01852
01853 while (i < level.num_entities && count < MAX_EXDATA_ENTS_TO_SEND)
01854 {
01855 ent = &g_entities[i];
01856
01857 if (ent->inuse && ent->client && msgTarg->s.number != ent->s.number &&
01858 ent->s.eType == ET_PLAYER && msgTarg->client->sess.sessionTeam == ent->client->sess.sessionTeam &&
01859 trap_InPVS(msgTarg->client->ps.origin, ent->client->ps.origin))
01860 {
01861 if (count)
01862 {
01863 Q_strcat(str, sizeof(str), " ");
01864 }
01865 else
01866 {
01867 strcpy(str, "sxd ");
01868 }
01869
01870
01871 Com_sprintf(scratch, sizeof(scratch), "%i|%i|%i|%i", ent->s.number, ent->client->ps.stats[STAT_HEALTH],
01872 ent->client->ps.stats[STAT_MAX_HEALTH], ent->client->ps.ammo[weaponData[ent->client->ps.weapon].ammoIndex]);
01873 Q_strcat(str, sizeof(str), scratch);
01874 count++;
01875 }
01876 i++;
01877 }
01878
01879 if (!count)
01880 {
01881 return;
01882 }
01883
01884
01885 trap_SendServerCommand(msgTarg-g_entities, str);
01886 }