diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/cgame/cg_draw.c | 42 | ||||
-rw-r--r-- | src/cgame/cg_local.h | 1 | ||||
-rw-r--r-- | src/cgame/cg_weapons.c | 106 | ||||
-rw-r--r-- | src/game/bg_misc.c | 10 | ||||
-rw-r--r-- | src/game/bg_pmove.c | 6 | ||||
-rw-r--r-- | src/game/bg_public.h | 6 | ||||
-rw-r--r-- | src/game/g_active.c | 65 | ||||
-rw-r--r-- | src/game/g_buildable.c | 37 | ||||
-rw-r--r-- | src/ui/ui_local.h | 5 | ||||
-rw-r--r-- | src/ui/ui_main.c | 79 |
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 ); |