summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMichael Levin <risujin@fastmail.fm>2009-10-03 11:21:01 +0000
committerTim Angus <tim@ngus.net>2013-01-03 00:14:54 +0000
commitce4dfd02633cfb1fa82b603f3d7af1a89a0fcb97 (patch)
tree103e783cd11e6bbdb0a77b9b6d7532b9f5820362
parent8a36ffb80b9ee398a6b21f6e1f937f2527ae9cce (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.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
-rw-r--r--ui/help.txt101
-rw-r--r--ui/ingame.menu30
-rw-r--r--ui/ingame.txt2
-rw-r--r--ui/menudef.h5
-rw-r--r--ui/tremulous_alien_common_hud.h30
-rw-r--r--ui/tremulous_human_hud.menu30
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