summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/cgame/cg_draw.c42
-rw-r--r--src/cgame/cg_local.h1
-rw-r--r--src/cgame/cg_weapons.c106
-rw-r--r--src/game/bg_misc.c10
-rw-r--r--src/game/bg_pmove.c6
-rw-r--r--src/game/bg_public.h6
-rw-r--r--src/game/g_active.c65
-rw-r--r--src/game/g_buildable.c37
-rw-r--r--src/ui/ui_local.h5
-rw-r--r--src/ui/ui_main.c79
10 files changed, 250 insertions, 107 deletions
diff --git a/src/cgame/cg_draw.c b/src/cgame/cg_draw.c
index 374c7a75..bc012338 100644
--- a/src/cgame/cg_draw.c
+++ b/src/cgame/cg_draw.c
@@ -899,15 +899,42 @@ CG_DrawPlayerHealthCross
*/
static void CG_DrawPlayerHealthCross( rectDef_t *rect, vec4_t color, qhandle_t shader )
{
- playerState_t *ps = &cg.snap->ps;
- int health = ps->stats[ STAT_HEALTH ];
-
- if( health < 10 )
+ if( ( cg.snap->ps.stats[ STAT_STATE ] & SS_HEALING_2X ) ||
+ ( cg.snap->ps.stats[ STAT_STATE ] & SS_HEALING_3X ) )
+ return;
+ if( cg.snap->ps.stats[ STAT_PTEAM ] == PTE_HUMANS &&
+ cg.snap->ps.stats[ STAT_HEALTH ] < 10 )
{
color[ 0 ] = 1.0f;
color[ 1 ] = color[ 2 ] = 0.0f;
}
+ if( cg.snap->ps.stats[ STAT_STATE ] & SS_HEALING_ACTIVE )
+ color[ 3 ] = 1.0f;
+
+ trap_R_SetColor( color );
+ CG_DrawPic( rect->x, rect->y, rect->w, rect->h, shader );
+ trap_R_SetColor( NULL );
+}
+
+static void CG_DrawPlayerHealthCross2( rectDef_t *rect, vec4_t color, qhandle_t shader )
+{
+ if( !( cg.snap->ps.stats[ STAT_STATE ] & SS_HEALING_2X ) )
+ return;
+ if( cg.snap->ps.stats[ STAT_STATE ] & SS_HEALING_ACTIVE )
+ color[ 3 ] = 1.0f;
+
+ trap_R_SetColor( color );
+ CG_DrawPic( rect->x, rect->y, rect->w, rect->h, shader );
+ trap_R_SetColor( NULL );
+}
+static void CG_DrawPlayerHealthCross3( rectDef_t *rect, vec4_t color, qhandle_t shader )
+{
+ if( !( cg.snap->ps.stats[ STAT_STATE ] & SS_HEALING_3X ) )
+ return;
+ if( cg.snap->ps.stats[ STAT_STATE ] & SS_HEALING_ACTIVE )
+ color[ 3 ] = 1.0f;
+
trap_R_SetColor( color );
CG_DrawPic( rect->x, rect->y, rect->w, rect->h, shader );
trap_R_SetColor( NULL );
@@ -2156,6 +2183,12 @@ void CG_OwnerDraw( float x, float y, float w, float h, float text_x,
case CG_PLAYER_HEALTH_CROSS:
CG_DrawPlayerHealthCross( &rect, color, shader );
break;
+ case CG_PLAYER_HEALTH_CROSS2:
+ CG_DrawPlayerHealthCross2( &rect, color, shader );
+ break;
+ case CG_PLAYER_HEALTH_CROSS3:
+ CG_DrawPlayerHealthCross3( &rect, color, shader );
+ break;
case CG_PLAYER_CLIPS_RING:
CG_DrawPlayerClipsRing( &rect, color, shader );
break;
@@ -2872,7 +2905,6 @@ static void CG_PainBlend( void )
return;
damage = cg.lastHealth - cg.snap->ps.stats[ STAT_HEALTH ];
-
if( damage < 0 )
damage = 0;
diff --git a/src/cgame/cg_local.h b/src/cgame/cg_local.h
index b47f7cc9..71e4a14c 100644
--- a/src/cgame/cg_local.h
+++ b/src/cgame/cg_local.h
@@ -1125,6 +1125,7 @@ typedef struct
float painBlendValue;
float painBlendTarget;
+ float healBlendValue;
int lastHealth;
int lastPredictedCommand;
diff --git a/src/cgame/cg_weapons.c b/src/cgame/cg_weapons.c
index 45318cf8..f4c8fbf8 100644
--- a/src/cgame/cg_weapons.c
+++ b/src/cgame/cg_weapons.c
@@ -869,6 +869,12 @@ void CG_AddPlayerWeapon( refEntity_t *parent, playerState_t *ps, centity_t *cent
trap_S_AddLoopingSound( cent->currentState.number, cent->lerpOrigin, vec3_origin, weapon->readySound );
}
+ // Lucifer cannon charge warning beep
+ if( weaponNum == WP_LUCIFER_CANNON &&
+ ( cent->currentState.eFlags & EF_WARN_CHARGE ) )
+ trap_S_AddLoopingSound( cent->currentState.number, cent->lerpOrigin,
+ vec3_origin, cgs.media.lCannonWarningSound );
+
if( !noGunModel )
{
CG_PositionEntityOnTag( &gun, parent, parent->hModel, "tag_weapon" );
@@ -1015,12 +1021,6 @@ void CG_AddViewWeapon( playerState_t *ps )
if( ( ps->stats[ STAT_BUILDABLE ] & ~SB_VALID_TOGGLEBIT ) > BA_NONE )
CG_GhostBuildable( ps->stats[ STAT_BUILDABLE ] & ~SB_VALID_TOGGLEBIT );
- // Lucifer cannon charge warning beep
- if( weapon == WP_LUCIFER_CANNON &&
- ps->stats[ STAT_MISC ] > LCANNON_TOTAL_CHARGE * 2 / 3 )
- trap_S_AddLoopingSound( ps->clientNum, ps->origin, vec3_origin,
- cgs.media.lCannonWarningSound );
-
// no gun if in third person view
if( cg.renderingThirdPerson )
return;
@@ -1165,22 +1165,12 @@ CG_DrawItemSelect
*/
void CG_DrawItemSelect( rectDef_t *rect, vec4_t color )
{
- int i;
- float x = rect->x;
- float y = rect->y;
- float width = rect->w;
- float height = rect->h;
- float iconWidth;
- float iconHeight;
- int items[ 64 ];
- int numItems = 0, selectedItem = 0;
- int length;
- int selectWindow;
- qboolean vertical;
- centity_t *cent;
+ centity_t *cent;
playerState_t *ps;
-
- int colinfo[ 64 ];
+ float x = rect->x, y = rect->y, width = rect->w, height = rect->h,
+ iconWidth, iconHeight;
+ int i, items[ 64 ], colinfo[ 64 ], numItems = 0, selectedItem = 0, length;
+ qboolean vertical;
cent = &cg_entities[ cg.snap->ps.clientNum ];
ps = &cg.snap->ps;
@@ -1201,23 +1191,7 @@ void CG_DrawItemSelect( rectDef_t *rect, vec4_t color )
// showing weapon select clears pickup item display, but not the blend blob
cg.itemPickupTime = 0;
- if( height > width )
- {
- vertical = qtrue;
- iconWidth = width * cgDC.aspectScale;
- iconHeight = width;
- length = height / ( width * cgDC.aspectScale );
- }
- else if( height <= width )
- {
- vertical = qfalse;
- iconWidth = height * cgDC.aspectScale;
- iconHeight = height;
- length = width / ( height * cgDC.aspectScale );
- }
-
- selectWindow = length / 2;
-
+ // put all weapons in the items list
for( i = WP_NONE + 1; i < WP_NUM_WEAPONS; i++ )
{
if( !BG_InventoryContainsWeapon( i, cg.snap->ps.stats ) )
@@ -1236,6 +1210,7 @@ void CG_DrawItemSelect( rectDef_t *rect, vec4_t color )
numItems++;
}
+ // put all upgrades in the weapons list
for( i = UP_NONE + 1; i < UP_NUM_UPGRADES; i++ )
{
if( !BG_InventoryContainsUpgrade( i, cg.snap->ps.stats ) )
@@ -1244,7 +1219,6 @@ void CG_DrawItemSelect( rectDef_t *rect, vec4_t color )
if( !BG_FindUsableForUpgrade ( i ) )
colinfo[ numItems ] = 2;
-
if( i == cg.weaponSelect - 32 )
selectedItem = numItems;
@@ -1253,42 +1227,60 @@ void CG_DrawItemSelect( rectDef_t *rect, vec4_t color )
numItems++;
}
+ // compute the length of the display window and determine orientation
+ vertical = height > width;
+ if( vertical )
+ {
+ iconWidth = width * cgDC.aspectScale;
+ iconHeight = width;
+ length = height / ( width * cgDC.aspectScale );
+ }
+ else
+ {
+ iconWidth = height * cgDC.aspectScale;
+ iconHeight = height;
+ length = width / ( height * cgDC.aspectScale );
+ }
+
+ // render icon ring
for( i = 0; i < length; i++ )
{
- int displacement = i - selectWindow;
- int item = displacement + selectedItem;
+ int item = i - length / 2 + selectedItem;
- if( ( item >= 0 ) && ( item < numItems ) )
+ if( item < 0 )
+ item += length;
+ else if( item >= length )
+ item -= length;
+ if( item >= 0 && item < numItems )
{
switch( colinfo[ item ] )
{
- case 0:
- color = colorCyan;
- break;
- case 1:
- color = colorRed;
- break;
- case 2:
- color = colorMdGrey;
- break;
+ case 0:
+ color = colorCyan;
+ break;
+ case 1:
+ color = colorRed;
+ break;
+ case 2:
+ color = colorMdGrey;
+ break;
}
color[3] = 0.5;
-
trap_R_SetColor( color );
if( items[ item ] <= 32 )
- CG_DrawPic( x, y, iconWidth, iconHeight, cg_weapons[ items[ item ] ].weaponIcon );
+ CG_DrawPic( x, y, iconWidth, iconHeight,
+ cg_weapons[ items[ item ] ].weaponIcon );
else if( items[ item ] > 32 )
- CG_DrawPic( x, y, iconWidth, iconHeight, cg_upgrades[ items[ item ] - 32 ].upgradeIcon );
-
- trap_R_SetColor( NULL );
+ CG_DrawPic( x, y, iconWidth, iconHeight,
+ cg_upgrades[ items[ item ] - 32 ].upgradeIcon );
}
-
if( vertical )
y += iconHeight;
else
x += iconWidth;
}
+ trap_R_SetColor( NULL );
}
diff --git a/src/game/bg_misc.c b/src/game/bg_misc.c
index 1686f172..a6c5e644 100644
--- a/src/game/bg_misc.c
+++ b/src/game/bg_misc.c
@@ -438,8 +438,8 @@ buildableAttributes_t bg_buildableList[ ] =
BA_H_MGTURRET, //int buildNum;
"mgturret", //char *buildName;
"Machinegun Turret", //char *humanName;
- "Automated base defense that is effective against fast moving targets, "
- "but does not cause much damage on its own and should always be "
+ "Automated base defense that is effective against large targets, "
+ "but is slow to begin firing and should always be "
"backed up by physical support.",
"team_human_mgturret", //char *entityName;
{ "models/buildables/mgturret/turret_base.md3",
@@ -480,9 +480,9 @@ buildableAttributes_t bg_buildableList[ ] =
BA_H_TESLAGEN, //int buildNum;
"tesla", //char *buildName;
"Tesla Generator", //char *humanName;
- "A structure equipped with a strong electrical attack that always "
- "hits its target. It is useful against larger aliens "
- "and for consolidating basic defense.",
+ "A structure equipped with a strong electrical attack that fires "
+ "instantly and always hits its target. It is effective against smaller "
+ "aliens and for consolidating basic defense.",
"team_human_tesla", //char *entityName;
{ "models/buildables/tesla/tesla.md3", 0, 0, 0 },
1.0f, //float modelScale;
diff --git a/src/game/bg_pmove.c b/src/game/bg_pmove.c
index 45cf89e0..a80bb5ab 100644
--- a/src/game/bg_pmove.c
+++ b/src/game/bg_pmove.c
@@ -2783,6 +2783,12 @@ static void PM_Weapon( void )
qboolean attack2 = qfalse;
qboolean attack3 = qfalse;
+ // Set overcharging flag so other players can hear warning
+ pm->ps->eFlags &= ~EF_WARN_CHARGE;
+ if( pm->ps->weapon == WP_LUCIFER_CANNON &&
+ pm->ps->stats[ STAT_MISC ] > LCANNON_TOTAL_CHARGE * 2 / 3 )
+ pm->ps->eFlags |= EF_WARN_CHARGE;
+
// don't allow attack until all buttons are up
if( pm->ps->pm_flags & PMF_RESPAWNED )
return;
diff --git a/src/game/bg_public.h b/src/game/bg_public.h
index ecc284e3..6a23595e 100644
--- a/src/game/bg_public.h
+++ b/src/game/bg_public.h
@@ -244,8 +244,10 @@ typedef enum
#define SS_BOOSTED 0x00000200
#define SS_SLOWLOCKED 0x00000400
#define SS_POISONCLOUDED 0x00000800
-#define SS_MEDKIT_ACTIVE 0x00001000
-#define SS_CHARGING 0x00002000
+#define SS_CHARGING 0x00001000
+#define SS_HEALING_ACTIVE 0x00002000 // medkit for Humans, creep for Aliens
+#define SS_HEALING_2X 0x00004000 // double healing rate (for HUD)
+#define SS_HEALING_3X 0x00008000 // triple healing rate (for HUD)
#define SB_VALID_TOGGLEBIT 0x00004000
diff --git a/src/game/g_active.c b/src/game/g_active.c
index 4e7134e2..ba1e28c8 100644
--- a/src/game/g_active.c
+++ b/src/game/g_active.c
@@ -669,8 +669,6 @@ void ClientTimerActions( gentity_t *ent, int msec )
client->ps.stats[ STAT_MISC2 ] <= 0 &&
client->ps.weaponstate != WEAPON_NEEDS_RESET )
{
- int ammo;
-
if( client->ps.stats[ STAT_MISC ] <= 0 )
client->lcannonStartTime = level.time;
@@ -735,7 +733,8 @@ void ClientTimerActions( gentity_t *ent, int msec )
break;
}
- if( client->ps.stats[ STAT_STATE ] & SS_MEDKIT_ACTIVE )
+ if( ent->client->pers.teamSelection == PTE_HUMANS &&
+ ( client->ps.stats[ STAT_STATE ] & SS_HEALING_ACTIVE ) )
{
int remainingStartupTime = MEDKIT_STARTUP_TIME - ( level.time - client->lastMedKitTime );
@@ -749,7 +748,7 @@ void ClientTimerActions( gentity_t *ent, int msec )
ent->health++;
}
else
- ent->client->ps.stats[ STAT_STATE ] &= ~SS_MEDKIT_ACTIVE;
+ ent->client->ps.stats[ STAT_STATE ] &= ~SS_HEALING_ACTIVE;
}
else
{
@@ -768,7 +767,7 @@ void ClientTimerActions( gentity_t *ent, int msec )
}
}
else
- ent->client->ps.stats[ STAT_STATE ] &= ~SS_MEDKIT_ACTIVE;
+ ent->client->ps.stats[ STAT_STATE ] &= ~SS_HEALING_ACTIVE;
}
}
}
@@ -794,19 +793,19 @@ void ClientTimerActions( gentity_t *ent, int msec )
G_Damage( ent, client->lastPoisonClient, client->lastPoisonClient, NULL,
0, damage, 0, MOD_POISON );
- }
+ }
//replenish alien health
if( client->ps.stats[ STAT_PTEAM ] == PTE_ALIENS &&
- level.surrenderTeam != PTE_ALIENS )
+ level.surrenderTeam != PTE_ALIENS )
{
int entityList[ MAX_GENTITIES ];
vec3_t range = { LEVEL4_REGEN_RANGE, LEVEL4_REGEN_RANGE, LEVEL4_REGEN_RANGE };
vec3_t mins, maxs;
int i, num;
gentity_t *boostEntity;
- float modifier = 1.0f;
- qboolean modified = qfalse;
+ float modifier = 1.0f, new_modifier;
+ qboolean creep;
VectorAdd( client->ps.origin, range, maxs );
VectorSubtract( client->ps.origin, range, mins );
@@ -816,34 +815,42 @@ void ClientTimerActions( gentity_t *ent, int msec )
{
boostEntity = &g_entities[ entityList[ i ] ];
+ new_modifier = 0.0f;
if( boostEntity->s.eType == ET_BUILDABLE &&
boostEntity->s.modelindex == BA_A_BOOSTER &&
boostEntity->spawned && boostEntity->health > 0)
- {
- modifier = BOOSTER_REGEN_MOD;
- modified = qtrue;
- break;
- }
+ new_modifier = BOOSTER_REGEN_MOD;
else if( boostEntity->client && boostEntity->health > 0 &&
- boostEntity->client->pers.teamSelection == PTE_ALIENS &&
- ( boostEntity->client->pers.classSelection == PCL_ALIEN_LEVEL1 ||
- boostEntity->client->pers.classSelection == PCL_ALIEN_LEVEL1_UPG ) )
+ boostEntity->client->pers.teamSelection == PTE_ALIENS )
{
if( boostEntity->client->pers.classSelection == PCL_ALIEN_LEVEL1_UPG )
- modifier = LEVEL1_UPG_REGEN_MOD;
- else
- modifier = LEVEL1_REGEN_MOD;
-
- modified = qtrue;
- break;
+ new_modifier = LEVEL1_UPG_REGEN_MOD;
+ else if( boostEntity->client->pers.classSelection == PCL_ALIEN_LEVEL1 )
+ new_modifier = LEVEL1_REGEN_MOD;
}
+ if( new_modifier > modifier )
+ modifier = new_modifier;
}
+
+ creep = G_FindCreep( ent );
+
+ // Transmit heal rate to the client so the HUD can display it properly
+ client->ps.stats[ STAT_STATE ] &= ~( SS_HEALING_2X | SS_HEALING_3X );
+ if( modifier >= 3.0f )
+ client->ps.stats[ STAT_STATE ] |= SS_HEALING_3X;
+ else if( modifier >= 2.0f )
+
+ client->ps.stats[ STAT_STATE ] |= SS_HEALING_2X;
+ if( creep || modifier != 1.0f )
+ client->ps.stats[ STAT_STATE ] |= SS_HEALING_ACTIVE;
+ else
+ client->ps.stats[ STAT_STATE ] &= ~SS_HEALING_ACTIVE;
if( ent->health > 0 &&
- ent->health < client->ps.stats[ STAT_MAX_HEALTH ] &&
+ ent->health < client->ps.stats[ STAT_MAX_HEALTH ] &&
( ent->lastDamageTime + ALIEN_REGEN_DAMAGE_TIME ) < level.time )
{
- if( !modified && !G_FindCreep( ent ) )
+ if( modifier == 1.0f && !creep )
{
if( ( ent->lastRegenTime + ALIEN_REGEN_NOCREEP_TIME ) < level.time )
{
@@ -866,7 +873,7 @@ void ClientTimerActions( gentity_t *ent, int msec )
// turn off life support when a team admits defeat
if( client->ps.stats[ STAT_PTEAM ] == PTE_ALIENS &&
- level.surrenderTeam == PTE_ALIENS )
+ level.surrenderTeam == PTE_ALIENS )
{
G_Damage( ent, NULL, NULL, NULL, NULL,
BG_FindRegenRateForClass( client->ps.stats[ STAT_PCLASS ] ),
@@ -891,9 +898,9 @@ void ClientTimerActions( gentity_t *ent, int msec )
if( client->ps.ammo < maxAmmo )
client->ps.ammo++;
+ }
}
}
-}
/*
====================
@@ -1508,7 +1515,7 @@ void ClientThink_real( gentity_t *ent )
BG_UpgradeIsActive( UP_MEDKIT, client->ps.stats ) )
{
//if currently using a medkit or have no need for a medkit now
- if( client->ps.stats[ STAT_STATE ] & SS_MEDKIT_ACTIVE ||
+ if( client->ps.stats[ STAT_STATE ] & SS_HEALING_ACTIVE ||
( client->ps.stats[ STAT_HEALTH ] == client->ps.stats[ STAT_MAX_HEALTH ] &&
!( client->ps.stats[ STAT_STATE ] & SS_POISONED ) ) )
{
@@ -1523,7 +1530,7 @@ void ClientThink_real( gentity_t *ent )
client->ps.stats[ STAT_STATE ] &= ~SS_POISONED;
client->poisonImmunityTime = level.time + MEDKIT_POISON_IMMUNITY_TIME;
- client->ps.stats[ STAT_STATE ] |= SS_MEDKIT_ACTIVE;
+ client->ps.stats[ STAT_STATE ] |= SS_HEALING_ACTIVE;
client->lastMedKitTime = level.time;
client->medKitHealthToRestore =
client->ps.stats[ STAT_MAX_HEALTH ] - client->ps.stats[ STAT_HEALTH ];
diff --git a/src/game/g_buildable.c b/src/game/g_buildable.c
index ec3c76fd..7ef5054e 100644
--- a/src/game/g_buildable.c
+++ b/src/game/g_buildable.c
@@ -1952,6 +1952,23 @@ void HDCC_Think( gentity_t *self )
/*
================
+HMedistat_Die
+
+Die function for Human Medistation
+================
+*/
+void HMedistat_Die( gentity_t *self, gentity_t *inflictor,
+ gentity_t *attacker, int damage, int mod )
+{
+ //clear target's healing flag
+ if( self->enemy && self->enemy->client )
+ self->enemy->client->ps.stats[ STAT_STATE ] &= ~SS_HEALING_3X;
+
+ HSpawn_Die( self, inflictor, attacker, damage, mod );
+}
+
+/*
+================
HMedistat_Think
think function for Human Medistation
@@ -1967,6 +1984,10 @@ void HMedistat_Think( gentity_t *self )
self->nextthink = level.time + BG_FindNextThinkForBuildable( self->s.modelindex );
+ //clear target's healing flag
+ if( self->enemy && self->enemy->client )
+ self->enemy->client->ps.stats[ STAT_STATE ] &= ~SS_HEALING_3X;
+
//make sure we have power
if( !( self->powered = G_FindPower( self ) ) )
{
@@ -1993,19 +2014,20 @@ void HMedistat_Think( gentity_t *self )
//if active use the healing idle
if( self->active )
G_SetIdleBuildableAnim( self, BANIM_IDLE2 );
-
+
//check if a previous occupier is still here
num = trap_EntitiesInBox( mins, maxs, entityList, MAX_GENTITIES );
for( i = 0; i < num; i++ )
{
player = &g_entities[ entityList[ i ] ];
- if( player->client && player->client->ps.stats[ STAT_PTEAM ] == PTE_HUMANS )
+ if( self->enemy == player && player->client &&
+ player->client->ps.stats[ STAT_PTEAM ] == PTE_HUMANS &&
+ player->health < player->client->ps.stats[ STAT_MAX_HEALTH ] &&
+ player->client->ps.pm_type != PM_DEAD )
{
- if( player->health < player->client->ps.stats[ STAT_MAX_HEALTH ] &&
- player->client->ps.pm_type != PM_DEAD &&
- self->enemy == player )
- occupied = qtrue;
+ occupied = qtrue;
+ player->client->ps.stats[ STAT_STATE ] |= SS_HEALING_3X;
}
}
@@ -2031,6 +2053,7 @@ void HMedistat_Think( gentity_t *self )
{
G_SetBuildableAnim( self, BANIM_ATTACK1, qfalse );
self->active = qtrue;
+ player->client->ps.stats[ STAT_STATE ] |= SS_HEALING_3X;
}
}
else if( !BG_InventoryContainsUpgrade( UP_MEDKIT, player->client->ps.stats ) )
@@ -3414,7 +3437,7 @@ static gentity_t *G_Build( gentity_t *builder, buildable_t buildable, vec3_t ori
case BA_H_MEDISTAT:
built->think = HMedistat_Think;
- built->die = HSpawn_Die;
+ built->die = HMedistat_Die;
break;
case BA_H_REACTOR:
diff --git a/src/ui/ui_local.h b/src/ui/ui_local.h
index ca3dab77..222942cb 100644
--- a/src/ui/ui_local.h
+++ b/src/ui/ui_local.h
@@ -57,6 +57,7 @@ void UI_DrawConnectScreen( qboolean overlay );
#define MAX_MODS 64
#define MAX_DEMOS 256
#define MAX_MOVIES 256
+#define MAX_HELP_INFOPANES 32
typedef struct
{
@@ -243,6 +244,10 @@ typedef struct
int humanBuildCount;
int humanBuildIndex;
+ menuItem_t helpList[ MAX_HELP_INFOPANES ];
+ int helpCount;
+ int helpIndex;
+
int weapons;
int upgrades;
diff --git a/src/ui/ui_main.c b/src/ui/ui_main.c
index 23005600..3a7e6d7e 100644
--- a/src/ui/ui_main.c
+++ b/src/ui/ui_main.c
@@ -1376,7 +1376,7 @@ void UI_LoadMenus( const char *menuFile, qboolean reset )
handle = trap_Parse_LoadSource( menuFile );
if( !handle )
- trap_Error( va( S_COLOR_RED "default menu file not found: ui/menus.txt, unable to continue!\n" ) );
+ trap_Error( va( S_COLOR_RED "menu list '%s' not found, unable to continue!\n", menuFile ) );
if( reset )
Menu_Reset();
@@ -1401,11 +1401,70 @@ void UI_LoadMenus( const char *menuFile, qboolean reset )
}
}
- Com_Printf( "UI menu load time = %d milli seconds\n", trap_Milliseconds() - start );
+ Com_Printf( "UI menu file '%s' loaded in %d msec\n", menuFile, trap_Milliseconds() - start );
trap_Parse_FreeSource( handle );
}
+void UI_LoadHelp( const char *helpFile )
+{
+ pc_token_t token;
+ int handle, start;
+ char title[ 32 ], buffer[ 1024 ];
+
+ start = trap_Milliseconds();
+
+ handle = trap_Parse_LoadSource( helpFile );
+ if( !handle )
+ {
+ Com_Printf( S_COLOR_YELLOW "WARNING: help file '%s' not found!\n",
+ helpFile );
+ return;
+ }
+
+ if( !trap_Parse_ReadToken( handle, &token ) ||
+ token.string[0] == 0 || token.string[0] != '{' )
+ {
+ Com_Printf( S_COLOR_YELLOW "WARNING: help file '%s' does not start with "
+ "'{'\n", helpFile );
+ return;
+ }
+
+ uiInfo.helpCount = 0;
+ title[ 0 ] = 0;
+ while( 1 )
+ {
+ if( !trap_Parse_ReadToken( handle, &token ) ||
+ token.string[0] == 0 || token.string[0] == '}' )
+ break;
+
+ if( token.string[0] == '{' )
+ {
+ buffer[ 0 ] = 0;
+ Q_strcat( buffer, sizeof( buffer ), title );
+ Q_strcat( buffer, sizeof( buffer ), "\n\n" );
+ while( trap_Parse_ReadToken( handle, &token ) &&
+ token.string[0] != 0 && token.string[0] != '}' )
+ {
+ Q_strcat( buffer, sizeof( buffer ), token.string );
+ }
+
+ uiInfo.helpList[ uiInfo.helpCount ].text = String_Alloc( title );
+ uiInfo.helpList[ uiInfo.helpCount ].v.text = String_Alloc( buffer );
+ uiInfo.helpList[ uiInfo.helpCount ].type = INFOTYPE_TEXT;
+ uiInfo.helpCount++;
+ title[ 0 ] = 0;
+ }
+ else
+ Q_strcat( title, sizeof( title ), token.string );
+ }
+
+ trap_Parse_FreeSource( handle );
+
+ Com_Printf( "UI help file '%s' loaded in %d msec (%d infopanes)\n",
+ helpFile, trap_Milliseconds() - start, uiInfo.helpCount );
+}
+
void UI_Load( void )
{
char lastName[1024];
@@ -1419,6 +1478,7 @@ void UI_Load( void )
UI_LoadMenus( "ui/menus.txt", qtrue );
UI_LoadMenus( "ui/ingame.txt", qfalse );
UI_LoadMenus( "ui/tremulous.txt", qfalse );
+ UI_LoadHelp( "ui/help.txt" );
Menus_CloseAll( qtrue );
Menus_ActivateByName( lastName );
@@ -1850,6 +1910,11 @@ static void UI_OwnerDraw( float x, float y, float w, float h,
&rect, text_x, text_y, scale, textalign, textvalign, color, textStyle );
break;
+ case UI_HELPINFOPANE:
+ UI_DrawInfoPane( &uiInfo.helpList[ uiInfo.helpIndex ],
+ &rect, text_x, text_y, scale, textalign, textvalign, color, textStyle );
+ break;
+
case UI_NETMAPPREVIEW:
UI_DrawServerMapPreview( &rect, scale, color );
break;
@@ -3270,6 +3335,8 @@ static int UI_FeederCount( float feederID )
}
else if( feederID == FEEDER_IGNORE_LIST )
return uiInfo.playerCount;
+ else if( feederID == FEEDER_HELP_LIST )
+ return uiInfo.helpCount;
else if( feederID == FEEDER_MODS )
return uiInfo.modCount;
else if( feederID == FEEDER_DEMOS )
@@ -3443,6 +3510,11 @@ static const char *UI_FeederItemText( float feederID, int index, int column, qha
}
}
}
+ else if( feederID == FEEDER_HELP_LIST )
+ {
+ if( index >= 0 && index < uiInfo.helpCount )
+ return uiInfo.helpList[ index ].text;
+ }
else if( feederID == FEEDER_MODS )
{
if( index >= 0 && index < uiInfo.modCount )
@@ -3598,6 +3670,8 @@ static void UI_FeederSelection( float feederID, int index )
uiInfo.teamPlayerIndex = index;
else if( feederID == FEEDER_IGNORE_LIST )
uiInfo.ignoreIndex = index;
+ else if( feederID == FEEDER_HELP_LIST )
+ uiInfo.helpIndex = index;
else if( feederID == FEEDER_MODS )
uiInfo.modIndex = index;
else if( feederID == FEEDER_CINEMATICS )
@@ -3775,6 +3849,7 @@ void UI_Init( qboolean inGameLoad )
UI_LoadMenus( "ui/menus.txt", qtrue );
UI_LoadMenus( "ui/ingame.txt", qfalse );
UI_LoadMenus( "ui/tremulous.txt", qfalse );
+ UI_LoadHelp( "ui/help.txt" );
Menus_CloseAll( qtrue );