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