diff options
author | Michael Levin <risujin@fastmail.fm> | 2009-10-03 11:21:01 +0000 |
---|---|---|
committer | Tim Angus <tim@ngus.net> | 2013-01-03 00:14:54 +0000 |
commit | ce4dfd02633cfb1fa82b603f3d7af1a89a0fcb97 (patch) | |
tree | 103e783cd11e6bbdb0a77b9b6d7532b9f5820362 | |
parent | 8a36ffb80b9ee398a6b21f6e1f937f2527ae9cce (diff) |
* Started updating infopanes with Badger, need to do more
* Fixed a bug where regular Basilisk would not heal faster by a booster sometimes (found thanks to new GUI indicator!)
* Un-reverted Lucifer Cannon sound heard by others, with Norf's blessing
* Added a Help menu listing mod changes and other stuff (ESC -> Help), edit ui/help.txt
* Human HUD item list will now wrap around so that it never hides items, also made it a little wider
GUI cross changes:
* Human GUI health cross glows when medkit is active
* Alien GUI health cross glows when on creep
* Double, triple healing rates show as multiple crosses
-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 | ||||
-rw-r--r-- | ui/help.txt | 101 | ||||
-rw-r--r-- | ui/ingame.menu | 30 | ||||
-rw-r--r-- | ui/ingame.txt | 2 | ||||
-rw-r--r-- | ui/menudef.h | 5 | ||||
-rw-r--r-- | ui/tremulous_alien_common_hud.h | 30 | ||||
-rw-r--r-- | ui/tremulous_human_hud.menu | 30 |
16 files changed, 438 insertions, 117 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 ); diff --git a/ui/help.txt b/ui/help.txt new file mode 100644 index 00000000..02a40cf9 --- /dev/null +++ b/ui/help.txt @@ -0,0 +1,101 @@ +{ + "Welcome to MGDev!" + { + "This mod is under ongoing development. It is probably buggy and new " + "features will come and go, please be patient and report any bugs you " + "find!\n\n" + "Please visit the Mercenaries Guild at:\n" + "http://www.mercenariesguild.net/\n\n" + "We can also be reached on Freenode IRC:\n" + "#mercenariesguild" + } + "Release Notes r86" + { + "* Help menu (you're looking at it!)\n" + "* UI health cross icon shows regen speed\n" + "* Human UI health cross glows from medkit\n" + "* Human item list wider and won't hide items\n" + "* Regular Basilik benefits from booster\n" + "* Lucifer Cannon overcharge heard by others\n" + } + "Alien Healing" + { + "The most important change for Alien players to know is that their healing " + "rate is slower away from creep. To counter this, healing near Boosters " + "and Basilisks is greatly accelerated. Watch the health cross icon on your " + "HUD to see what your healing rate is. If the icon glows, you are on " + "creep. If you are near a booster or basilisk, you will see multiple " + "crosses." + } + "Barricades" + { + "Nearly useless in 1.1, Barricades now have more health, are cheaper to " + "build, and will shrink to allow Aliens to pass through them. Acid tubes " + "will fire from behind barricades, providing a formidable defense. " + "Experiment with blocking off hallways and building staged defenses, but " + "keep in mind that low ceilings will prevent Tyrants from returning inside " + "the base." + } + "Anti-Camping" + { + "Aliens will no longer be as frustrated by camping Human players because " + "the Adv. Dragoon is now available at Stage 2. The Adv. " + "Dragoon snipe attack has slight splash damage. Also, because Human turrets " + "have a slight spinup delay, skillful Dretches can run inside the Human " + "base and get a few kills before being shot by turrets." + } + "Tyrant" + { + "The Tyrant is now a weaker class as its health has been lowered and " + "turret damage is greater. To counter this, Tyrants can charge for longer " + "periods of time and can crush any Humans they land on top of. Remember " + "that because trample takes longer to charge, you need to let go early " + "for a quick charge. The Tyrant's healing aura has been removed, find a " + "booster or a basilisk to heal faster." + } + "Sprint / Dodge" + { + "Human players will find their old binds for sprinting will no longer " + "work. Sprinting has been merged with a new Human ability, dodging. You " + "can bind a key for Sprint and Dodge via the Options menu or bind a " + "key (\\bind shift +button6). When you are strafing or walking backwards, " + "press the dodge key to make a quick sideways jump. When running forward, " + "press the dodge key to start a sprint. The sprint will last until you let " + "go of the forward key." + } + "Human Weapons" + { + "The Lucifer Cannon projectile can be fired faster but now takes longer " + "to charge. You will be able to hear other players overcharge " + "their Lucifer Cannon.\n\n" + "The Mass Driver can now fire through players and buildables. The same " + "amount of damage is dealt to all targets along the path. Keep in mind " + "that you cannot shoot through friendly targets if friendly fire is off." + } + "Human Buildables" + { + "While turrets now have a small spin up delay before firing, they have " + "increased damage output. To protect against small Aliens getting inside " + "the base, build Tesla Generators at Stage 3. Tesla Generators no longer " + "require the Defense Computer to function. Instead, the Defense Computer " + "will automatically repair Human buildables." + } + "Lag Correction" + { + "While the Tremulous implementation of Neil Toronto's unlagged is " + "becoming widely accepted, MGDev also implements client-side improvements " + "not possible in 1.1 servers. Because attacking is more " + "accurate on account of lag correction, Humans no longer need to lead " + "their weapons and Alien ranges and attack widths have generally been " + "decreased." + } + "Credits" + { + "MGDev is developed and hosted by the Mercenaries Guild. " + "Contributing developers:\n\n" + "Norfenstein\n" + "Benmachine\n" + "Lakitu7\n" + "Michael Levin <risujin@risujin.org>" + } +} diff --git a/ui/ingame.menu b/ui/ingame.menu index 90b4cf12..2c8981fa 100644 --- a/ui/ingame.menu +++ b/ui/ingame.menu @@ -1,9 +1,9 @@ #include "ui/menudef.h" { -#define BUTT_BAR_X 35 +#define BUTT_BAR_X 50 #define BUTT_BAR_Y 0 -#define BUTT_BAR_W 235 +#define BUTT_BAR_W 150 #define BUTT_BAR_H 56 #define BUTT_W (BUTT_BAR_W/3) #define BUTT_H BUTT_BAR_H @@ -68,7 +68,7 @@ rect BUTT_BAR_X BUTT_BAR_Y BUTT_W BUTT_H type ITEM_TYPE_BUTTON style WINDOW_STYLE_EMPTY - textalign ALIGN_RIGHT + textalign ALIGN_CENTER textvalign VALIGN_CENTER textalignx -BUTT_TEXT_S textscale .4 @@ -103,11 +103,31 @@ itemDef { name leave - text "Exit" + text "Help" type ITEM_TYPE_BUTTON style WINDOW_STYLE_EMPTY rect (BUTT_BAR_X+(2*BUTT_W)) BUTT_BAR_Y BUTT_W BUTT_H - textalign ALIGN_LEFT + textalign ALIGN_CENTER + textvalign VALIGN_CENTER + textalignx BUTT_TEXT_S + textscale .4 + forecolor 1 1 1 1 + visible MENU_TRUE + action + { + play "sound/misc/menu1.wav"; + open ingame_help + } + } + + itemDef + { + name leave + text "Exit" + type ITEM_TYPE_BUTTON + style WINDOW_STYLE_EMPTY + rect (BUTT_BAR_X+(3*BUTT_W)) BUTT_BAR_Y BUTT_W BUTT_H + textalign ALIGN_CENTER textvalign VALIGN_CENTER textalignx BUTT_TEXT_S textscale .4 diff --git a/ui/ingame.txt b/ui/ingame.txt index a71be329..2caf449f 100644 --- a/ui/ingame.txt +++ b/ui/ingame.txt @@ -5,5 +5,5 @@ loadMenu { "ui/ingame_game.menu" } loadMenu { "ui/ingame_options.menu" } loadMenu { "ui/ingame_leave.menu" } - loadMenu { "ui/fonttest.menu" } + loadMenu { "ui/ingame_help.menu" } } diff --git a/ui/menudef.h b/ui/menudef.h index c85cb430..99adf158 100644 --- a/ui/menudef.h +++ b/ui/menudef.h @@ -79,6 +79,7 @@ #define FEEDER_TREMALIENBUILD 18 // alien buildables #define FEEDER_TREMHUMANBUILD 19 // human buildables #define FEEDER_IGNORE_LIST 20 // ignored players +#define FEEDER_HELP_LIST 21 // help topics // display flags #define UI_SHOW_FAVORITESERVERS 0x00000001 @@ -171,5 +172,9 @@ #define UI_HSELLINFOPANE 72 #define UI_ABUILDINFOPANE 73 #define UI_HBUILDINFOPANE 74 +#define UI_HELPINFOPANE 75 + +#define CG_PLAYER_HEALTH_CROSS2 76 +#define CG_PLAYER_HEALTH_CROSS3 77 #endif diff --git a/ui/tremulous_alien_common_hud.h b/ui/tremulous_alien_common_hud.h index 321c00f0..e092ecf9 100644 --- a/ui/tremulous_alien_common_hud.h +++ b/ui/tremulous_alien_common_hud.h @@ -92,13 +92,39 @@ itemDef itemDef { name "cross" - rect 155 422.5 15 15 + rect 152.5 420.5 20 20 aspectBias ALIGN_LEFT visible MENU_TRUE decoration forecolor COMMON_HUD_R COMMON_HUD_G COMMON_HUD_B 0.5 - style WINDOW_STYLE_SHADER background "ui/assets/neutral/cross.tga" + ownerdraw CG_PLAYER_HEALTH_CROSS +} + +//CROSS 2X +itemDef +{ + name "cross" + rect 152.5 420.5 20 20 + aspectBias ALIGN_LEFT + visible MENU_TRUE + decoration + forecolor COMMON_HUD_R COMMON_HUD_G COMMON_HUD_B 0.5 + background "ui/assets/neutral/cross2.tga" + ownerdraw CG_PLAYER_HEALTH_CROSS2 +} + +//CROSS 3X +itemDef +{ + name "cross" + rect 152.5 420.5 20 20 + aspectBias ALIGN_LEFT + visible MENU_TRUE + decoration + forecolor COMMON_HUD_R COMMON_HUD_G COMMON_HUD_B 0.5 + background "ui/assets/neutral/cross3.tga" + ownerdraw CG_PLAYER_HEALTH_CROSS3 } //LEFT RING diff --git a/ui/tremulous_human_hud.menu b/ui/tremulous_human_hud.menu index 3d527608..5727aaf5 100644 --- a/ui/tremulous_human_hud.menu +++ b/ui/tremulous_human_hud.menu @@ -121,7 +121,7 @@ itemDef { name "cross" - rect 137.5 430 15 15 + rect 135 427.5 20 20 aspectBias ALIGN_LEFT visible MENU_TRUE decoration @@ -130,6 +130,32 @@ ownerdraw CG_PLAYER_HEALTH_CROSS } + //CROSS 2X + itemDef + { + name "cross" + rect 135 427.5 20 20 + aspectBias ALIGN_LEFT + visible MENU_TRUE + decoration + forecolor COMMON_HUD_R COMMON_HUD_G COMMON_HUD_B 0.5 + background "ui/assets/neutral/cross2.tga" + ownerdraw CG_PLAYER_HEALTH_CROSS2 + } + + //CROSS 3X + itemDef + { + name "cross" + rect 135 427.5 20 20 + aspectBias ALIGN_LEFT + visible MENU_TRUE + decoration + forecolor COMMON_HUD_R COMMON_HUD_G COMMON_HUD_B 0.5 + background "ui/assets/neutral/cross3.tga" + ownerdraw CG_PLAYER_HEALTH_CROSS3 + } + //STAMINA 1 itemDef { @@ -311,7 +337,7 @@ itemDef { name "inventory" - rect 232.5 425 175 25 + rect 182.5 425 275 25 aspectBias ALIGN_CENTER visible MENU_TRUE decoration |