/* ** Command & Conquer Renegade(tm) ** Copyright 2025 Electronic Arts Inc. ** ** This program is free software: you can redistribute it and/or modify ** it under the terms of the GNU General Public License as published by ** the Free Software Foundation, either version 3 of the License, or ** (at your option) any later version. ** ** This program is distributed in the hope that it will be useful, ** but WITHOUT ANY WARRANTY; without even the implied warranty of ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ** GNU General Public License for more details. ** ** You should have received a copy of the GNU General Public License ** along with this program. If not, see . */ /*********************************************************************************************** *** Confidential - Westwood Studios *** *********************************************************************************************** * * * Project Name : Commando * * * * $Archive:: /Commando/Code/Combat/hud.cpp $* * * * $Author:: Byon_g $* * * * $Modtime:: 2/11/02 2:27p $* * * * $Revision:: 228 $* * * *---------------------------------------------------------------------------------------------* * Functions: * * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ #include "hud.h" #include #include "wwprofile.h" #include "assets.h" #include "font3d.h" #include "combat.h" #include "soldier.h" #include "debug.h" #include "ccamera.h" #include "vehicle.h" #include "weapons.h" #include "radar.h" #include "texture.h" #include "phys.h" #include "render2d.h" #include "hudinfo.h" #include "globalsettings.h" #include "translatedb.h" #include "playerdata.h" #include "playertype.h" #include "sniper.h" #include "render2dsentence.h" #include "input.h" #include "building.h" #include "objectives.h" #include "weaponbag.h" #include "string_ids.h" #include "gametype.h" #include "stylemgr.h" static void Generate_WChar_Text_From_Number(WCHAR* text,int digits,int min_digits,int value) { text[digits]=0; while (digits) { digits--; text[digits]=value%10+'0'; value/=10; min_digits--; if (value==0 && (min_digits == 0)) break; } if ((min_digits==0) && digits) { int i=0; while (WCHAR c=text[digits++]) { text[i++]=c; } text[i]=0; } } /* ** */ Vector2 INFO_UV_SCALE( 1.0f/256.0f, 1.0f/256.0f ); Vector2 INFO_OFFSET( 7, -179 ); Vector2 FRAME_1_UV_UL( 96, 105 ); Vector2 FRAME_1_UV_LR( 214, 255 ); Vector2 FRAME_1_OFFSET( -3, -1 ); Vector2 FRAME_2_UV_UL( 215, 125 ); Vector2 FRAME_2_UV_LR( 255, 192 ); Vector2 FRAME_2_OFFSET( 114, 57 ); Vector2 FRAME_3_UV_UL( 218, 192 ); Vector2 FRAME_3_UV_LR( 255, 201 ); Vector2 FRAME_3_OFFSET( 154, 115 ); Vector2 FRAME_4_UV_UL( 216, 200 ); Vector2 FRAME_4_UV_LR( 255, 255 ); Vector2 FRAME_4_OFFSET( 191, 115 ); Vector2 FRAME_5_UV_UL( 80, 203 ); Vector2 FRAME_5_UV_LR( 100, 258 ); Vector2 FRAME_5_OFFSET( 230, 116 ); Vector2 FRAME_6_UV_UL( 216, 101 ); Vector2 FRAME_6_UV_LR( 240, 125 ); Vector2 FRAME_6_OFFSET( 74, 149 ); Vector2 HEALTH_BACK_UV_UL( 183, 241 ); Vector2 HEALTH_BACK_UV_LR( 186, 248 ); Vector2 HEALTH_BACK_UL( 98, 122 ); Vector2 HEALTH_BACK_LR( 224, 168 ); Vector2 GRADIENT_BLACK_UV_UL( 3, 135 ); Vector2 GRADIENT_BLACK_UV_LR( 44, 144 ); Vector2 HEALTH_TEXT_BACK_UL( 77, 124 ); Vector2 HEALTH_TEXT_BACK_LR( 163, 150 ); Vector2 HEALTH_UV_UL( 94, 52 ); Vector2 HEALTH_UV_LR( 249, 100 ); Vector2 HEALTH_OFFSET( 73, 121 ); Vector2 SHIELD_UV_UL( 66, 97 ); Vector2 SHIELD_UV_LR( 96, 132 ); Vector2 SHIELD_OFFSET( 211, 140 ); Vector2 KEY_1_UV_UL( 30, 180 ); Vector2 KEY_1_UV_LR( 57, 197 ); Vector2 KEY_1_OFFSET( 32, 134 ); Vector2 KEY_2_UV_UL( 0, 181 ); Vector2 KEY_2_UV_LR( 30, 197 ); Vector2 KEY_2_OFFSET( 41, 140 ); Vector2 KEY_3_UV_UL( 69, 133 ); Vector2 KEY_3_UV_LR( 97, 149 ); Vector2 KEY_3_OFFSET( 50, 148 ); Vector2 HEALTH_CROSS_1_UV_UL( 33, 199 ); Vector2 HEALTH_CROSS_1_UV_LR( 63, 226 ); Vector2 HEALTH_CROSS_1_OFFSET( 77, 124 ); Vector2 HEALTH_CROSS_2_UV_UL( 33, 228 ); Vector2 HEALTH_CROSS_2_UV_LR( 63, 258 ); Vector2 HEALTH_CROSS_2_OFFSET( 77, 124 ); Vector2 TIME_BACK_UL( 150, 97 ); Vector2 TIME_BACK_LR( 213, 116 ); Vector2 TIME_CLOCK_UV_UL( 46, 125 ); Vector2 TIME_CLOCK_UV_LR( 66, 148 ); Vector2 TIME_CLOCK_OFFSET( 186, 94 ); Vector2 WEAPON_BOX_UV_UL( 0, 0 ); Vector2 WEAPON_BOX_UV_LR( 95, 95 ); Vector2 WEAPON_BOX_OFFSET( 195, -53 ); Vector2 POWER_OUT_ICON_UV_UL( 0, 95 ); Vector2 POWER_OUT_ICON_UV_LR( 30, 129 ); Vector2 POWER_OUT_ICON_OFFSET( 143, 41 ); Vector2 REPAIR_ICON_UV_UL( 31, 97 ); Vector2 REPAIR_ICON_UV_LR( 61, 126 ); Vector2 REPAIR_ICON_OFFSET( 181, 43 ); Vector2 GDI_ICON_UV_UL( 14, 222 ); Vector2 GDI_ICON_UV_LR( 34, 238 ); Vector2 GDI_ICON_OFFSET( 217, 77 ); Vector2 NOD_ICON_UV_UL( 14, 205 ); Vector2 NOD_ICON_UV_LR( 34, 221 ); Vector2 NOD_ICON_OFFSET( 238, 76 ); Vector2 NEUTRAL_ICON_UV_UL( 14, 238 ); Vector2 NEUTRAL_ICON_UV_LR( 33, 257 ); Vector2 NEUTRAL_ICON_OFFSET( 260, 77 ); Vector2 BULLET_ICON_UV_UL( 2, 211 ); Vector2 BULLET_ICON_UV_LR( 13, 255 ); Vector2 BULLET_ICON_OFFSET( -20, -30 ); Vector2 RADAR_CENTER_OFFSET( 55, 78 ); Vector2 DAMAGE_1_UV_UL( 65, 184 ); Vector2 DAMAGE_1_UV_LR( 78, 255 ); Vector2 DAMAGE_2_UV_UL( 200, 3 ); Vector2 DAMAGE_2_UV_LR( 248, 51 ); Vector2 HORIZ_DAMAGE_SIZE( 81, 14 ); Vector2 VERT_DAMAGE_SIZE( 15, 78 ); Vector2 DIAG_DAMAGE_SIZE( 53, 59 ); Vector2 HV_DAMAGE_OFFSET( 170, 168 ); Vector2 DIAG_DAMAGE_OFFSET( 119, 117 ); //Vector2 POWERUP_BOX_UV_UL( 48, 0 ); //Vector2 POWERUP_BOX_UV_LR( 129, 54 ); Vector2 POWERUP_BOX_UV_UL( 50, 1 ); Vector2 POWERUP_BOX_UV_LR( 127, 52 ); Vector2 RADAR_RINGS_UV_UL( 95, 0 ); Vector2 RADAR_RINGS_UV_LR( 197, 53 ); Vector2 RADAR_RINGS_L_OFFSET( -51, -50 ); Vector2 RADAR_RINGS_R_OFFSET( 0, -50 ); Vector2 RADAR_STAR_UV_UL( 241, 103 ); Vector2 RADAR_STAR_UV_LR( 249, 111 ); Vector2 RADAR_STAR_OFFSET( 280, 50 ); Vector2 RADAR_SQUARE_UV_UL( 247, 85 ); Vector2 RADAR_SQUARE_UV_LR( 255, 93 ); Vector2 RADAR_SQUARE_OFFSET( 290, 50 ); Vector2 RADAR_TRIANGLE_UV_UL( 247, 93 ); Vector2 RADAR_TRIANGLE_UV_LR( 255, 101 ); Vector2 RADAR_TRIANGLE_OFFSET( 300, 50 ); Vector2 RADAR_CIRCLE_UV_UL( 247, 77 ); Vector2 RADAR_CIRCLE_UV_LR( 255, 85 ); Vector2 RADAR_CIRCLE_OFFSET( 310, 50 ); Vector2 RADAR_BRACKET_UV_UL( 241, 114 ); Vector2 RADAR_BRACKET_UV_LR( 249, 122 ); Vector2 RADAR_BRACKET_OFFSET( 320, 50 ); Vector2 RADAR_SWEEP_UV_UL( 80, 182 ); Vector2 RADAR_SWEEP_UV_LR( 95, 191 ); Vector2 RADAR_SWEEP_OFFSET( 330, 50 ); Vector2 TARGET_HEALTH_L_UV_UL( 0, 165 ); Vector2 TARGET_HEALTH_L_UV_LR( 20, 181 ); Vector2 TARGET_HEALTH_R_UV_UL( 20, 165 ); //Vector2 TARGET_HEALTH_R_UV_LR( 96, 181 ); Vector2 TARGET_HEALTH_R_UV_LR( 96, 173 ); Vector2 TARGET_HEALTH_OFFSET( 123, 5 ); Vector2 TARGET_NAME_UV_UL( 1, 149 ); Vector2 TARGET_NAME_UV_LR( 91, 164 ); Vector2 TARGET_NAME_OFFSET( 125, 24 ); // Reticle #define RETICLE_WIDTH (64.0f/640.0f) #define RETICLE_HEIGHT (64.0f/480.0f) // Vector2 TARGET_ENTERABLE_UV_UL( 45, 209 ); Vector2 TARGET_ENTERABLE_UV_LR( 51, 215 ); Vector2 TARGET_ENTERABLE_SIZE( 32, 32 ); float TARGET_ENTERABLE_BOUNCE = 4; /* ** */ //#define LARGE_FONT "FONT24x36.TGA" #define LARGE_FONT "FONT12x16.TGA" #define MEDIUM_FONT "FONT12x16.TGA" #define SMALL_FONT "FONT6x8.TGA" enum { HUD_HELP_TEXT_DISPLAYING = 0, HUD_HELP_TEXT_FADING, HUD_HELP_TEXT_DONE }; /* ** */ #define HUD_MAIN_TEXTURE "HUD_MAIN.TGA" #define HUD_CHATPBOX_TEXTURE "HUD_CHATPBOX.TGA" #define HUD_WEAPONS_TEXTURE "hud_TibRVoltR.tga" /* This should be removed */ Render2DClass * InfoRenderer; Render2DSentenceClass * HUDHelpTextRenderer; Vector2 HUDHelpTextExtents (0, 0); float HUDHelpTextTimer = 0; int HUDHelpTextState = HUD_HELP_TEXT_DISPLAYING; /* ** */ unsigned long COLOR( float alpha, unsigned long color = 0x00FFFFFF ) { alpha = WWMath::Clamp( alpha, 0, 1 ) * 255.0f; color &= 0x00FFFFFF; color |= ((int)alpha) << 24; return color; } unsigned long Get_Health_Color( float percent ) { Vector3 color = HUDGlobalSettingsDef::Get_Instance()->Get_Health_High_Color(); if ( percent <= 0.5f ) { color = HUDGlobalSettingsDef::Get_Instance()->Get_Health_Med_Color(); } if ( percent <= 0.25f ) { color = HUDGlobalSettingsDef::Get_Instance()->Get_Health_Low_Color(); } return color.Convert_To_ARGB(); } /* ** Powerup Display */ struct PowerupIconStruct { PowerupIconStruct( void ) : Renderer( NULL ), Number( 0 ) {} ~PowerupIconStruct( void ) { if ( Renderer != NULL ) { delete Renderer; Renderer = NULL; } } WideStringClass Name; int Number; Render2DClass * Renderer; RectClass UV; RectClass IconBox; float Timer; }; // Two lists. A right one for weapons, health, and armor static DynamicVectorClass RightPowerupIconList; // and a left one for keys static DynamicVectorClass LeftPowerupIconList; Render2DClass * PowerupBoxRenderer; Render2DSentenceClass * PowerupTextRenderer; #define MAX_ICONS 5 #define POWERUP_TIME 6 static void Powerup_Init( void ) { PowerupBoxRenderer = new Render2DClass(); PowerupBoxRenderer->Set_Texture( HUD_CHATPBOX_TEXTURE ); PowerupBoxRenderer->Set_Coordinate_Range( Render2DClass::Get_Screen_Resolution() ); PowerupBoxRenderer->Enable_Additive( true ); FontCharsClass * font = StyleMgrClass::Peek_Font( StyleMgrClass::FONT_INGAME_TXT ); PowerupTextRenderer = new Render2DSentenceClass(); PowerupTextRenderer->Set_Font( font ); WWASSERT( LeftPowerupIconList.Count() == 0 ); WWASSERT( RightPowerupIconList.Count() == 0 ); } static void Powerup_Shutdown( void ) { delete PowerupBoxRenderer; PowerupBoxRenderer = NULL; delete PowerupTextRenderer; PowerupTextRenderer = NULL; int i; for ( i = 0; i < LeftPowerupIconList.Count(); i++ ) { delete LeftPowerupIconList[i]; } LeftPowerupIconList.Delete_All(); for ( i = 0; i < RightPowerupIconList.Count(); i++ ) { delete RightPowerupIconList[i]; } RightPowerupIconList.Delete_All(); } static void Powerup_Add( const WCHAR * name, int number, const char * texture_name, const RectClass & uv, const Vector2 & offset, bool right_list = true ) { PowerupIconStruct * data = new PowerupIconStruct(); data->Renderer = new Render2DClass(); StringClass new_name(true); Strip_Path_From_Filename( new_name, texture_name ); data->Renderer->Set_Texture( new_name ); data->Renderer->Set_Coordinate_Range( Render2DClass::Get_Screen_Resolution() ); // data->Renderer->Enable_Additive( true ); // SurfaceClass::SurfaceDescription surface_desc; // data->Renderer->Peek_Texture()->Get_Level_Description( surface_desc ); // float size = surface_desc.Width; // Assume square float size = data->Renderer->Peek_Texture()->Get_Width(); // Assume square data->UV = uv; if ( size > 0 ) { data->UV.Scale( Vector2( 1/size, 1/size ) ); } data->IconBox = uv; data->IconBox += offset + Vector2( 0, -40.0f ) - data->IconBox.Upper_Left(); data->Name = name; data->Number = number; data->Timer = POWERUP_TIME; if ( right_list ) { RightPowerupIconList.Add( data ); } else { LeftPowerupIconList.Add( data ); } } void Powerup_Reset( void ) { while ( LeftPowerupIconList.Count() ) { delete LeftPowerupIconList[0]; LeftPowerupIconList.Delete(0); } while ( RightPowerupIconList.Count() ) { delete RightPowerupIconList[0]; RightPowerupIconList.Delete(0); } } #define POWERUP_BOX_BASE POWERUP_BOX_WIDTH + 6, 112 #define POWERUP_BOX_WIDTH 80 #define POWERUP_BOX_HEIGHT 55 #define POWERUP_BOX_SPACING (POWERUP_BOX_HEIGHT + 10) #define POWERUP_BOX_UV 127,0,207,55 static void Powerup_Update( void ) { PowerupBoxRenderer->Reset(); PowerupTextRenderer->Reset(); RectClass box_uv( POWERUP_BOX_UV_UL, POWERUP_BOX_UV_LR ); box_uv.Scale( Vector2( 1.0f/128.0f, 1.0f/128.0f ) ); #define ANIMATE_TIME 1.0f // Two timers static float LeftAnimateTimer = 0; static float RightAnimateTimer = 0; if ( LeftPowerupIconList.Count() > 0 && LeftPowerupIconList[0]->Timer < 0 ) { LeftAnimateTimer += TimeManager::Get_Frame_Seconds(); if ( LeftAnimateTimer > ANIMATE_TIME ) { LeftAnimateTimer = 0; if ( LeftPowerupIconList.Count() ) { delete LeftPowerupIconList[0]; LeftPowerupIconList.Delete(0); } } } else { LeftAnimateTimer = 0; } if ( RightPowerupIconList.Count() > 0 && RightPowerupIconList[0]->Timer < 0 ) { RightAnimateTimer += TimeManager::Get_Frame_Seconds(); if ( RightAnimateTimer > ANIMATE_TIME ) { RightAnimateTimer = 0; if ( RightPowerupIconList.Count() ) { delete RightPowerupIconList[0]; RightPowerupIconList.Delete(0); } } } else { RightAnimateTimer = 0; } RectClass box( POWERUP_BOX_UV_UL, POWERUP_BOX_UV_LR ); Vector2 start = Render2DClass::Get_Screen_Resolution().Lower_Right() - Vector2( POWERUP_BOX_BASE ); box += start - box.Lower_Left(); box -= Vector2( box.Left - 6, +75 ); int i; for ( i = 0; i < MAX_ICONS && i < LeftPowerupIconList.Count(); i++ ) { LeftPowerupIconList[i]->Timer -= TimeManager::Get_Frame_Seconds(); RectClass draw_box = box; int green = 0xFF00FF00; int white = 0xFFFFFFFF; // Slide the bottom (first) icon away if ( i == 0 && LeftAnimateTimer > 0.0f ) { green = COLOR( WWMath::Clamp( 1.0f - (LeftAnimateTimer/ANIMATE_TIME), 0, 1 ), green ) ; white = COLOR( WWMath::Clamp( 1.0f - (LeftAnimateTimer/ANIMATE_TIME), 0, 1 ), white ) ; } #if 0 // No boxes // The box is drawn additive, so his color is green alpha int box_color = (white & 0xFF000000) | ((white >> 16) & 0x0000FF00); PowerupBoxRenderer->Add_Quad( draw_box, box_uv, box_color ); #endif // Draw powerup name PowerupTextRenderer->Build_Sentence( LeftPowerupIconList[i]->Name ); PowerupTextRenderer->Set_Location( Vector2( draw_box.Left + 1, draw_box.Top + POWERUP_BOX_HEIGHT - 15 ) ); PowerupTextRenderer->Draw_Sentence( white ); #if 0 // Draw powerup count if ( LeftPowerupIconList[i]->Number != 0 ) { WideStringClass num(0,true); num.Format( L"%d", LeftPowerupIconList[i]->Number ); PowerupTextRenderer->Build_Sentence( num ); PowerupTextRenderer->Set_Location( Vector2( draw_box.Right - 12, draw_box.Top + 1 ) ); PowerupTextRenderer->Draw_Sentence( white ); } #endif RectClass icon_box = LeftPowerupIconList[i]->IconBox; icon_box += draw_box.Upper_Left(); LeftPowerupIconList[i]->Renderer->Reset(); LeftPowerupIconList[i]->Renderer->Add_Quad( icon_box, LeftPowerupIconList[i]->UV, white ); // Drop the remaining icons down if ( i == 0 && LeftAnimateTimer > ANIMATE_TIME * 0.5f ) { box += Vector2( 0, ((2*LeftAnimateTimer/ANIMATE_TIME)-1) * POWERUP_BOX_SPACING ); } box -= Vector2( 0, POWERUP_BOX_SPACING ); } // Setup box for right box = RectClass( POWERUP_BOX_UV_UL, POWERUP_BOX_UV_LR ); start = Render2DClass::Get_Screen_Resolution().Lower_Right() - Vector2( POWERUP_BOX_BASE ); box += start - box.Lower_Left(); for ( i = 0; i < MAX_ICONS && i < RightPowerupIconList.Count(); i++ ) { RightPowerupIconList[i]->Timer -= TimeManager::Get_Frame_Seconds(); RectClass draw_box = box; int green = 0xFF00FF00; int white = 0xFFFFFFFF; // Slide the bottom (first) icon away if ( i == 0 && RightAnimateTimer > 0.0f ) { green = COLOR( WWMath::Clamp( 1.0f - (RightAnimateTimer/ANIMATE_TIME), 0, 1 ), green ) ; white = COLOR( WWMath::Clamp( 1.0f - (RightAnimateTimer/ANIMATE_TIME), 0, 1 ), white ) ; } #if 0 // No boxes // The box is drawn additive, so his color is green alpha int box_color = (white & 0xFF000000) | ((white >> 16) & 0x0000FF00); PowerupBoxRenderer->Add_Quad( draw_box, box_uv, box_color ); #endif // Draw powerup name PowerupTextRenderer->Build_Sentence( RightPowerupIconList[i]->Name ); float left_edge = draw_box.Left + 1; Vector2 extents = PowerupTextRenderer->Get_Text_Extents( RightPowerupIconList[i]->Name ); if ( left_edge + extents.X + 1> Render2DClass::Get_Screen_Resolution().Right ) { left_edge = Render2DClass::Get_Screen_Resolution().Right - extents.X - 1; } PowerupTextRenderer->Set_Location( Vector2( left_edge, draw_box.Top + POWERUP_BOX_HEIGHT - 15 ) ); PowerupTextRenderer->Draw_Sentence( white ); // Draw powerup count if ( RightPowerupIconList[i]->Number != 0 ) { WideStringClass num(0,true); num.Format( L"%d", RightPowerupIconList[i]->Number ); PowerupTextRenderer->Build_Sentence( num ); PowerupTextRenderer->Set_Location( Vector2( draw_box.Right - 12, draw_box.Top + 1 ) ); PowerupTextRenderer->Draw_Sentence( white ); } RectClass icon_box = RightPowerupIconList[i]->IconBox; icon_box += draw_box.Upper_Left(); RightPowerupIconList[i]->Renderer->Reset(); RightPowerupIconList[i]->Renderer->Add_Quad( icon_box, RightPowerupIconList[i]->UV, green ); // Drop the remaining icons down if ( i == 0 && RightAnimateTimer > ANIMATE_TIME * 0.5f ) { box += Vector2( 0, ((2*RightAnimateTimer/ANIMATE_TIME)-1) * POWERUP_BOX_SPACING ); } box -= Vector2( 0, POWERUP_BOX_SPACING ); } } static void Powerup_Render( void ) { #if 0 // No boxes PowerupBoxRenderer->Render(); #endif int i; for ( i = 0; i < MAX_ICONS && i < LeftPowerupIconList.Count(); i++ ) { LeftPowerupIconList[i]->Renderer->Render(); } for ( i = 0; i < MAX_ICONS && i < RightPowerupIconList.Count(); i++ ) { RightPowerupIconList[i]->Renderer->Render(); } PowerupTextRenderer->Render(); } /* ** Weapon Display */ Render2DClass * WeaponBoxRenderer; Render2DClass * WeaponImageRenderer; Render2DTextClass * WeaponClipCountRenderer; Render2DTextClass * WeaponTotalCountRenderer; Render2DSentenceClass * WeaponNameRenderer; Vector2 WeaponBase; WeaponClass * _LastHUDWeapon = NULL; int _LastVehicleSeat = -1; #define WEAPON_OFFSET 100, 110 //#define WEAPON_BOX_UV 0,0,95,95 #define SNIPER_UV 90,0,255,53 #define SNIPER_OFFSET -80,-4 static void HUD_Help_Text_Init( void ) { // // Load the font... // FontCharsClass *font = StyleMgrClass::Peek_Font( StyleMgrClass::FONT_INGAME_BIG_TXT ); WWASSERT (font != NULL); // // Configure the renderer // HUDHelpTextRenderer = new Render2DSentenceClass; HUDHelpTextRenderer->Set_Font( font ); HUDHelpTextExtents.Set (0, 0); HUDHelpTextTimer = 0; HUDHelpTextState = HUD_HELP_TEXT_DISPLAYING; return ; } static void HUD_Help_Text_Render( void ) { const float HUD_HELP_TEXT_FADE_TIME = 2.0F; const float HUD_HELP_TEXT_DISPLAY_TIME = 2.0F; const WideStringClass &string = HUDInfo::Get_HUD_Help_Text(); bool is_empty = string.Is_Empty(); // // Rebuild the renderer (if necessary) // if (HUDInfo::Is_HUD_Help_Text_Dirty()) { HUDHelpTextState = HUD_HELP_TEXT_DISPLAYING; HUDInfo::Set_Is_HUD_Help_Text_Dirty( false ); HUDHelpTextRenderer->Reset(); if (is_empty == false) { HUDHelpTextRenderer->Build_Sentence( string ); HUDHelpTextTimer = HUD_HELP_TEXT_DISPLAY_TIME; } HUDHelpTextExtents = HUDHelpTextRenderer->Get_Text_Extents (string); } // // Draw the text if there's something to draw // if ( is_empty == false ) { HUDHelpTextRenderer->Reset_Polys(); // // Render the text above the reticle // Vector2 reticle_offset = COMBAT_CAMERA->Get_Camera_Target_2D_Offset(); const RectClass &screen_rect = Render2DClass::Get_Screen_Resolution(); float x_pos = screen_rect.Center ().X - (HUDHelpTextExtents.X * 0.5F); float y_pos = screen_rect.Center ().Y - (HUDHelpTextExtents.Y); y_pos -= (RETICLE_HEIGHT * screen_rect.Height () * 0.25F); HUDHelpTextRenderer->Set_Location( Vector2( x_pos, y_pos ) ); HUDHelpTextRenderer->Draw_Sentence( RGB_TO_INT32 (0, 0, 0) ); HUDHelpTextRenderer->Set_Location( Vector2( x_pos-1, y_pos-1 ) ); HUDHelpTextRenderer->Draw_Sentence( VRGB_TO_INT32 (HUDInfo::Get_HUD_Help_Text_Color ()) ); // // Fade the text out (if necessary) // if (HUDHelpTextState == HUD_HELP_TEXT_FADING) { float percent = WWMath::Clamp ((HUDHelpTextTimer / HUD_HELP_TEXT_FADE_TIME), 0.0F, 1.0F); HUDHelpTextRenderer->Force_Alpha (percent * 0.5F); } else { HUDHelpTextRenderer->Force_Alpha (0.5F); } // // Render the quads // HUDHelpTextRenderer->Render(); // // Advance to the next state // HUDHelpTextTimer -= TimeManager::Get_Frame_Seconds (); if (HUDHelpTextTimer <= 0) { HUDHelpTextState ++; // // Clear the text if necessary // if (HUDHelpTextState >= HUD_HELP_TEXT_DONE) { HUDInfo::Set_HUD_Help_Text( L"" ); HUDHelpTextRenderer->Reset(); } else if (HUDHelpTextState == HUD_HELP_TEXT_FADING) { HUDHelpTextTimer = HUD_HELP_TEXT_FADE_TIME; } } } return ; } static void HUD_Help_Text_Shutdown( void ) { delete HUDHelpTextRenderer; HUDHelpTextRenderer = NULL; return ; } static void Weapon_Init( void ) { WeaponBoxRenderer = new Render2DClass(); WeaponBoxRenderer->Set_Texture( HUD_MAIN_TEXTURE ); WeaponBoxRenderer->Set_Coordinate_Range( Render2DClass::Get_Screen_Resolution() ); RectClass box_uv( WEAPON_BOX_UV_UL, WEAPON_BOX_UV_LR ); RectClass draw_box = box_uv; box_uv.Scale( Vector2( 1.0f/256.0f, 1.0f/256.0f ) ); draw_box += Render2DClass::Get_Screen_Resolution().Lower_Right() - Vector2( WEAPON_OFFSET ) - draw_box.Upper_Left(); WeaponBoxRenderer->Add_Quad( draw_box, box_uv ); WeaponBase = draw_box.Upper_Left(); WeaponImageRenderer = new Render2DClass(); WeaponImageRenderer->Set_Coordinate_Range( Render2DClass::Get_Screen_Resolution() ); FontCharsClass *chars_font = StyleMgrClass::Peek_Font( StyleMgrClass::FONT_INGAME_TXT ); WeaponNameRenderer = new Render2DSentenceClass(); WeaponNameRenderer->Set_Font( chars_font ); // WeaponNameRenderer->Set_Coordinate_Range( Render2DClass::Get_Screen_Resolution() ); Font3DInstanceClass * font = WW3DAssetManager::Get_Instance()->Get_Font3DInstance( LARGE_FONT ); SET_REF_OWNER( font ); WeaponClipCountRenderer = new Render2DTextClass( font ); WeaponClipCountRenderer->Set_Coordinate_Range( Render2DClass::Get_Screen_Resolution() ); font->Release_Ref(); font = WW3DAssetManager::Get_Instance()->Get_Font3DInstance( SMALL_FONT ); SET_REF_OWNER( font ); WeaponTotalCountRenderer = new Render2DTextClass( font ); WeaponTotalCountRenderer->Set_Coordinate_Range( Render2DClass::Get_Screen_Resolution() ); font->Release_Ref(); _LastHUDWeapon = NULL; _LastVehicleSeat = -1; } static void Weapon_Shutdown( void ) { delete WeaponBoxRenderer; WeaponBoxRenderer = NULL; delete WeaponImageRenderer; WeaponImageRenderer = NULL; delete WeaponNameRenderer; WeaponNameRenderer = NULL; delete WeaponClipCountRenderer; WeaponClipCountRenderer = NULL; delete WeaponTotalCountRenderer; WeaponTotalCountRenderer = NULL; } #define CLIP_ROUNDS_OFFSET 15,27 #define TOTAL_ROUNDS_OFFSET 65,34 #define WEAPON_NAME_OFFSET -10, 95 float LastClipCount = 0; float CenterClipCountTimer = 0; const float CENTER_CLIP_COUNT_TIME = 2.0f; enum { SEAT_DRIVER = 0, SEAT_GUNNER, SEAT_PASENGER, }; const char * _Seat_Textures[3] = { "hud_driverseat.tga", // SEAT_DRIVER = 0, "hud_gunseat.tga", // SEAT_GUNNER, "hud_passseat.tga", // SEAT_PASENGER, }; static void Weapon_Reset( void ) { _LastHUDWeapon = (WeaponClass *)0xFFFFFFFF; // force weapon to re-draw next _LastVehicleSeat = -1; // force vehicle seat to re-draw next } static void Weapon_Update( void ) { WeaponClass * weapon = NULL; if ( COMBAT_STAR ) { weapon = COMBAT_STAR->Get_Weapon(); if ( COMBAT_STAR->Get_Vehicle() ) { weapon = COMBAT_STAR->Get_Vehicle()->Get_Weapon(); } } WeaponClipCountRenderer->Reset(); WeaponTotalCountRenderer->Reset(); if ( weapon != NULL ) { // StringClass text; // text.Format( "%03d", weapon->Get_Clip_Rounds() ); WCHAR tmp_text[5]; if ( weapon->Get_Clip_Rounds() == -1 ) { //text.Format( "999", weapon->Get_Total_Rounds() ); tmp_text[0]='9'; tmp_text[1]='9'; tmp_text[2]='9'; tmp_text[3]=0; } else { Generate_WChar_Text_From_Number(tmp_text,3,3,weapon->Get_Clip_Rounds()); } WeaponClipCountRenderer->Set_Location( WeaponBase + Vector2( CLIP_ROUNDS_OFFSET ) ); WeaponClipCountRenderer->Draw_Text( tmp_text ); if ( LastClipCount != weapon->Get_Clip_Rounds() ) { LastClipCount = weapon->Get_Clip_Rounds(); CenterClipCountTimer = CENTER_CLIP_COUNT_TIME; } if ( CenterClipCountTimer > 0 ) { // Also draw the above at the center Vector2 center_clip_count_offset = Render2DClass::Get_Screen_Resolution().Center(); center_clip_count_offset.X *= 1.5; float fade = WWMath::Clamp( CenterClipCountTimer, 0, 1 ); RectClass uv; uv.Set( BULLET_ICON_UV_UL, BULLET_ICON_UV_LR ); RectClass draw = uv; uv.Scale( INFO_UV_SCALE ); draw += center_clip_count_offset + BULLET_ICON_OFFSET - draw.Upper_Left(); InfoRenderer->Add_Quad( draw, uv, COLOR( fade ) ); WeaponClipCountRenderer->Set_Location( draw.Upper_Right() + Vector2( 4, 15 ) ); WeaponClipCountRenderer->Draw_Text( tmp_text, COLOR( fade ) ); CenterClipCountTimer -= TimeManager::Get_Frame_Seconds(); } if ( weapon->Get_Total_Rounds() == -1 ) { //text.Format( "999", weapon->Get_Total_Rounds() ); tmp_text[0]='9'; tmp_text[1]='9'; tmp_text[2]='9'; tmp_text[3]=0; } else { // text.Format( "%03d", weapon->Get_Total_Rounds() - weapon->Get_Clip_Rounds() ); Generate_WChar_Text_From_Number(tmp_text,3,3,weapon->Get_Total_Rounds() - weapon->Get_Clip_Rounds()); } WeaponTotalCountRenderer->Set_Location( WeaponBase + Vector2( TOTAL_ROUNDS_OFFSET ) ); WeaponTotalCountRenderer->Draw_Text( tmp_text ); } // If in vehicle, don't draw the weapon icon and name, // draw a seat icon and the vehicle name if ( COMBAT_STAR->Get_Vehicle() ) { int seat = SEAT_PASENGER; if ( COMBAT_STAR->Get_Vehicle()->Get_Driver() == COMBAT_STAR ) { seat = SEAT_DRIVER; } else if ( COMBAT_STAR->Get_Vehicle()->Get_Gunner() == COMBAT_STAR ) { seat = SEAT_GUNNER; } if ( _LastVehicleSeat != seat ) { _LastVehicleSeat = seat; _LastHUDWeapon = (WeaponClass *)0xFFFFFFFF; // force weapon to re-draw next WeaponImageRenderer->Reset(); StringClass filename = _Seat_Textures[seat]; WeaponImageRenderer->Set_Texture( filename ); Vector2 offset( 16, 34 ); RectClass icon_box( 0,0,64,64 ); icon_box += WeaponBase + offset - icon_box.Upper_Left(); WeaponImageRenderer->Add_Quad( icon_box ); // Draw Name Backdrop WeaponNameRenderer->Reset(); WideStringClass name(COMBAT_STAR->Get_Vehicle()->Get_Vehicle_Name(),true); WeaponNameRenderer->Build_Sentence( name ); Vector2 text_size = WeaponNameRenderer->Get_Text_Extents( name ); WeaponNameRenderer->Set_Location( Render2DClass::Get_Screen_Resolution().Lower_Right() - text_size ); WeaponNameRenderer->Draw_Sentence(); } } else if ( _LastHUDWeapon != weapon ) { // Update the weapon icon WWPROFILE( "Weapon Change" ); _LastHUDWeapon = weapon; _LastVehicleSeat = -1; // force vehicle seat to re-draw next WeaponImageRenderer->Reset(); WeaponNameRenderer->Reset(); if ( weapon != NULL ) { StringClass filename( HUD_WEAPONS_TEXTURE, true ); RectClass uv( 0,64,128,128 ); Vector2 offset( -24, 38 ); const WeaponDefinitionClass * def = weapon->Get_Definition(); if ( !def->IconTextureName.Is_Empty() ) { Strip_Path_From_Filename( filename, def->IconTextureName ); uv = def->IconTextureUV; offset = def->IconOffset; #if 0 // Used to find offsets static Vector2 tweak_add(0,0); Vector2 add(0,0); add.X += Input::Get_Amount( INPUT_FUNCTION_MOVE_LEFT ) - Input::Get_Amount( INPUT_FUNCTION_MOVE_RIGHT ); add.Y += Input::Get_Amount( INPUT_FUNCTION_MOVE_FORWARD ) - Input::Get_Amount( INPUT_FUNCTION_MOVE_BACKWARD ); tweak_add -= add; offset += tweak_add; _LastHUDWeapon = NULL; if ( add.Length() != 0 ) { Debug_Say(( "%s offset %f %f\n", def->Get_Name(), offset.X, offset.Y )); } #endif } RectClass icon_box = uv; icon_box += WeaponBase + offset - icon_box.Upper_Left(); { StringClass new_name(true); Strip_Path_From_Filename( new_name, filename ); WeaponImageRenderer->Set_Texture( new_name ); } // SurfaceClass::SurfaceDescription surface_desc; // WeaponImageRenderer->Peek_Texture()->Get_Level_Description( surface_desc ); // float size = surface_desc.Width; // Assume square float size = WeaponImageRenderer->Peek_Texture()->Get_Width(); // Assume square if ( size > 0 ) { uv.Scale( Vector2( 1/size, 1/size ) ); } int color = 0xFF00FF00; // green WeaponImageRenderer->Add_Quad( icon_box, uv, color ); // Draw Name Backdrop // Right justify Name WideStringClass name(0,true); // = L"Rocket Launcher"; name = TranslateDBClass::Get_String( def->IconNameID ); WeaponNameRenderer->Build_Sentence( name ); Vector2 text_size = WeaponNameRenderer->Get_Text_Extents( name ) + Vector2( 1, 0 ); WeaponNameRenderer->Set_Location( Render2DClass::Get_Screen_Resolution().Lower_Right() - text_size ); WeaponNameRenderer->Draw_Sentence(); } } } static void Weapon_Render( void ) { WeaponBoxRenderer->Render(); WeaponImageRenderer->Render(); WeaponNameRenderer->Render(); WeaponClipCountRenderer->Render(); WeaponTotalCountRenderer->Render(); } /* ** Weapon Chart Display */ Render2DClass * WeaponChartBoxRenderer; static DynamicVectorClass WeaponChartIcons; Render2DSentenceClass * WeaponChartKeynameRenderer; float WeaponChartTimer; #define WEAPON_CHART_TIME 3.0f static void Weapon_Chart_Init( void ) { WeaponChartBoxRenderer = new Render2DClass(); WeaponChartBoxRenderer->Enable_Texturing( false ); WeaponChartBoxRenderer->Set_Coordinate_Range( Render2DClass::Get_Screen_Resolution() ); FontCharsClass *chars_font = StyleMgrClass::Peek_Font( StyleMgrClass::FONT_INGAME_TXT ); WeaponChartKeynameRenderer = new Render2DSentenceClass(); WeaponChartKeynameRenderer->Set_Font( chars_font ); } static void Weapon_Chart_Shutdown( void ) { delete WeaponChartBoxRenderer; WeaponChartBoxRenderer = NULL; for ( int i = 0; i < WeaponChartIcons.Count(); i++) { delete WeaponChartIcons[i]; WeaponChartIcons[i] = NULL; } WeaponChartIcons.Delete_All(); delete WeaponChartKeynameRenderer; WeaponChartKeynameRenderer = NULL; } Vector2 WeaponChartBase( 0.11f, 0.05f ); Vector2 WeaponChartSpacing( 0.075f, 0.05f ); float WeaponChartIconScale = 0.45f / 640.0f; static void Clear_Weapon_Chart_Icons( void ) { if ( WeaponChartIcons.Count != 0 ) { int i; for ( i = 0; i < WeaponChartIcons.Count(); i++) { delete WeaponChartIcons[i]; WeaponChartIcons[i] = NULL; } WeaponChartIcons.Delete_All(); WeaponChartKeynameRenderer->Reset(); } } static void Build_Weapon_Chart_Icons( void ) { WeaponBagClass * weapon_bag = COMBAT_STAR->Get_Weapon_Bag(); Clear_Weapon_Chart_Icons(); float screen_scale = Render2DClass::Get_Screen_Resolution().Width(); Vector2 pos = WeaponChartBase * screen_scale; // For each column... for ( int column = 1; column <= 10; column++ ) { // Add column header int key = Input::Get_Primary_Key_For_Function(INPUT_FUNCTION_SELECT_WEAPON_0 + (column%10) ); WideStringClass name(0,true); Input::Get_Translated_Key_Name( key, name ); WeaponChartKeynameRenderer->Build_Sentence( name ); Vector2 text_size = WeaponChartKeynameRenderer->Get_Text_Extents( name ); Vector2 text_offset = pos - text_size/2 - Vector2( 0, WeaponChartSpacing.Y * screen_scale * 0.75f ); text_offset.X = (int)text_offset.X; text_offset.Y = (int)text_offset.Y; WeaponChartKeynameRenderer->Set_Location( text_offset ); WeaponChartKeynameRenderer->Draw_Sentence(); // Draw weapons in that column for ( int i = 0; i < weapon_bag->Get_Count(); i++ ) { WeaponClass * weapon = weapon_bag->Peek_Weapon( i ); if ( weapon != NULL ) { if ( (int)weapon->Get_Key_Number() != (column%10) ) { continue; } StringClass filename( HUD_WEAPONS_TEXTURE, true ); RectClass uv( 0,64,128,128 ); Vector2 offset( -40, 40 ); const WeaponDefinitionClass * def = weapon->Get_Definition(); if ( !def->IconTextureName.Is_Empty() ) { Strip_Path_From_Filename( filename, def->IconTextureName ); uv = def->IconTextureUV; offset = def->IconOffset; } RectClass icon_box = uv; // icon_box += pos - icon_box.Upper_Left(); // icon_box += offset - icon_box.Upper_Left() + pos; icon_box += pos - icon_box.Center(); icon_box.Scale_Relative_Center( WeaponChartIconScale * screen_scale ); pos.Y += WeaponChartSpacing.Y * screen_scale; // Draw Icon Render2DClass * renderer = new Render2DClass(); WeaponChartIcons.Add( renderer ); renderer->Set_Coordinate_Range( Render2DClass::Get_Screen_Resolution() ); StringClass new_name(true); Strip_Path_From_Filename( new_name, filename ); renderer->Set_Texture( new_name ); if ( renderer->Peek_Texture() != NULL ) { // SurfaceClass::SurfaceDescription surface_desc; // renderer->Peek_Texture()->Get_Level_Description( surface_desc ); // float size = surface_desc.Width; // Assume square float size = renderer->Peek_Texture()->Get_Width(); // Assume square if ( size > 0 ) { uv.Scale( Vector2( 1/size, 1/size ) ); } } renderer->Add_Quad( icon_box, uv ); } } // Goto next column pos.Y = WeaponChartBase.Y * screen_scale; pos.X += WeaponChartSpacing.X * screen_scale; } } bool ForceChartRebuild = false; void HUDClass::Force_Weapon_Chart_Update( void ) { ForceChartRebuild = true; } void HUDClass::Force_Weapon_Chart_Display( void ) { WeaponChartTimer = WEAPON_CHART_TIME; } static void Weapon_Chart_Update( void ) { if ( COMBAT_STAR == NULL || COMBAT_STAR->Get_Weapon_Bag() == NULL || COMBAT_STAR->Get_Vehicle() != NULL ) { Clear_Weapon_Chart_Icons(); return; } int i; WeaponBagClass * weapon_bag = COMBAT_STAR->Get_Weapon_Bag(); if ( weapon_bag->HUD_Is_Changed() ) { weapon_bag->HUD_Reset_Changed(); WeaponChartTimer = WEAPON_CHART_TIME; } WeaponChartTimer -= TimeManager::Get_Frame_Seconds(); if ( WeaponChartTimer <= 0 ) { return; } // Rebuild the icons if necessary // subtract 1 because the first is always null if ( ForceChartRebuild || (weapon_bag->Get_Count()-1 != WeaponChartIcons.Count()) ) { ForceChartRebuild = false; Debug_Say(( "Build icons\n" )); Build_Weapon_Chart_Icons(); } float alpha = WWMath::Clamp( WeaponChartTimer, 0, 1 ); WeaponChartBoxRenderer->Reset(); // For each column... int index = 0; for ( int column = 1; column <= 10; column++ ) { // Update intensities in that column for ( i = 0; i < weapon_bag->Get_Count(); i++ ) { WeaponClass * weapon = weapon_bag->Peek_Weapon( i ); if ( weapon != NULL ) { if ( (int)weapon->Get_Key_Number() != (column%10) ) { continue; } long color = 0x000FF00; // Dim if ( weapon_bag->Get_Index() == i ) { color = 0x0000FF00; // Bright } // Draw yellow if empty or reloading // if ( weapon->Is_Reloading() || weapon->Is_Switching() || weapon->Get_Total_Rounds() == 0 ) { // if ( weapon->Is_Switching() || weapon->Get_Total_Rounds() == 0 ) { if ( weapon->Get_Total_Rounds() == 0 ) { color = 0x00FFFF00; // Dim yellow if ( weapon_bag->Get_Index() == i ) { color = 0x00FFFF00; // Bright yellow } } #if 01 if ( weapon_bag->Get_Index() == i ) { color = COLOR( alpha, color ); } else { color = COLOR( alpha * 0.5f, color ); } #endif WeaponChartIcons[index]->Force_Color( color ); index++; } } } WeaponChartKeynameRenderer->Force_Alpha( alpha ); } static void Weapon_Chart_Render( void ) { if ( WeaponChartTimer <= 0 ) { return; } WeaponChartBoxRenderer->Render(); for ( int i = 0; i < WeaponChartIcons.Count(); i++) { WeaponChartIcons[i]->Render(); } WeaponChartKeynameRenderer->Render(); } /* ** Damage Display */ Render2DClass * DamageRenderer; const int NUM_DAMAGE_INDICATORS = 8; float DamageIndicatorIntensity[ NUM_DAMAGE_INDICATORS ]; bool DamageIndicatorIntensityChanging; bool DamageIndicatorOrientation; static void Damage_Reset( void ) { for ( int i = 0; i < NUM_DAMAGE_INDICATORS; i++ ) { DamageIndicatorIntensity[ i ] = 0; } DamageIndicatorIntensityChanging = true; CombatManager::Clear_Star_Damage_Direction(); } static void Damage_Init( void ) { DamageRenderer = new Render2DClass(); DamageRenderer->Set_Texture( HUD_MAIN_TEXTURE ); DamageRenderer->Set_Coordinate_Range( Render2DClass::Get_Screen_Resolution() ); DamageRenderer->Enable_Additive( true ); Damage_Reset(); } static void Damage_Shutdown( void ) { delete DamageRenderer; DamageRenderer = NULL; } static void Damage_Add_Indicator( int index, float start_x, float start_y, float end_x, float end_y ) { Vector2 vert[4]; vert[0] = Vector2( start_x, start_y ); vert[1] = Vector2( start_x, end_y ); vert[2] = Vector2( end_x, start_y ); vert[3] = Vector2( end_x, end_y ); if ( !CombatManager::Is_First_Person() ) { for ( int i = 0; i < 4; i++ ) { vert[i].X *= WWMath::Fabs(1 + vert[i].Y); // Skew vert[i].Y /= 2; // Squash vertical vert[i].Y += 0.25f; // Lower } } for ( int i = 0; i < 4; i++ ) { // Numbers are -0.5 to 0.5, switch them to pixels, to match the info_renderer mode vert[i].X = (vert[i].X + 0.5f) * Render2DClass::Get_Screen_Resolution().Width(); vert[i].Y = (vert[i].Y + 0.5f) * Render2DClass::Get_Screen_Resolution().Height(); } RectClass uv( DAMAGE_1_UV_UL, DAMAGE_1_UV_LR ); if ( index & 1 ) { uv = RectClass( DAMAGE_2_UV_UL, DAMAGE_2_UV_LR ); } uv.Scale( INFO_UV_SCALE ); unsigned long color_bits = (int)(DamageIndicatorIntensity[index] * 255) & 0x000000FF; unsigned long color = color_bits | color_bits<<8 | color_bits<<16; switch (index) { case 3: case 4: DamageRenderer->Add_Quad( vert[1], vert[3], vert[0], vert[2], uv, color ); break; case 5: case 6: DamageRenderer->Add_Quad( vert[0], vert[1], vert[2], vert[3], uv, color ); break; case 7: case 0: DamageRenderer->Add_Quad( vert[2], vert[0], vert[3], vert[1], uv, color ); break; case 1: case 2: DamageRenderer->Add_Quad( vert[3], vert[2], vert[1], vert[0], uv, color ); break; } } static void Damage_Update( void ) { DamageRenderer->Reset(); if (Input::Are_Damage_Indicators_Enabled () == false) { return ; } int new_damage = CombatManager::Get_Star_Damage_Direction(); //new_damage = 0xFF; if ( new_damage != 0 ) { DamageIndicatorIntensityChanging = true; } if ( !DamageIndicatorIntensityChanging && DamageIndicatorOrientation == CombatManager::Is_First_Person() ) { return; } // DamageRenderer->Reset(); DamageIndicatorOrientation = CombatManager::Is_First_Person(); DamageIndicatorIntensityChanging = false; // Update the intensities CombatManager::Clear_Star_Damage_Direction(); for ( int i = 0; i < NUM_DAMAGE_INDICATORS; i++ ) { if ( new_damage & (1< 0 ) { DamageIndicatorIntensity[ i ] -= TimeManager::Get_Frame_Seconds(); // and fade it away DamageIndicatorIntensity[ i ] = WWMath::Clamp( DamageIndicatorIntensity[ i ], 0, 1 ); DamageIndicatorIntensityChanging = true; } } } // Redraw the indicators #if 0 const float HORIZ_WIDTH = 58.0f/640.0f; const float HORIZ_HEIGHT = 20.0f/480.0f; const float VERT_WIDTH = 20.0f/640.0f; const float VERT_HEIGHT = 58.0f/480.0f; const float OFFSET_X = 220.0f/640.0f; const float OFFSET_Y = 190.0f/480.0f; const float DIAG_WIDTH = 46.0f/640.0f; const float DIAG_HEIGHT = 46.0f/480.0f; const float DIAG_OFFSET_X = 160.0f/640.0f; const float DIAG_OFFSET_Y = 130.0f/480.0f; #else float HORIZ_WIDTH = HORIZ_DAMAGE_SIZE.U/640.0f; float HORIZ_HEIGHT = HORIZ_DAMAGE_SIZE.V/480.0f; float VERT_WIDTH = VERT_DAMAGE_SIZE.U/640.0f; float VERT_HEIGHT = VERT_DAMAGE_SIZE.V/480.0f; float OFFSET_X = HV_DAMAGE_OFFSET.U/640.0f; float OFFSET_Y = HV_DAMAGE_OFFSET.V/480.0f; float DIAG_WIDTH = DIAG_DAMAGE_SIZE.U/640.0f; float DIAG_HEIGHT = DIAG_DAMAGE_SIZE.V/480.0f; float DIAG_OFFSET_X = DIAG_DAMAGE_OFFSET.U/640.0f; float DIAG_OFFSET_Y = DIAG_DAMAGE_OFFSET.V/480.0f; #endif Damage_Add_Indicator( 0, -HORIZ_WIDTH/2, -OFFSET_Y-HORIZ_HEIGHT/2, HORIZ_WIDTH/2, -OFFSET_Y+HORIZ_HEIGHT/2 ); Damage_Add_Indicator( 2, OFFSET_X-VERT_WIDTH/2, -VERT_HEIGHT/2, OFFSET_X+VERT_WIDTH/2, VERT_HEIGHT/2 ); Damage_Add_Indicator( 4, -HORIZ_WIDTH/2, OFFSET_Y-HORIZ_HEIGHT/2, HORIZ_WIDTH/2, OFFSET_Y+HORIZ_HEIGHT/2 ); Damage_Add_Indicator( 6, -OFFSET_X-VERT_WIDTH/2, -VERT_HEIGHT/2, -OFFSET_X+VERT_WIDTH/2, VERT_HEIGHT/2 ); Damage_Add_Indicator( 1, DIAG_OFFSET_X-DIAG_WIDTH/2, -DIAG_OFFSET_Y-DIAG_HEIGHT/2, DIAG_OFFSET_X+DIAG_WIDTH/2, -DIAG_OFFSET_Y+DIAG_HEIGHT/2 ); Damage_Add_Indicator( 3, DIAG_OFFSET_X-DIAG_WIDTH/2, DIAG_OFFSET_Y-DIAG_HEIGHT/2, DIAG_OFFSET_X+DIAG_WIDTH/2, DIAG_OFFSET_Y+DIAG_HEIGHT/2 ); Damage_Add_Indicator( 5, -DIAG_OFFSET_X-DIAG_WIDTH/2, DIAG_OFFSET_Y-DIAG_HEIGHT/2, -DIAG_OFFSET_X+DIAG_WIDTH/2, DIAG_OFFSET_Y+DIAG_HEIGHT/2 ); Damage_Add_Indicator( 7, -DIAG_OFFSET_X-DIAG_WIDTH/2, -DIAG_OFFSET_Y-DIAG_HEIGHT/2, -DIAG_OFFSET_X+DIAG_WIDTH/2, -DIAG_OFFSET_Y+DIAG_HEIGHT/2 ); } void HUDClass::Damage_Render( void ) { DamageRenderer->Render(); } /* ** Target Display */ Render2DClass * TargetRenderer; Render2DClass * TargetBoxRenderer; Render2DSentenceClass * TargetNameRenderer; Render2DSentenceClass * InfoDebugRenderer; WideStringClass TargetNameString; // Cache the current target name string so that we know when the string changes Vector2 TargetNameLocation; // Cache the name location as well static void Target_Init( void ) { TargetRenderer = new Render2DClass(); TargetRenderer->Set_Texture( HUD_MAIN_TEXTURE ); TargetRenderer->Set_Coordinate_Range( Render2DClass::Get_Screen_Resolution() ); TargetBoxRenderer = new Render2DClass(); TargetBoxRenderer->Enable_Texturing( false ); TargetBoxRenderer->Set_Coordinate_Range( Render2DClass::Get_Screen_Resolution() ); FontCharsClass *chars_font = StyleMgrClass::Peek_Font( StyleMgrClass::FONT_INGAME_TXT ); TargetNameRenderer = new Render2DSentenceClass(); TargetNameRenderer->Set_Font( chars_font ); InfoDebugRenderer = new Render2DSentenceClass(); InfoDebugRenderer->Set_Font( chars_font ); // TargetNameRenderer->Set_Coordinate_Range( Render2DClass::Get_Screen_Resolution() ); } static void Target_Shutdown( void ) { delete TargetRenderer; TargetRenderer = NULL; delete TargetBoxRenderer; TargetBoxRenderer = NULL; delete TargetNameRenderer; TargetNameRenderer = NULL; TargetNameString=""; delete InfoDebugRenderer; InfoDebugRenderer = NULL; } bool InfoDebug = false; static RectClass Get_Target_Box( PhysicalGameObj * obj ); static void Target_Box_Edge( const Vector2 & a, const Vector2 & b, unsigned int color ); static void Target_Update( void ) { TargetRenderer->Reset(); TargetBoxRenderer->Reset(); // TargetNameRenderer->Reset(); InfoDebugRenderer->Reset(); HUDInfo::Update_Info_Object(); static float box_zoom_size = 0; DamageableGameObj * d_obj = HUDInfo::Get_Info_Object(); if ( d_obj != NULL ) { PhysicalGameObj * p_obj = d_obj->As_PhysicalGameObj(); BuildingGameObj * building = d_obj->As_BuildingGameObj(); DamageableGameObj * obj = d_obj; if ( obj && COMBAT_STAR ) { box_zoom_size += TimeManager::Get_Frame_Seconds() * 4; box_zoom_size = WWMath::Clamp( box_zoom_size, 0, 1 ); int color = HUDGlobalSettingsDef::Get_Instance()->Get_No_Relation_Color().Convert_To_ARGB(); if ( p_obj != NULL ) { if ( COMBAT_STAR->Is_Teammate(p_obj) ) { color = HUDGlobalSettingsDef::Get_Instance()->Get_Friendly_Color().Convert_To_ARGB(); } else if ( COMBAT_STAR->Is_Enemy(p_obj) ) { color = HUDGlobalSettingsDef::Get_Instance()->Get_Enemy_Color().Convert_To_ARGB(); } } if ( building != NULL ) { // if ( building->Is_GDI() ) { if ( COMBAT_STAR->Is_Teammate(building) ) { color = HUDGlobalSettingsDef::Get_Instance()->Get_Friendly_Color().Convert_To_ARGB(); // } else if ( building->Is_Nod() ) { } else if ( COMBAT_STAR->Is_Enemy(building) ) { color = HUDGlobalSettingsDef::Get_Instance()->Get_Enemy_Color().Convert_To_ARGB(); } } RectClass box = Render2DClass::Get_Screen_Resolution(); if ( obj->As_PhysicalGameObj() ) { box = Get_Target_Box( obj->As_PhysicalGameObj() ); } else { // Build a box for the buildings box.Scale_Relative_Center( 0.3f ); // center on cursor reticle Vector2 new_center = (COMBAT_CAMERA->Get_Camera_Target_2D_Offset() * 0.5f ); new_center.Y *= -1.0f; new_center += Vector2( 0.5f, 0.5f ); new_center.X *= Render2DClass::Get_Screen_Resolution().Right; new_center.Y *= Render2DClass::Get_Screen_Resolution().Bottom; box += new_center - box.Center(); } // Scale the box to let it zoom in if ( box_zoom_size < 1 ) { box.Scale_Relative_Center( 1 + ((1-box_zoom_size) * 0.3f) ); } box.Snap_To_Units( Vector2( 1, 1 ) ); // Clamp box to fit on screen; RectClass res = Render2DClass::Get_Screen_Resolution(); if ( box.Top < 0 ) { box.Top = 0; } if ( box.Left < 0 ) { box.Left = 0; } if ( box.Right > res.Right-1 ) { box.Right = res.Right-1; } // Leave room for info at the bottom if ( box.Bottom > res.Bottom - 26 ) { box.Bottom = res.Bottom - 26; } Target_Box_Edge( box.Upper_Left(), box.Upper_Right(), color ); Target_Box_Edge( box.Upper_Left(), box.Lower_Left(), color ); Target_Box_Edge( box.Lower_Right(), box.Upper_Right(), color ); Target_Box_Edge( box.Lower_Right(), box.Lower_Left(), color ); RectClass uv( TARGET_HEALTH_R_UV_UL, TARGET_HEALTH_R_UV_LR ); RectClass draw = uv; RectClass draw2; bool draw_health = obj->Is_Health_Bar_Displayed(); if ( draw_health ) { float health_percent = 0; // float health = 0; const DefenseObjectClass * def = obj->Get_Defense_Object(); if ( def ) { // health = def->Get_Health(); // health_percent = WWMath::Clamp( def->Get_Health() / def->Get_Health_Max(), 0, 1 ); float health_max = def->Get_Health_Max(); float shield_max = def->Get_Shield_Strength_Max(); float max = health_max + shield_max; float health = def->Get_Health(); float shield = def->Get_Shield_Strength(); // if ( health_max && ((health/health_max) < 0.25) ) { // shield *= ((health/health_max) / 0.25f); // } // Display less shield as health drops if ( health_max ) { shield *= (health/health_max); } float total = health + shield; if ( max != 0 ) { health_percent = total / max; health_percent = WWMath::Clamp( health_percent, 0, 1 ); } } int health_color = Get_Health_Color( health_percent ); // Draw Health static float power_flash = 0; power_flash += TimeManager::Get_Frame_Seconds(); power_flash = WWMath::Wrap( power_flash, 0, 2 ); RectClass uv3( POWER_OUT_ICON_UV_UL, POWER_OUT_ICON_UV_LR ); RectClass draw3 = uv3; uv3.Scale( INFO_UV_SCALE ); RectClass black( HEALTH_BACK_UV_UL, HEALTH_BACK_UV_LR ); black.Scale( INFO_UV_SCALE ); uv.Scale( INFO_UV_SCALE ); // draw += box.Upper_Left() - draw.Lower_Left() - Vector2( 0, 1 ); draw += box.Lower_Left() - draw.Upper_Left() + Vector2( 0, 18 ); // draw += Vector2( (box.Width() - draw.Width())/2 + 10, 0 ); // Center draw += Vector2( (box.Width() - draw.Width())/2 + 2, 0 ); // Center draw3 += draw.Center() - draw3.Center(); // Draw background draw.Inflate( Vector2( 1, 1 ) ); TargetRenderer->Add_Quad( draw, black ); draw.Inflate( Vector2( -1, -1 ) ); draw.Right = draw.Left + draw.Width() * health_percent; uv.Right = uv.Left + uv.Width() * health_percent; TargetRenderer->Add_Quad( draw, uv, health_color ); // power out if ( power_flash < 1 ) { // TargetRenderer->Add_Quad( draw3, uv3 ); } uv.Set( TARGET_HEALTH_L_UV_UL, TARGET_HEALTH_L_UV_LR ); draw2 = uv; #if 0 uv.Scale( INFO_UV_SCALE ); draw2 += draw.Upper_Left() - draw2.Upper_Right(); TargetRenderer->Add_Quad( draw2, uv, health_color ); WideStringClass num(0,true); if ( health < 1 && health > 0 ) { health = 1; } num.Format( L"%d", (int)health ); TargetNameRenderer->Build_Sentence( num ); Vector2 text_size = TargetNameRenderer->Get_Text_Extents( num ); text_size.U -= 1; text_size.V = -1; draw -= text_size; draw.Snap_To_Units( Vector2( 1, 1 ) ); TargetNameRenderer->Set_Location( draw.Upper_Left() ); TargetNameRenderer->Draw_Sentence( health_color ); #endif } // Draw Name uv.Set( TARGET_NAME_UV_UL, TARGET_NAME_UV_LR ); draw = uv; uv.Scale( INFO_UV_SCALE ); draw += box.Lower_Left() - draw.Upper_Left() + Vector2( 0, 1 ); draw += Vector2( (box.Width() - draw.Width())/2 + 10, 0 ); draw.Snap_To_Units( Vector2( 1, 1 ) ); TargetRenderer->Add_Quad( draw, uv, color ); if ( obj->Get_Translated_Name_ID() != 0 ) { TDBObjClass *translate_obj = TranslateDBClass::Find_Object( obj->Get_Translated_Name_ID() ); if ( translate_obj ) { WideStringClass translate_string=translate_obj->Get_String(); if ( building != NULL && HUDInfo::Get_Info_Object_Is_MCT() ) { translate_string=TRANSLATE( IDS_Enc_Struct_Nod_MCT_Name ); } Vector2 string_loc=draw.Upper_Left() + Vector2( 3.0f,1.0f ); if (translate_string!=TargetNameString) { TargetNameRenderer->Reset(); TargetNameString=translate_string; TargetNameLocation = string_loc; TargetNameRenderer->Build_Sentence( TargetNameString ); TargetNameRenderer->Set_Location( TargetNameLocation ); TargetNameRenderer->Set_Base_Location( TargetNameLocation ); TargetNameRenderer->Draw_Sentence( color ); } if (string_loc!=TargetNameLocation) { TargetNameLocation=string_loc; TargetNameRenderer->Set_Base_Location( TargetNameLocation ); } } else { TargetNameRenderer->Reset(); TargetNameString=""; TargetNameLocation = Vector2(0.0f,0.0f); } } else { TargetNameRenderer->Reset(); TargetNameString=""; TargetNameLocation = Vector2(0.0f,0.0f); } // Draw Team Icon int team = PLAYERTYPE_GDI; if ( p_obj != NULL ) { team = p_obj->Get_Player_Type(); } if ( building != NULL ) { if ( building->Is_GDI() ) { team = PLAYERTYPE_GDI; } else if ( building->Is_Nod() ) { team = PLAYERTYPE_NOD; } else { team = PLAYERTYPE_NEUTRAL; } } if ( team == PLAYERTYPE_NOD ) { uv.Set( NOD_ICON_UV_UL, NOD_ICON_UV_LR ); } else if ( team == PLAYERTYPE_GDI ) { uv.Set( GDI_ICON_UV_UL, GDI_ICON_UV_LR ); } else { uv.Set( NEUTRAL_ICON_UV_UL, NEUTRAL_ICON_UV_LR ); } draw2 = uv; uv.Scale( INFO_UV_SCALE ); draw2 += draw.Upper_Left() - draw2.Upper_Right(); TargetRenderer->Add_Quad( draw2, uv ); // Draw chevrons bool draw_chevrons = false; if ( p_obj != NULL && p_obj->Is_HUD_Pokable_Indicator_Enabled() ) { draw_chevrons = true; } if ( obj->As_SmartGameObj() != NULL && obj->As_SmartGameObj()->As_VehicleGameObj() != NULL && COMBAT_STAR->Is_Permitted_To_Enter_Vehicle() && obj->As_SmartGameObj()->As_VehicleGameObj()->Is_Entry_Permitted( COMBAT_STAR ) ) { draw_chevrons = true; } if ( draw_chevrons ) { RectClass enterable_box( Vector2(0,0), TARGET_ENTERABLE_SIZE ); enterable_box += Vector2( box.Center().X - enterable_box.Center().X , box.Top - enterable_box.Bottom ); static float enterable_bounce = 0; enterable_bounce += TimeManager::Get_Frame_Seconds() * 5; enterable_bounce = WWMath::Wrap( enterable_bounce, 0, DEG_TO_RADF( 360 ) ); enterable_box += Vector2( 0, TARGET_ENTERABLE_BOUNCE * (WWMath::Sin( enterable_bounce ) - 1) ); uv.Set( TARGET_ENTERABLE_UV_UL, TARGET_ENTERABLE_UV_LR ); uv.Scale( INFO_UV_SCALE ); color = Get_Health_Color( 1 ); // TargetRenderer->Add_Quad( enterable_box, uv ); enterable_box -= Vector2( 0, enterable_box.Height() * 0.6f ); TargetRenderer->Add_Tri( enterable_box.Upper_Right(), enterable_box.Upper_Left(), enterable_box.Center(), uv.Upper_Right(), uv.Upper_Left(), uv.Center(), color ); enterable_box += Vector2( 0, enterable_box.Height() * 0.6f ); TargetRenderer->Add_Tri( enterable_box.Upper_Right(), enterable_box.Upper_Left(), enterable_box.Center(), uv.Upper_Right(), uv.Upper_Left(), uv.Center(), color ); enterable_box += Vector2( 0, enterable_box.Height() * 0.6f ); TargetRenderer->Add_Tri( enterable_box.Upper_Right(), enterable_box.Upper_Left(), enterable_box.Center(), uv.Upper_Right(), uv.Upper_Left(), uv.Center(), color ); } } if ( InfoDebug ) { StringClass info(0,true); obj->Get_Information( info ); WideStringClass str(0,true); str.Convert_From( info ); InfoDebugRenderer->Build_Sentence( str ); InfoDebugRenderer->Set_Location( Vector2( 520, 240 ) ); // InfoDebugRenderer->Set_Base_Location( Vector2( 520, 240 ) ); InfoDebugRenderer->Draw_Sentence(); } } else { TargetNameRenderer->Reset(); TargetNameString=""; TargetNameLocation = Vector2(0.0f,0.0f); box_zoom_size = 0; HUDInfo::Clear_Info_Object(); } } static void Target_Render( void ) { TargetRenderer->Render(); TargetBoxRenderer->Render(); TargetNameRenderer->Render(); InfoDebugRenderer->Render(); } static RectClass Get_Target_Box( PhysicalGameObj * obj ) { // Lets draw a box around the target WWASSERT( obj ); PhysClass * po = obj->Peek_Physical_Object(); Vector2 top(0,0); Vector2 bottom(0,0); if ( po != NULL ) { // Get the Obj AABox in Camera Space AABoxClass obj_box; po->Get_Shadow_Blob_Box( &obj_box ); Matrix3D obj_tm = po->Get_Transform(); Matrix3D boxview_tm; Matrix3D boxview_inv_tm; boxview_tm.Look_At(COMBAT_CAMERA->Get_Transform().Get_Translation(),obj_tm * obj_box.Center,0.0f); boxview_tm.Get_Orthogonal_Inverse(boxview_inv_tm); Matrix3D obj_to_boxview_tm = boxview_inv_tm * obj_tm; AABoxClass boxview_box; obj_to_boxview_tm.Transform_Center_Extent_AABox( obj_box.Center, obj_box.Extent, &boxview_box.Center, &boxview_box.Extent ); Matrix3D camera_tm = COMBAT_CAMERA->Get_Transform(); Matrix3D camera_inv_tm; camera_tm.Get_Orthogonal_Inverse(camera_inv_tm); Matrix3D boxview_to_camera_tm = camera_inv_tm * boxview_tm; AABoxClass camera_box; boxview_to_camera_tm.Transform_Center_Extent_AABox( boxview_box.Center, boxview_box.Extent, &camera_box.Center, &camera_box.Extent); camera_box.Extent.Z = 0.0f; Vector3 ctop = camera_box.Center - camera_box.Extent; Vector3 cbottom = camera_box.Center + camera_box.Extent; Vector3 temp; COMBAT_CAMERA->Project_Camera_Space_Point( temp, ctop ); top.X = temp.X; top.Y = temp.Y; COMBAT_CAMERA->Project_Camera_Space_Point( temp, cbottom ); bottom.X = temp.X; bottom.Y = temp.Y; } // Get Box in proper convention RectClass screen = Render2DClass::Get_Screen_Resolution(); top.X = top.X * 0.5f + 0.5f; top.Y = top.Y * -0.5f + 0.5f; bottom.X = bottom.X * 0.5f + 0.5f; bottom.Y = bottom.Y * -0.5f + 0.5f; float temp = top.Y; top.Y = bottom.Y; bottom.Y = temp; static RectClass info_box; info_box.Set( top.X * screen.Right, top.Y * screen.Bottom, bottom.X * screen.Right, bottom.Y * screen.Bottom ); // convention 0,0 - 1,1 return info_box; } static void Target_Box_Edge( const Vector2 & a, const Vector2 & b, unsigned int color ) { float percent = 0.2f; Vector2 a_ = b - a; a_ *= percent; a_ += a; TargetBoxRenderer->Add_Line( a, a_, 2, color ); Vector2 b_ = a - b; b_ *= percent; b_ += b; TargetBoxRenderer->Add_Line( b, b_, 2, color ); } /* ** Score Display */ /* Render2DTextClass * ScoreRenderer; static void Score_Init( void ) { Font3DInstanceClass * font = WW3DAssetManager::Get_Instance()->Get_Font3DInstance( LARGE_FONT ); SET_REF_OWNER( font ); ScoreRenderer = new Render2DTextClass( font ); ScoreRenderer->Set_Coordinate_Range( Render2DClass::Get_Screen_Resolution() ); font->Release_Ref(); } static void Score_Shutdown( void ) { delete ScoreRenderer; ScoreRenderer = NULL; } static void Score_Update( void ) { ScoreRenderer->Reset(); //TSS2001e if ( COMBAT_STAR ) { if ( COMBAT_STAR && COMBAT_STAR->Get_Player_Data() ) { int score = COMBAT_STAR->Get_Player_Data()->Get_Score(); // WideStringClass scorestring; // scorestring.Format( L"%d", score ); WCHAR score_string[12]; // 12 digits ought to be enough... Generate_WChar_Text_From_Number(score_string,sizeof(score_string),false,score); Vector2 position = Render2DClass::Get_Screen_Resolution().Center(); position.Y = Render2DClass::Get_Screen_Resolution().Bottom; Vector2 size = ScoreRenderer->Get_Text_Extents( score_string ); size.X *= 0.5f; position -= size; ScoreRenderer->Set_Location( position ); ScoreRenderer->Draw_Text( score_string ); } } static void Score_Render( void ) { ScoreRenderer->Render(); } */ /* ** Objective Display */ DynamicVectorClass ObjectivePogRenderers; Render2DClass * ObjectiveArrowRenderer; Render2DSentenceClass * ObjectiveTextRenderer; int CurrentObjectiveIndex = 0; void * CurrentObjective = NULL; static int CachedObjectiveIndex=-1; int CachedRange=0; #define OBJECTIVE_ARROW_TEXTURE "HUD_obje_arrow.TGA" static void Objective_Init( void ) { ObjectiveArrowRenderer = new Render2DClass(); ObjectiveArrowRenderer->Set_Texture( OBJECTIVE_ARROW_TEXTURE ); ObjectiveArrowRenderer->Set_Coordinate_Range( Render2DClass::Get_Screen_Resolution() ); FontCharsClass *font = StyleMgrClass::Peek_Font( StyleMgrClass::FONT_INGAME_TXT ); ObjectiveTextRenderer = new Render2DSentenceClass(); ObjectiveTextRenderer->Set_Font( font ); CurrentObjectiveIndex=0; CurrentObjective=NULL; CachedObjectiveIndex=-1; CachedRange=0; } static void Objective_Release_Pogs( void ) { for ( int i = 0; i < ObjectivePogRenderers.Count(); i++ ) { delete ObjectivePogRenderers[i]; ObjectivePogRenderers[i] = NULL; } ObjectivePogRenderers.Delete_All(); } static void Objective_Shutdown( void ) { Objective_Release_Pogs(); delete ObjectiveArrowRenderer; ObjectiveArrowRenderer = NULL; delete ObjectiveTextRenderer; ObjectiveTextRenderer = NULL; } #define POG_FLY_TIME 2.0f static void Objective_Update( void ) { RectClass pog_box( 0, 0, 64, 64 ); pog_box += Render2DClass::Get_Screen_Resolution().Upper_Right() - pog_box.Upper_Right(); pog_box += Vector2( -16, 8 ); #define POG_SPACING Vector2( 10, 0 ) bool rebuild = false; int objective_count = ObjectiveManager::Get_Num_HUD_Objectives(); if ( objective_count > 0 ) { // maintain the index if ( CurrentObjective != ObjectiveManager::Get_Objective( CurrentObjectiveIndex ) ) { CurrentObjectiveIndex = 0; rebuild = true; #if 0 // no, just go for the first // Try to find the last objective for ( int i = 0; i < objective_count; i++ ) { if ( CurrentObjective == ObjectiveManager::Get_Objective( i ) ) { CurrentObjectiveIndex = i; } } #endif } if ( IS_MISSION && Input::Get_State( INPUT_FUNCTION_CYCLE_POG ) ) { rebuild = true; CurrentObjectiveIndex++; if ( CurrentObjectiveIndex >= objective_count ) { CurrentObjectiveIndex = 0; } } CurrentObjective = ObjectiveManager::Get_Objective( CurrentObjectiveIndex ); } else { if (CurrentObjectiveIndex!=0 || CurrentObjective!=NULL) { rebuild=true; } CurrentObjectiveIndex = 0; CurrentObjective = NULL; } // re-Create the Pogs, if needed if ( rebuild || ObjectiveManager::Are_HUD_Objectives_Changed() ) { // Debug_Say(( "Rebuild Hud Pogs\n" )); Objective_Release_Pogs(); // Reset text ObjectiveTextRenderer->Reset(); CachedRange=0; CachedObjectiveIndex=-1; int count = objective_count; pog_box += POG_SPACING * (float)count; bool dont_clear = false; for ( int i = count - 1; i >= 0; i-- ) { int index = (i + CurrentObjectiveIndex) % objective_count; pog_box -= POG_SPACING; // Add Pog Render2DClass * renderer = new Render2DClass(); if ( renderer ) { renderer->Set_Texture( ObjectiveManager::Get_HUD_Objectives_Pog_Texture_Name( index ) ); renderer->Set_Coordinate_Range( Render2DClass::Get_Screen_Resolution() ); float age = ObjectiveManager::Get_HUD_Objectives_Age( index ); if ( age < POG_FLY_TIME ) { Vector2 offset = Render2DClass::Get_Screen_Resolution().Center() - Render2DClass::Get_Screen_Resolution().Upper_Right(); offset.X *= 0.75f; float fly = WWMath::Clamp( (2.0f-(2.0f*age/POG_FLY_TIME)), 0, 1 ); offset *= fly; pog_box += offset; renderer->Add_Quad( pog_box ); pog_box -= offset; dont_clear = true; // AND, make an extra renderer for the radar star Render2DClass * renderer = new Render2DClass(); if ( renderer ) { renderer->Set_Texture( "HUD_STAR.TGA" ); renderer->Set_Coordinate_Range( Render2DClass::Get_Screen_Resolution() ); RectClass star_box( -32, -32, 32, 32 ); star_box.Scale( fly ); Vector2 star_fly_start = Render2DClass::Get_Screen_Resolution().Center(); Vector2 star_fly_end = Render2DClass::Get_Screen_Resolution().Lower_Left(); star_fly_start.X *= 0.85f; star_fly_start.Y *= 1.175f; star_fly_end.X += 40.0f; star_fly_end.Y *= 0.8f; star_box += star_fly_end; Vector2 offset = star_fly_start - star_fly_end; offset *= fly; star_box += offset; Vector3 color3( 0,1,0 ); if ( ObjectiveManager::Get_Objective(index) != NULL ) { color3 = ObjectiveManager::Get_Objective(index)->Type_To_Color(); } unsigned int color = color3.Convert_To_ARGB(); renderer->Add_Quad( star_box, color ); ObjectivePogRenderers.Add( renderer ); } } else { renderer->Add_Quad( pog_box ); } ObjectivePogRenderers.Add( renderer ); } } if ( !dont_clear ) { ObjectiveManager::Clear_HUD_Objectives_Changed(); } } ObjectiveArrowRenderer->Reset(); float range = 0; int count = objective_count; if ( count > 0 ) { // Create Arrow float angle = 0; Vector3 objective_pos = ObjectiveManager::Get_HUD_Objectives_Location( CurrentObjectiveIndex ); if ( COMBAT_STAR ) { Vector3 rel_pos; Matrix3D::Inverse_Transform_Vector( COMBAT_STAR->Get_Transform(), objective_pos, &rel_pos ); angle = ::atan2( rel_pos.Y, rel_pos.X ); range = rel_pos.Length(); } Vector2 arrow_vertex; arrow_vertex.X = WWMath::Fast_Sin( angle + DEG_TO_RAD( 180 + 45 ) ); arrow_vertex.Y = WWMath::Fast_Cos( angle + DEG_TO_RAD( 180 + 45 ) ); Vector2 verts[4]; verts[0] = Vector2( arrow_vertex.X, arrow_vertex.Y ); verts[1] = Vector2( arrow_vertex.Y, -arrow_vertex.X ); verts[2] = Vector2( -arrow_vertex.Y, arrow_vertex.X ); verts[3] = Vector2( -arrow_vertex.X, -arrow_vertex.Y ); Vector2 offset; offset.Y = WWMath::Fast_Sin( -angle + DEG_TO_RAD( -90 ) ); offset.X = WWMath::Fast_Cos( -angle + DEG_TO_RAD( -90 ) ); offset *= 35; offset += pog_box.Center(); const float SIN_45=0.70710678118654752440084436210485f; for ( int i = 0; i < 4; i++ ) { verts[i] *= 0.5f * 16 / SIN_45;//::sin( DEG_TO_RAD( 45 ) ); verts[i] += offset; } ObjectiveArrowRenderer->Add_Quad( verts[0], verts[1], verts[2], verts[3] ); } int irange=(int)(range); irange=(irange/10)*10; if (CachedObjectiveIndex!=CurrentObjectiveIndex || irange!=CachedRange) { ObjectiveTextRenderer->Reset(); if (objective_count>0) { CachedRange=irange; CachedObjectiveIndex=CurrentObjectiveIndex; // Draw message Vector2 position = pog_box.Lower_Left(); position += Vector2( 0, -15 ); WideStringClass str(ObjectiveManager::Get_HUD_Objectives_Message( CurrentObjectiveIndex ),true); ObjectiveTextRenderer->Build_Sentence( str ); Vector2 text_size = ObjectiveTextRenderer->Get_Text_Extents( str ); position.X = (int)(pog_box.Center().X - (text_size.X/2)); ObjectiveTextRenderer->Set_Location( position ); ObjectiveTextRenderer->Draw_Sentence(); // Draw range position = pog_box.Lower_Left(); str.Format( TRANSLATE(IDS_HUD_RANGE), irange ); ObjectiveTextRenderer->Build_Sentence( str ); text_size = ObjectiveTextRenderer->Get_Text_Extents( str ); position.X = (int)(pog_box.Center().X - (text_size.X/2)); ObjectiveTextRenderer->Set_Location( position ); ObjectiveTextRenderer->Draw_Sentence(); } else { CachedRange=0; CachedObjectiveIndex=-1; } } } static void Objective_Render( void ) { for ( int i = 0; i < ObjectivePogRenderers.Count(); i++ ) { ObjectivePogRenderers[i]->Render(); } ObjectiveArrowRenderer->Render(); ObjectiveTextRenderer->Render(); } /* ** Info Display */ struct InfoEditorField { const char * Name; Vector2 * Value; bool operator == (InfoEditorField const & rec) const { return false; } bool operator != (InfoEditorField const & rec) const { return true; } }; static DynamicVectorClass InfoEditorFieldList; #define INFO_EDITOR_ADD(x) field.Name = #x; field.Value = &x; InfoEditorFieldList.Add( field ); static void Info_Editor_Init( void ) { #if 0 InfoEditorField field; INFO_EDITOR_ADD( INFO_OFFSET ); INFO_EDITOR_ADD( FRAME_1_UV_UL ); INFO_EDITOR_ADD( FRAME_1_UV_LR ); INFO_EDITOR_ADD( FRAME_1_OFFSET ); INFO_EDITOR_ADD( FRAME_2_UV_UL ); INFO_EDITOR_ADD( FRAME_2_UV_LR ); INFO_EDITOR_ADD( FRAME_2_OFFSET ); INFO_EDITOR_ADD( FRAME_3_UV_UL ); INFO_EDITOR_ADD( FRAME_3_UV_LR ); INFO_EDITOR_ADD( FRAME_3_OFFSET ); INFO_EDITOR_ADD( FRAME_4_UV_UL ); INFO_EDITOR_ADD( FRAME_4_UV_LR ); INFO_EDITOR_ADD( FRAME_4_OFFSET ); INFO_EDITOR_ADD( FRAME_5_UV_UL ); INFO_EDITOR_ADD( FRAME_5_UV_LR ); INFO_EDITOR_ADD( FRAME_5_OFFSET ); INFO_EDITOR_ADD( FRAME_6_UV_UL ); INFO_EDITOR_ADD( FRAME_6_UV_LR ); INFO_EDITOR_ADD( FRAME_6_OFFSET ); INFO_EDITOR_ADD( HEALTH_BACK_UV_UL ); INFO_EDITOR_ADD( HEALTH_BACK_UV_LR ); INFO_EDITOR_ADD( HEALTH_BACK_UL ); INFO_EDITOR_ADD( HEALTH_BACK_LR ); INFO_EDITOR_ADD( GRADIENT_BLACK_UV_UL ); INFO_EDITOR_ADD( GRADIENT_BLACK_UV_LR ); INFO_EDITOR_ADD( HEALTH_TEXT_BACK_UL ); INFO_EDITOR_ADD( HEALTH_TEXT_BACK_LR ); INFO_EDITOR_ADD( HEALTH_UV_UL ); INFO_EDITOR_ADD( HEALTH_UV_LR ); INFO_EDITOR_ADD( HEALTH_OFFSET ); INFO_EDITOR_ADD( SHIELD_UV_UL ); INFO_EDITOR_ADD( SHIELD_UV_LR ); INFO_EDITOR_ADD( SHIELD_OFFSET ); INFO_EDITOR_ADD( KEY_1_UV_UL ); INFO_EDITOR_ADD( KEY_1_UV_LR ); INFO_EDITOR_ADD( KEY_1_OFFSET ); INFO_EDITOR_ADD( KEY_2_UV_UL ); INFO_EDITOR_ADD( KEY_2_UV_LR ); INFO_EDITOR_ADD( KEY_2_OFFSET ); INFO_EDITOR_ADD( KEY_3_UV_UL ); INFO_EDITOR_ADD( KEY_3_UV_LR ); INFO_EDITOR_ADD( KEY_3_OFFSET ); INFO_EDITOR_ADD( HEALTH_CROSS_1_UV_UL ); INFO_EDITOR_ADD( HEALTH_CROSS_1_UV_LR ); INFO_EDITOR_ADD( HEALTH_CROSS_1_OFFSET ); INFO_EDITOR_ADD( HEALTH_CROSS_2_UV_UL ); INFO_EDITOR_ADD( HEALTH_CROSS_2_UV_LR ); INFO_EDITOR_ADD( HEALTH_CROSS_2_OFFSET ); INFO_EDITOR_ADD( TIME_BACK_UL ); INFO_EDITOR_ADD( TIME_BACK_LR ); INFO_EDITOR_ADD( TIME_CLOCK_UV_UL ); INFO_EDITOR_ADD( TIME_CLOCK_UV_LR ); INFO_EDITOR_ADD( TIME_CLOCK_OFFSET ); INFO_EDITOR_ADD( WEAPON_BOX_UV_UL ); INFO_EDITOR_ADD( WEAPON_BOX_UV_LR ); INFO_EDITOR_ADD( WEAPON_BOX_OFFSET ); INFO_EDITOR_ADD( POWER_OUT_ICON_UV_UL ); INFO_EDITOR_ADD( POWER_OUT_ICON_UV_LR ); INFO_EDITOR_ADD( POWER_OUT_ICON_OFFSET ); INFO_EDITOR_ADD( REPAIR_ICON_UV_UL ); INFO_EDITOR_ADD( REPAIR_ICON_UV_LR ); INFO_EDITOR_ADD( REPAIR_ICON_OFFSET ); INFO_EDITOR_ADD( GDI_ICON_UV_UL ); INFO_EDITOR_ADD( GDI_ICON_UV_LR ); INFO_EDITOR_ADD( GDI_ICON_OFFSET ); INFO_EDITOR_ADD( NOD_ICON_UV_UL ); INFO_EDITOR_ADD( NOD_ICON_UV_LR ); INFO_EDITOR_ADD( NOD_ICON_OFFSET ); INFO_EDITOR_ADD( NEUTRAL_ICON_UV_UL ); INFO_EDITOR_ADD( NEUTRAL_ICON_UV_LR ); INFO_EDITOR_ADD( NEUTRAL_ICON_OFFSET ); INFO_EDITOR_ADD( BULLET_ICON_UV_UL ); INFO_EDITOR_ADD( BULLET_ICON_UV_LR ); INFO_EDITOR_ADD( BULLET_ICON_OFFSET ); INFO_EDITOR_ADD( RADAR_CENTER_OFFSET ); INFO_EDITOR_ADD( DAMAGE_1_UV_UL ); INFO_EDITOR_ADD( DAMAGE_1_UV_LR ); INFO_EDITOR_ADD( DAMAGE_2_UV_UL ); INFO_EDITOR_ADD( DAMAGE_2_UV_LR ); INFO_EDITOR_ADD( HORIZ_DAMAGE_SIZE ); INFO_EDITOR_ADD( VERT_DAMAGE_SIZE ); INFO_EDITOR_ADD( DIAG_DAMAGE_SIZE ); INFO_EDITOR_ADD( HV_DAMAGE_OFFSET ); INFO_EDITOR_ADD( DIAG_DAMAGE_OFFSET ); INFO_EDITOR_ADD( POWERUP_BOX_UV_UL ); INFO_EDITOR_ADD( POWERUP_BOX_UV_LR ); INFO_EDITOR_ADD( RADAR_RINGS_UV_UL ); INFO_EDITOR_ADD( RADAR_RINGS_UV_LR ); INFO_EDITOR_ADD( RADAR_RINGS_L_OFFSET ); INFO_EDITOR_ADD( RADAR_RINGS_R_OFFSET ); INFO_EDITOR_ADD( RADAR_STAR_UV_UL ); INFO_EDITOR_ADD( RADAR_STAR_UV_LR ); INFO_EDITOR_ADD( RADAR_STAR_OFFSET ); INFO_EDITOR_ADD( RADAR_SQUARE_UV_UL ); INFO_EDITOR_ADD( RADAR_SQUARE_UV_LR ); INFO_EDITOR_ADD( RADAR_SQUARE_OFFSET); INFO_EDITOR_ADD( RADAR_TRIANGLE_UV_UL); INFO_EDITOR_ADD( RADAR_TRIANGLE_UV_LR); INFO_EDITOR_ADD( RADAR_TRIANGLE_OFFSET ); INFO_EDITOR_ADD( RADAR_CIRCLE_UV_UL ); INFO_EDITOR_ADD( RADAR_CIRCLE_UV_LR ); INFO_EDITOR_ADD( RADAR_CIRCLE_OFFSET ); INFO_EDITOR_ADD( RADAR_BRACKET_UV_UL ); INFO_EDITOR_ADD( RADAR_BRACKET_UV_LR ); INFO_EDITOR_ADD( RADAR_BRACKET_OFFSET ); INFO_EDITOR_ADD( RADAR_SWEEP_UV_UL ); INFO_EDITOR_ADD( RADAR_SWEEP_UV_LR ); INFO_EDITOR_ADD( RADAR_SWEEP_OFFSET ); INFO_EDITOR_ADD( TARGET_HEALTH_L_UV_UL ); INFO_EDITOR_ADD( TARGET_HEALTH_L_UV_LR ); INFO_EDITOR_ADD( TARGET_HEALTH_R_UV_UL ); INFO_EDITOR_ADD( TARGET_HEALTH_R_UV_LR ); INFO_EDITOR_ADD( TARGET_HEALTH_OFFSET ); INFO_EDITOR_ADD( TARGET_NAME_UV_UL ); INFO_EDITOR_ADD( TARGET_NAME_UV_LR ); INFO_EDITOR_ADD( TARGET_NAME_OFFSET ); #endif } static void Info_Editor_Update( void ) { return; bool changed = false; static int index = 0; static float _move = 0; float move = Input::Get_Amount( INPUT_FUNCTION_MOVE_LEFT ) - Input::Get_Amount( INPUT_FUNCTION_MOVE_RIGHT ); if ( _move != move ) { _move = move; index += (int)-move; index = (int)WWMath::Wrap( index, (float)0, (float)(InfoEditorFieldList.Count()) ); if ( move != 0 ) { changed = true; } } float _forward = 0; float forward = Input::Get_Amount( INPUT_FUNCTION_MOVE_FORWARD ) - Input::Get_Amount( INPUT_FUNCTION_MOVE_BACKWARD ); forward *= 10; forward = WWMath::Clamp( forward, -1, 1 ); if ( _forward != forward ) { _forward = forward; InfoEditorFieldList[index].Value->V += forward; if ( forward != 0 ) { changed = true; } } float _left = 0; float left = Input::Get_Amount( INPUT_FUNCTION_TURN_LEFT ) - Input::Get_Amount( INPUT_FUNCTION_TURN_RIGHT ); left *= 10; left = WWMath::Clamp( left, -1, 1 ); if ( _left != left ) { _left = left; InfoEditorFieldList[index].Value->U += left; if ( left != 0 ) { changed = true; } } if ( changed ) { Debug_Say(( "Vector2 %s( %d, %d );\n", InfoEditorFieldList[index].Name, (int)InfoEditorFieldList[index].Value->U, (int)InfoEditorFieldList[index].Value->V )); } } static void Info_Editor_Shutdown( void ) { while ( InfoEditorFieldList.Count() > 0 ) { Debug_Say(( "Vector2 %s( %d, %d );\n", InfoEditorFieldList[0].Name, (int)InfoEditorFieldList[0].Value->U, (int)InfoEditorFieldList[0].Value->V )); InfoEditorFieldList.Delete(0); } } /* ** */ Render2DTextClass * InfoHealthCountRenderer; Render2DTextClass * InfoShieldCountRenderer; Vector2 InfoBase(0,0); float LastHealth = 0; float CenterHealthTimer = 0; const float CENTER_HEALTH_TIME = 2.0f; static void Info_Init( void ) { Info_Editor_Init(); InfoRenderer = new Render2DClass(); InfoRenderer->Set_Texture( HUD_MAIN_TEXTURE ); InfoRenderer->Set_Coordinate_Range( Render2DClass::Get_Screen_Resolution() ); Font3DInstanceClass * font = WW3DAssetManager::Get_Instance()->Get_Font3DInstance( LARGE_FONT ); SET_REF_OWNER( font ); InfoHealthCountRenderer = new Render2DTextClass( font ); InfoHealthCountRenderer->Set_Coordinate_Range( Render2DClass::Get_Screen_Resolution() ); font->Release_Ref(); font = WW3DAssetManager::Get_Instance()->Get_Font3DInstance( SMALL_FONT ); SET_REF_OWNER( font ); InfoShieldCountRenderer = new Render2DTextClass( font ); InfoShieldCountRenderer->Set_Coordinate_Range( Render2DClass::Get_Screen_Resolution() ); font->Release_Ref(); InfoBase = Render2DClass::Get_Screen_Resolution().Lower_Left() + Vector2( INFO_OFFSET ); } static void Info_Shutdown( void ) { Info_Editor_Shutdown() ; delete InfoRenderer; InfoRenderer = NULL; delete InfoHealthCountRenderer; InfoHealthCountRenderer = NULL; delete InfoShieldCountRenderer; InfoShieldCountRenderer = NULL; } static void Info_Update_Health_Shield( void ) { // Draw Health float health = 0; float health_percent = 0; float shield = 0; float shield_percent = 0; if ( COMBAT_STAR ) { const DefenseObjectClass * def = COMBAT_STAR->Get_Defense_Object(); if ( COMBAT_STAR->Get_Vehicle() ) { def = COMBAT_STAR->Get_Vehicle()->Get_Defense_Object(); } if ( def && def->Get_Health_Max() ) { health = def->Get_Health(); health_percent = WWMath::Clamp( def->Get_Health() / def->Get_Health_Max(), 0, 1 ); } if ( def && def->Get_Shield_Strength_Max() ) { shield = def->Get_Shield_Strength(); shield_percent = WWMath::Clamp( def->Get_Shield_Strength() / def->Get_Shield_Strength_Max(), 0, 1 ); } } RectClass uv; RectClass draw; // Draw Health Bar uv.Set( HEALTH_UV_UL, HEALTH_UV_LR ); draw = uv; uv.Scale( INFO_UV_SCALE ); draw += InfoBase + HEALTH_OFFSET - draw.Upper_Left(); // Scale bars static float _last_health_percent = 0; float diff = health_percent - _last_health_percent; float max_change = TimeManager::Get_Frame_Seconds(); _last_health_percent += WWMath::Clamp( diff, -max_change, max_change ); uv.Right = uv.Left + uv.Width() * _last_health_percent; draw.Right = draw.Left + draw.Width() * _last_health_percent; // Get bar color float color_percent = MAX( _last_health_percent, health_percent ); InfoRenderer->Add_Quad( draw, uv, Get_Health_Color( color_percent ) ); uv.Set( GRADIENT_BLACK_UV_UL, GRADIENT_BLACK_UV_LR ); uv.Scale( INFO_UV_SCALE ); draw.Set( HEALTH_TEXT_BACK_UL, HEALTH_TEXT_BACK_LR ); draw += InfoBase; InfoRenderer->Add_Quad( draw, uv ); // Draw Cross static float flash = 0; flash += TimeManager::Get_Frame_Seconds() * 4; if ( flash > 2 ) { flash -= 2; } if ( health_percent > 0.25f ) { flash = 0; } float intensity = flash; if ( flash > 1 ) { intensity = 2 - flash; } int health_color = Get_Health_Color( color_percent ); uv.Set( HEALTH_CROSS_1_UV_UL, HEALTH_CROSS_1_UV_LR ); draw = uv; uv.Scale( INFO_UV_SCALE ); draw += InfoBase + HEALTH_CROSS_1_OFFSET - draw.Upper_Left(); InfoRenderer->Add_Quad( draw, uv, COLOR( intensity, health_color ) ); RectClass uv2; uv2.Set( HEALTH_CROSS_2_UV_UL, HEALTH_CROSS_2_UV_LR ); uv2.Scale( INFO_UV_SCALE ); InfoRenderer->Add_Quad( draw, uv2, COLOR( 1-intensity, health_color ) ); // Draw Health Number InfoHealthCountRenderer->Reset(); // StringClass text; if ( health < 1 && health > 0 ) { health = 1; } //text.Format( "%03d", (int)health ); long lhealth=WWMath::Float_To_Long(health); WCHAR tmp_text[5]; Generate_WChar_Text_From_Number(tmp_text,4,3,lhealth); InfoHealthCountRenderer->Set_Location( draw.Upper_Right() + Vector2( 4,4) ); InfoHealthCountRenderer->Draw_Text( tmp_text, health_color ); if ( health != LastHealth || health_percent <= 0.25f ) { LastHealth = health; CenterHealthTimer = CENTER_HEALTH_TIME; } if ( CenterHealthTimer > 0 ) { // Also draw the above at the center Vector2 health_center_offset = Render2DClass::Get_Screen_Resolution().Center(); health_center_offset.X *= 0.5; health_center_offset.Y -= draw.Height() / 2; health_center_offset -= HEALTH_CROSS_1_OFFSET; float fade = WWMath::Clamp( CenterHealthTimer, 0, 1 ); uv.Set( GRADIENT_BLACK_UV_UL, GRADIENT_BLACK_UV_LR ); uv.Scale( INFO_UV_SCALE ); draw.Set( HEALTH_TEXT_BACK_UL, HEALTH_TEXT_BACK_LR ); draw += health_center_offset; InfoRenderer->Add_Quad( draw, uv, COLOR( fade ) ); uv.Set( HEALTH_CROSS_1_UV_UL, HEALTH_CROSS_1_UV_LR ); draw = uv; uv.Scale( INFO_UV_SCALE ); draw += health_center_offset + HEALTH_CROSS_1_OFFSET - draw.Upper_Left(); InfoRenderer->Add_Quad( draw, uv, COLOR( fade * intensity, health_color ) ); InfoRenderer->Add_Quad( draw, uv2, COLOR( fade * (1-intensity), health_color ) ); InfoHealthCountRenderer->Set_Location( draw.Upper_Right() + Vector2( 4,4) ); InfoHealthCountRenderer->Draw_Text( tmp_text, COLOR( fade, health_color ) ); CenterHealthTimer -= TimeManager::Get_Frame_Seconds(); } // Draw Shield static float _last_shield_percent = 0; diff = shield_percent - _last_shield_percent; max_change = TimeManager::Get_Frame_Seconds(); _last_shield_percent += WWMath::Clamp( diff, -max_change, max_change ); shield_percent = _last_shield_percent; uv.Right = uv.Left + uv.Width() * shield_percent; draw.Right = draw.Left + draw.Width() * shield_percent; if ( shield_percent > 0 ) { #define TOTAL_SHIELD_MOVEMENT 80 for ( float percent = 0; percent < shield_percent; percent += 0.1f ) { uv.Set( SHIELD_UV_UL, SHIELD_UV_LR ); draw = uv; uv.Scale( INFO_UV_SCALE ); draw += InfoBase + SHIELD_OFFSET - draw.Upper_Left(); draw += Vector2( (int)(-percent * TOTAL_SHIELD_MOVEMENT), 0 ); InfoRenderer->Add_Quad( draw, uv ); } uv.Set( SHIELD_UV_UL, SHIELD_UV_LR ); draw = uv; uv.Scale( INFO_UV_SCALE ); draw += InfoBase + SHIELD_OFFSET - draw.Upper_Left(); draw += Vector2( (int)(-shield_percent * TOTAL_SHIELD_MOVEMENT), 0 ); InfoRenderer->Add_Quad( draw, uv ); // Draw Shield Number InfoShieldCountRenderer->Reset(); // StringClass text; // text.Format( "%03d", (int)shield ); long lshield=WWMath::Float_To_Long(shield); WCHAR tmp_text[5]; Generate_WChar_Text_From_Number(tmp_text,4,3,lshield); InfoShieldCountRenderer->Set_Location( draw.Upper_Left() + Vector2( 4,4) ); InfoShieldCountRenderer->Draw_Text( tmp_text ); } else { InfoShieldCountRenderer->Reset(); } } static void Info_Update( void ) { // Info_Editor_Update(); // Clear the renderer InfoRenderer->Reset(); // Draw the Frame RectClass uv; uv.Set( FRAME_1_UV_UL, FRAME_1_UV_LR ); RectClass draw = uv; uv.Scale( INFO_UV_SCALE ); draw += InfoBase + FRAME_1_OFFSET - draw.Upper_Left(); InfoRenderer->Add_Quad( draw, uv ); uv.Set( FRAME_2_UV_UL, FRAME_2_UV_LR ); draw = uv; uv.Scale( INFO_UV_SCALE ); draw += InfoBase + FRAME_2_OFFSET - draw.Upper_Left(); InfoRenderer->Add_Quad( draw, uv ); uv.Set( FRAME_3_UV_UL, FRAME_3_UV_LR ); draw = uv; uv.Scale( INFO_UV_SCALE ); draw += InfoBase + FRAME_3_OFFSET - draw.Upper_Left(); InfoRenderer->Add_Quad( draw, uv ); uv.Set( FRAME_4_UV_UL, FRAME_4_UV_LR ); draw = uv; uv.Scale( INFO_UV_SCALE ); draw += InfoBase + FRAME_4_OFFSET - draw.Upper_Left(); InfoRenderer->Add_Quad( draw, uv ); uv.Set( FRAME_5_UV_UL, FRAME_5_UV_LR ); draw = uv; uv.Scale( INFO_UV_SCALE ); draw += InfoBase + FRAME_5_OFFSET - draw.Upper_Left(); InfoRenderer->Add_Quad( draw, uv ); uv.Set( FRAME_6_UV_UL, FRAME_6_UV_LR ); draw = uv; uv.Scale( INFO_UV_SCALE ); draw += InfoBase + FRAME_6_OFFSET - draw.Upper_Left(); InfoRenderer->Add_Quad( draw, uv ); uv.Set( HEALTH_BACK_UV_UL, HEALTH_BACK_UV_LR ); uv.Scale( INFO_UV_SCALE ); draw.Set( HEALTH_BACK_UL, HEALTH_BACK_LR ); draw += InfoBase; InfoRenderer->Add_Quad( draw, uv ); // Draw Health and Shield Info_Update_Health_Shield(); if ( COMBAT_STAR ) { if ( COMBAT_STAR->Has_Key( 1 ) ) { uv.Set( KEY_1_UV_UL, KEY_1_UV_LR ); draw = uv; uv.Scale( INFO_UV_SCALE ); draw += InfoBase + KEY_1_OFFSET - draw.Upper_Left(); InfoRenderer->Add_Quad( draw, uv ); } if ( COMBAT_STAR->Has_Key( 2 ) ) { uv.Set( KEY_2_UV_UL, KEY_2_UV_LR ); draw = uv; uv.Scale( INFO_UV_SCALE ); draw += InfoBase + KEY_2_OFFSET - draw.Upper_Left(); InfoRenderer->Add_Quad( draw, uv ); } if ( COMBAT_STAR->Has_Key( 3 ) ) { uv.Set( KEY_3_UV_UL, KEY_3_UV_LR ); draw = uv; uv.Scale( INFO_UV_SCALE ); draw += InfoBase + KEY_3_OFFSET - draw.Upper_Left(); InfoRenderer->Add_Quad( draw, uv ); } } #if 0 return; uv.Set( TARGET_HEALTH_L_UV_UL, TARGET_HEALTH_L_UV_LR ); draw = uv; uv.Scale( INFO_UV_SCALE ); draw += InfoBase + TARGET_HEALTH_OFFSET - draw.Upper_Left(); InfoRenderer->Add_Quad( draw, uv ); uv.Set( TARGET_HEALTH_R_UV_UL, TARGET_HEALTH_R_UV_LR ); draw = uv; uv.Scale( INFO_UV_SCALE ); draw += InfoBase + TARGET_HEALTH_OFFSET - draw.Upper_Left() + Vector2( 0, 20 ); InfoRenderer->Add_Quad( draw, uv ); uv.Set( TARGET_NAME_UV_UL, TARGET_NAME_UV_LR ); draw = uv; uv.Scale( INFO_UV_SCALE ); draw += InfoBase + TARGET_NAME_OFFSET - draw.Upper_Left(); InfoRenderer->Add_Quad( draw, uv ); uv.Set( GRADIENT_BLACK_UV_UL, GRADIENT_BLACK_UV_LR ); uv.Scale( INFO_UV_SCALE ); draw.Set( TIME_BACK_UL, TIME_BACK_LR ); draw += InfoBase; InfoRenderer->Add_Quad( draw, uv ); uv.Set( TIME_CLOCK_UV_UL, TIME_CLOCK_UV_LR ); draw = uv; uv.Scale( INFO_UV_SCALE ); draw += InfoBase + TIME_CLOCK_OFFSET - draw.Upper_Left(); InfoRenderer->Add_Quad( draw, uv ); uv.Set( WEAPON_BOX_UV_UL, WEAPON_BOX_UV_LR ); draw = uv; uv.Scale( INFO_UV_SCALE ); draw += InfoBase + WEAPON_BOX_OFFSET - draw.Upper_Left(); InfoRenderer->Add_Quad( draw, uv ); uv.Set( POWER_OUT_ICON_UV_UL, POWER_OUT_ICON_UV_LR ); draw = uv; uv.Scale( INFO_UV_SCALE ); draw += InfoBase + POWER_OUT_ICON_OFFSET - draw.Upper_Left(); InfoRenderer->Add_Quad( draw, uv ); uv.Set( REPAIR_ICON_UV_UL, REPAIR_ICON_UV_LR ); draw = uv; uv.Scale( INFO_UV_SCALE ); draw += InfoBase + REPAIR_ICON_OFFSET - draw.Upper_Left(); InfoRenderer->Add_Quad( draw, uv ); uv.Set( GDI_ICON_UV_UL, GDI_ICON_UV_LR ); draw = uv; uv.Scale( INFO_UV_SCALE ); draw += InfoBase + GDI_ICON_OFFSET - draw.Upper_Left(); InfoRenderer->Add_Quad( draw, uv ); uv.Set( NOD_ICON_UV_UL, NOD_ICON_UV_LR ); draw = uv; uv.Scale( INFO_UV_SCALE ); draw += InfoBase + NOD_ICON_OFFSET - draw.Upper_Left(); InfoRenderer->Add_Quad( draw, uv ); uv.Set( NEUTRAL_ICON_UV_UL, NEUTRAL_ICON_UV_LR ); draw = uv; uv.Scale( INFO_UV_SCALE ); draw += InfoBase + NEUTRAL_ICON_OFFSET - draw.Upper_Left(); InfoRenderer->Add_Quad( draw, uv ); // Radar uv.Set( RADAR_STAR_UV_UL, RADAR_STAR_UV_LR ); draw = uv; uv.Scale( INFO_UV_SCALE ); draw += InfoBase + RADAR_STAR_OFFSET - draw.Upper_Left(); InfoRenderer->Add_Quad( draw, uv ); uv.Set( RADAR_STAR_UV_UL, RADAR_STAR_UV_LR ); draw = uv; uv.Scale( INFO_UV_SCALE ); draw += InfoBase + RADAR_STAR_OFFSET - draw.Upper_Left(); InfoRenderer->Add_Quad( draw, uv ); uv.Set( RADAR_SQUARE_UV_UL, RADAR_SQUARE_UV_LR ); draw = uv; uv.Scale( INFO_UV_SCALE ); draw += InfoBase + RADAR_SQUARE_OFFSET - draw.Upper_Left(); InfoRenderer->Add_Quad( draw, uv ); uv.Set( RADAR_TRIANGLE_UV_UL, RADAR_TRIANGLE_UV_LR ); draw = uv; uv.Scale( INFO_UV_SCALE ); draw += InfoBase + RADAR_TRIANGLE_OFFSET - draw.Upper_Left(); InfoRenderer->Add_Quad( draw, uv ); uv.Set( RADAR_CIRCLE_UV_UL, RADAR_CIRCLE_UV_LR ); draw = uv; uv.Scale( INFO_UV_SCALE ); draw += InfoBase + RADAR_CIRCLE_OFFSET - draw.Upper_Left(); InfoRenderer->Add_Quad( draw, uv ); uv.Set( RADAR_BRACKET_UV_UL, RADAR_BRACKET_UV_LR ); draw = uv; uv.Scale( INFO_UV_SCALE ); draw += InfoBase + RADAR_BRACKET_OFFSET - draw.Upper_Left(); InfoRenderer->Add_Quad( draw, uv ); uv.Set( RADAR_SWEEP_UV_UL, RADAR_SWEEP_UV_LR ); draw = uv; uv.Scale( INFO_UV_SCALE ); draw += InfoBase + RADAR_SWEEP_OFFSET - draw.Upper_Left(); InfoRenderer->Add_Quad( draw, uv ); #endif } static void Info_Render( void ) { InfoRenderer->Render(); InfoHealthCountRenderer->Render(); InfoShieldCountRenderer->Render(); } /* ** OLD HUD STUFF */ static bool _HUDEnabled = true; static bool _HUDInited = false; #ifdef ATI_DEMO_HACK typedef enum { DEMO_HUD_IMAGE=0, DEMO_HUD_IMAGE2, NUM_RENDER_IMAGES, }; #else typedef enum { RETICLE = 0, RETICLE_HIT, ACTION_STATUSBAR_RENDERER, DEMO_HUD_IMAGE, DEMO_HUD_IMAGE2, NUM_RENDER_IMAGES, }; #endif Render2DClass * RenderImages[ NUM_RENDER_IMAGES ]; /* ** */ static bool Is_HUD_Displayed( void ); /* ** */ void HUDClass::Init(bool render_available) { for( int i = 0; i < NUM_RENDER_IMAGES; i++ ) { RenderImages[i] = NULL; } // Reticles #ifndef ATI_DEMO_HACK RenderImages[RETICLE] = new Render2DClass(); RenderImages[RETICLE]->Set_Texture( "HD_reticle.tga" ); RenderImages[RETICLE]->Set_Hidden( true ); RenderImages[RETICLE_HIT] = new Render2DClass(); RenderImages[RETICLE_HIT]->Set_Texture( "HD_reticle_hit.tga" ); RenderImages[RETICLE_HIT]->Set_Hidden( true ); // Action Status Bar (arming/disarming explosives, etc) RenderImages[ACTION_STATUSBAR_RENDERER] = new Render2DClass(); RenderImages[ACTION_STATUSBAR_RENDERER]->Set_Coordinate_Range( Render2DClass::Get_Screen_Resolution() ); #else RectClass rect=Render2DClass::Get_Screen_Resolution(); RenderImages[DEMO_HUD_IMAGE] = new Render2DClass(); RenderImages[DEMO_HUD_IMAGE]->Reset(); RenderImages[DEMO_HUD_IMAGE]->Set_Texture( "renegade_demo.tga" ); RenderImages[DEMO_HUD_IMAGE]->Set_Hidden( false ); RenderImages[DEMO_HUD_IMAGE]->Set_Coordinate_Range( Render2DClass::Get_Screen_Resolution() ); RenderImages[DEMO_HUD_IMAGE]->Add_Quad( RectClass( float(8),float(-8),float(256+8),float(128-8)), RectClass(0.0f,0.0f,1.0f,0.5f),0xffffffff); RenderImages[DEMO_HUD_IMAGE2] = new Render2DClass(); RenderImages[DEMO_HUD_IMAGE2]->Reset(); RenderImages[DEMO_HUD_IMAGE2]->Set_Texture( "renegade_demo.tga" ); RenderImages[DEMO_HUD_IMAGE2]->Set_Hidden( false ); RenderImages[DEMO_HUD_IMAGE2]->Set_Coordinate_Range( Render2DClass::Get_Screen_Resolution() ); RenderImages[DEMO_HUD_IMAGE2]->Add_Quad( RectClass( rect.Right+float(-256-8),rect.Bottom+float(-128+8),rect.Right+float(-8),rect.Bottom+float(8)), RectClass(0.0f,0.5f,1.0f,1.0f),0xffffffff); #endif if (render_available) { _HUDEnabled = true; SniperHUDClass::Init(); Powerup_Init(); Weapon_Init(); Weapon_Chart_Init(); Info_Init(); Damage_Init(); Target_Init(); //Score_Init(); Objective_Init(); HUD_Help_Text_Init(); _HUDInited = true; } } /* ** */ void HUDClass::Shutdown() { if (_HUDInited) { Objective_Shutdown(); //Score_Shutdown(); Target_Shutdown(); Damage_Shutdown(); Info_Shutdown(); Weapon_Chart_Shutdown(); Weapon_Shutdown(); Powerup_Shutdown(); HUD_Help_Text_Shutdown(); SniperHUDClass::Shutdown(); for( int i = 0; i < NUM_RENDER_IMAGES; i++ ) { if ( RenderImages[i] ) { delete RenderImages[i]; RenderImages[i] = NULL; } } _HUDInited = false; } } void HUDClass::Reset( void ) { Powerup_Reset(); Damage_Reset(); Weapon_Reset(); } void HUDClass::Render() { WWPROFILE( "HUD Render" ); #ifdef ATI_DEMO_HACK RenderImages[DEMO_HUD_IMAGE]->Render(); RenderImages[DEMO_HUD_IMAGE2]->Render(); #else if ( COMBAT_CAMERA && COMBAT_CAMERA->Draw_Sniper() ) { SniperHUDClass::Render(); } // Only render if Combat is active, and Menu is not, and we have a star who is not sniping if ( Is_HUD_Displayed() ) { Powerup_Render(); Weapon_Render(); Weapon_Chart_Render(); Info_Render(); Damage_Render(); Target_Render(); //Score_Render(); HUD_Help_Text_Render(); Objective_Render(); RadarManager::Render(); for( int i = 0; i < NUM_RENDER_IMAGES; i++ ) { if ( RenderImages[i] ) { RenderImages[i]->Render(); } } } #endif } static bool Is_HUD_Displayed( void ) { return ( _HUDEnabled && COMBAT_STAR && !COMBAT_STAR->Is_Dead() && !COMBAT_STAR->Is_Destroyed() ); } /* ** called each time through the main loop */ void HUDClass::Think() { WWPROFILE( "HUD Think" ); #ifndef ATI_DEMO_HACK if ( COMBAT_CAMERA && COMBAT_CAMERA->Draw_Sniper() ) { SniperHUDClass::Update(); } if ( !Is_HUD_Displayed() ) { return; } if ( HUDInfo::Display_Action_Status_Bar() ) { RenderImages[ACTION_STATUSBAR_RENDERER]->Set_Hidden( false ); RenderImages[ACTION_STATUSBAR_RENDERER]->Reset(); RenderImages[ACTION_STATUSBAR_RENDERER]->Enable_Texturing( false ); // // Plot the rectangle // const RectClass &screen_rect = Render2DClass::Get_Screen_Resolution(); RectClass status_bar_rect (0.4F, 0.95F, 0.6F, 0.98F); status_bar_rect.Left = int(status_bar_rect.Left * screen_rect.Width()); status_bar_rect.Right = int(status_bar_rect.Right * screen_rect.Width()); status_bar_rect.Top = int(status_bar_rect.Top * screen_rect.Height()); status_bar_rect.Bottom = int(status_bar_rect.Bottom * screen_rect.Height()); RenderImages[ACTION_STATUSBAR_RENDERER]->Add_Line( status_bar_rect.Upper_Left (), status_bar_rect.Upper_Right (), 1, 0xFFFFFFFF ); RenderImages[ACTION_STATUSBAR_RENDERER]->Add_Line( status_bar_rect.Upper_Right (), status_bar_rect.Lower_Right (), 1, 0xFFFFFFFF ); RenderImages[ACTION_STATUSBAR_RENDERER]->Add_Line( status_bar_rect.Lower_Right (), status_bar_rect.Lower_Left (), 1, 0xFFFFFFFF ); RenderImages[ACTION_STATUSBAR_RENDERER]->Add_Line( status_bar_rect.Lower_Left (), status_bar_rect.Upper_Left (), 1, 0xFFFFFFFF ); // // Deflate the rectangle // status_bar_rect.Right -= 1.0F; status_bar_rect.Bottom -= 1.0F; // // Plot the status rectangle // float width = status_bar_rect.Width() * HUDInfo::Get_Action_Status_Value(); status_bar_rect.Right = status_bar_rect.Left + int(width); DWORD color = VRGB_TO_INT32( Vector3( 1.0F, 0.25F, 0 ) ); RenderImages[ACTION_STATUSBAR_RENDERER]->Add_Quad( status_bar_rect, color ); } else { RenderImages[ACTION_STATUSBAR_RENDERER]->Set_Hidden( true ); } SmartGameObj * star = COMBAT_STAR; if ( COMBAT_STAR->Get_Vehicle() ) { star = COMBAT_STAR->Get_Vehicle(); } Info_Update(); Powerup_Update(); Weapon_Update(); Weapon_Chart_Update(); Damage_Update(); Target_Update(); //Score_Update(); Objective_Update(); // Radar Matrix3D tm; star->Get_Transform().Get_Inverse( tm ); if ( star->As_VehicleGameObj() && COMBAT_CAMERA && !COMBAT_CAMERA->Is_2D_Targeting() ) { // Make a tm facing target Matrix3D gun; gun.Obj_Look_At( star->Get_Transform().Get_Translation(), star->Get_Targeting_Pos(), 0 ); gun.Get_Inverse( tm ); } PhysicalGameObj * obj = NULL; if ( HUDInfo::Get_Info_Object() ) { obj = HUDInfo::Get_Info_Object()->As_PhysicalGameObj(); } RadarManager::Set_Bracket_Object( obj ); Vector2 radar_center = InfoBase + RADAR_CENTER_OFFSET; RadarManager::Update( tm, radar_center ); unsigned long reticle_color = HUDGlobalSettingsDef::Get_Instance()->Get_No_Relation_Color().Convert_To_ARGB(); if ( HUDInfo::Get_Weapon_Target_Object() != NULL ) { reticle_color = HUDGlobalSettingsDef::Get_Instance()->Get_Friendly_Color().Convert_To_ARGB(); PhysicalGameObj * pgo = HUDInfo::Get_Weapon_Target_Object()->As_PhysicalGameObj(); if ( pgo && pgo->Is_Enemy( star ) ) { reticle_color = HUDGlobalSettingsDef::Get_Instance()->Get_Enemy_Color().Convert_To_ARGB(); } } WeaponClass * weapon = star->Get_Weapon(); if ( weapon ) { if ( weapon->Is_Reloading() || weapon->Is_Switching() || !weapon->Is_Loaded() ) { reticle_color = 0xFFFFFF00; // yellow } } Vector2 reticle_offset = COMBAT_CAMERA->Get_Camera_Target_2D_Offset(); RenderImages[RETICLE]->Reset(); RenderImages[RETICLE]->Add_Quad( RectClass( reticle_offset.X - RETICLE_WIDTH/2, reticle_offset.Y - RETICLE_HEIGHT/2, reticle_offset.X + RETICLE_WIDTH/2, reticle_offset.Y + RETICLE_HEIGHT/2 ), reticle_color); //RenderImages[RETICLE]->Set_Hidden( false ); //TSS092401 if ( CombatManager::Is_Gameplay_Permitted() ) { RenderImages[RETICLE]->Set_Hidden( false ); } else { RenderImages[RETICLE]->Set_Hidden( true ); } //TSS092401 if ( weapon ) { if ( CombatManager::Is_Gameplay_Permitted() && (weapon != NULL) && CombatManager::Is_Hit_Reticle_Enabled() ) { WWPROFILE( "Reticle" ); Vector3 pos3d = HUDInfo::Get_Weapon_Target_Position(); Vector3 reticle_hit_offset; COMBAT_CAMERA->Project( reticle_hit_offset, pos3d ); // weapon_hitting = HUDInfo::Get_Weapon_Target_Object() != NULL; RenderImages[RETICLE_HIT]->Reset(); RenderImages[RETICLE_HIT]->Add_Quad( RectClass( reticle_hit_offset.X - RETICLE_WIDTH/2, reticle_hit_offset.Y - RETICLE_HEIGHT/2, reticle_hit_offset.X + RETICLE_WIDTH/2, reticle_hit_offset.Y + RETICLE_HEIGHT/2 ), reticle_color); RenderImages[RETICLE_HIT]->Set_Hidden( false ); } else { RenderImages[RETICLE_HIT]->Set_Hidden( true ); } #if 0 // Display points if ( _HUDTimer > 0 ) { WWPROFILE( "Points" ); _HUDTimer -= TimeManager::Get_Frame_Seconds(); StringClass pointstring; int points = _HUDPoints; if ( points ) { Vector2 position = Render2DClass::Get_Screen_Resolution().Lower_Right(); position /= 2; float scale = WWMath::Clamp( 2 * _HUDTimer / HUD_POINTS_TIME, 0, 1 ); position.Y *= 0.3f + (scale/2); pointstring.Format( "%d", points ); ((Render2DTextClass *)RenderImages[TEXT_RENDERER])->Set_Location( position ); Font3DInstanceClass * font = ((Render2DTextClass *)RenderImages[TEXT_RENDERER])->Peek_Font(); if ( font ) { font->Set_Scale( 2 + (scale * 3) ); position.X -= font->String_Width( pointstring ) / 2; position.Y -= font->Char_Height() / 2; ((Render2DTextClass *)RenderImages[TEXT_RENDERER])->Set_Location( position ); ((Render2DTextClass *)RenderImages[TEXT_RENDERER])->Draw_Text( pointstring, COLOR( scale ) ); font->Set_Scale( 1 ); } } } #endif #endif // ATI_DEMO_HACK } void HUDClass::Toggle_Hide_Points( void ) { // _HUDHidePoints = !_HUDHidePoints; } void HUDClass::Display_Points( float points ) { /* if ( !_HUDHidePoints ) { _HUDPoints = points; _HUDTimer = HUD_POINTS_TIME; }*/ } bool HUDClass::Is_Enabled( void ) { return _HUDEnabled; } void HUDClass::Enable( bool enable ) { _HUDEnabled = enable; } #define SNIPER_AMMO_UV 3, 139,79,191 #define SNIPER_AMMO_OFFSET -10,-4 #define NUKE_UV 193,187,244,246 #define NUKE_OFFSET 10,-4 #define ION_UV 101,196,164,246 #define ION_OFFSET 10,-4 void HUDClass::Add_Powerup_Weapon( int id, int rounds ) { const WeaponDefinitionClass * def = WeaponManager::Find_Weapon_Definition( id ); if ( def ) { if ( !def->IconTextureName.Is_Empty() ) { Powerup_Add( TranslateDBClass::Get_String( def->IconNameID ), rounds, def->IconTextureName, def->IconTextureUV, def->IconOffset ); } } } void HUDClass::Add_Powerup_Ammo( int id, int rounds ) { Add_Powerup_Weapon( id, rounds ); #if 0 const WeaponDefinitionClass * wdef = WeaponManager::Find_Weapon_Definition( id ); if ( wdef ) { const AmmoDefinitionClass * def = WeaponManager::Find_Ammo_Definition( wdef->PrimaryAmmoDefID ); if ( def ) { if ( !def->IconTextureName.Is_Empty() ) { Powerup_Add( TranslateDBClass::Get_String( def->IconNameID ), rounds, def->IconTextureName, def->IconTextureUV, def->IconOffset ); } } } #endif } void HUDClass::Add_Shield_Grant( float strength ) { const char * texture_name = "hud_armor3.tga"; if ( strength > 75 ) { texture_name = "hud_armor1.tga"; } else if ( strength > 30 ) { texture_name = "hud_armor2.tga"; } Powerup_Add( TranslateDBClass::Get_String(IDS_Power_up_Armor_00), (int)strength, texture_name, RectClass( 0,0,64,64 ), Vector2( 10,40 ) ); } void HUDClass::Add_Health_Grant( float amount ) { const char * texture_name = "hud_health1.tga"; if ( amount > 75 ) { texture_name = "hud_health3.tga"; } else if ( amount > 30 ) { texture_name = "hud_health2.tga"; } Powerup_Add( TranslateDBClass::Get_String(IDS_Power_up_Health_00), (int)amount, texture_name, RectClass( 0,0,64,64 ), Vector2( 10,40 ) ); } void HUDClass::Add_Shield_Upgrade_Grant( float strength ) { Powerup_Add( TranslateDBClass::Get_String(IDS_Power_up_Armor_Upgrade), (int)strength, "hud_armedal.tga", RectClass( 0,0,64,64 ), Vector2( 10,40 ), false ); } void HUDClass::Add_Health_Upgrade_Grant( float amount ) { Powerup_Add( TranslateDBClass::Get_String(IDS_Power_up_Health_Upgrade), (int)amount, "hud_hemedal.tga", RectClass( 0,0,64,64 ), Vector2( 10,40 ), false ); } void HUDClass::Add_Key_Grant( int key ) { const char * texture_name = "hud_keycard_green.tga"; if ( key == 3 ) { texture_name = "hud_keycard_red.tga"; } else if ( key == 2 ) { texture_name = "hud_keycard_yellow.tga"; } Powerup_Add( TranslateDBClass::Get_String(IDS_Power_up_SecurityCard), 0, texture_name, RectClass( 0,0,64,64 ), Vector2( 10,40 ), false ); } void HUDClass::Add_Objective( int type ) { if ( type == ObjectiveManager::TYPE_PRIMARY ) { Powerup_Add( TranslateDBClass::Get_String(IDS_Enc_Obj_Priority_0_Primary), 0, "p_eva1.tga", RectClass( 0,0,64,64 ), Vector2( 10,40 ), false ); } else if ( type == ObjectiveManager::TYPE_SECONDARY ) { Powerup_Add( TranslateDBClass::Get_String(IDS_Enc_Obj_Priority_0_Secondary), 0, "p_eva2.tga", RectClass( 0,0,64,64 ), Vector2( 10,40 ), false ); } } void HUDClass::Add_Data_Link( void ) { int cur = TimeManager::Get_Total_Seconds() * 2.0f; static int last = 0; // Don't accept too fast; if ( cur == last ) { return; } last = cur; Powerup_Add( TranslateDBClass::Get_String(IDS_Power_up_DataDisc_01), 0, "hud_cd_rom.tga", RectClass( 0,0,64,64 ), Vector2( 10,40 ), false ); } void HUDClass::Add_Map_Reveal( void ) { Add_Data_Link(); // Powerup_Add( TranslateDBClass::Get_String(IDS_Power_up_DataDisc_01), 0, "hud_cd_rom.tga", RectClass( 0,0,64,64 ), Vector2( 10,40 ), false ); // Powerup_Add( TranslateDBClass::Get_String(IDS_Enc_Pow_Bonus_Map_Name), 0, "hud_cd_rom.tga", RectClass( 0,0,64,64 ), Vector2( 10,40 ), false ); } /* ** */ enum { CHUNKID_VARIABLES = 1117011622, CHUNKID_MARKER_ENTRY, MICROCHUNKID_ENABLED = 1, }; /* ** */ bool HUDClass::Save( ChunkSaveClass &csave ) { csave.Begin_Chunk( CHUNKID_VARIABLES ); WRITE_MICRO_CHUNK( csave, MICROCHUNKID_ENABLED, _HUDEnabled ); csave.End_Chunk(); return true; } bool HUDClass::Load( ChunkLoadClass &cload ) { while (cload.Open_Chunk()) { switch(cload.Cur_Chunk_ID()) { case CHUNKID_VARIABLES: while (cload.Open_Micro_Chunk()) { switch(cload.Cur_Micro_Chunk_ID()) { READ_MICRO_CHUNK( cload, MICROCHUNKID_ENABLED, _HUDEnabled ); default: Debug_Say(("Unhandled Chunk:%d File:%s Line:%d\r\n",cload.Cur_Chunk_ID(),__FILE__,__LINE__)); break; } cload.Close_Micro_Chunk(); } break; default: Debug_Say(("Unhandled Chunk:%d File:%s Line:%d\r\n",cload.Cur_Chunk_ID(),__FILE__,__LINE__)); break; } cload.Close_Chunk(); } return true; }