#define MECHICON_CPP /*************************************************************************************************\ MechIcon.cpp : Implementation of the MechIcon component. //---------------------------------------------------------------------------// // Copyright (C) Microsoft Corporation. All rights reserved. // //===========================================================================// \*************************************************************************************************/ #include "MechIcon.h" #include "Mover.h" #include "Utilities.h" #include "Mech.h" #include "gvehicl.h" #include "GameCam.h" #include "controlgui.h" #include "gamesound.h" #include #ifndef MISSION_H #include "mission.h" #endif #ifndef MULTPLYR_H #include "multplyr.h" #endif TGAFileHeader *MechIcon::s_MechTextures = NULL; TGAFileHeader *VehicleIcon::s_VehicleTextures = NULL; TGAFileHeader* ForceGroupIcon::s_textureMemory = 0; StaticInfo* ForceGroupIcon::jumpJetIcon = NULL; MC2MoviePtr ForceGroupIcon::bMovie = NULL; unsigned long ForceGroupIcon::pilotVideoTexture = 0; MechWarrior* ForceGroupIcon::pilotVideoPilot = NULL; #define HEALTH_BAROFFSET 12.0f * Environment.screenHeight/600.f #define HEALTH_BARLENGTH 31.0f * Environment.screenWidth/600.f #define HEALTH_BARHEIGHT 2.0f * Environment.screenHeight/600.f #define TEXT_HEIGHT 8.0f * Environment.screenHeight/480.f float MechIcon::unitIconX = 32; float MechIcon::unitIconY = 38; float PilotIcon::pilotIconX = 25; float PilotIcon::pilotIconY = 36; const long PilotIcon::DEAD_PILOT_INDEX = 27; unsigned long PilotIcon::s_pilotTextureHandle = 0; unsigned long PilotIcon::s_pilotTextureWidth = 0; long ForceGroupIcon::pilotTextTop[17] = {0}; long MechIcon::damageColors[4][3] = { 194 << 16 | 229 << 8 | 255 | 0xff << 24, 92 << 16 | 150 << 8 | 194 | 0xff << 24, 0 << 16 | 83 << 8 | 146 | 0xff << 24, 248 << 16 | 241 << 8 | 193 | 0xff << 24, 248 << 16 | 206 << 8 | 31 | 0xff << 24, 139 << 16 | 114 << 8 | 0 | 0xff << 24, 248 << 16 | 193 << 8 | 193 | 0xff << 24, 248 << 16 | 31 << 8 | 31 | 0xff << 24, 139 << 16 | 0 << 8 | 0 | 0xff << 24, 94 << 16 | 101 << 8 | 101 | 0xff << 24, 56 << 16 | 64 << 8 | 64 | 0xff << 24, 26 << 16 | 33 << 8 | 33 | 0xff << 24 }; long MechIcon::ForceGroupColors[11] = { 0xff005392, 0xffC66600, 0xff6E7C00, 0xffB70000, 0xff620053, 0xffD8AD00, 0xff8B00BE, 0xffFF0000, 0xffFF8A00, 0xff0091FF, 0xff505050 }; ForceGroupIcon::AnimationInfo ForceGroupIcon::animationInfos[NUM_DEATH_INFOS] = { 0.f, 0, 2.5f, 0, 5.0f, 0x7fff0000, 5.35f, 0x7fff0000, 6.0f, 0xff000000, 6.5f, 0xff000000 }; unsigned long ForceGroupIcon::s_textureHandle[5] = { -1, -1, -1, -1, -1 }; bool ForceGroupIcon::s_slotUsed[240] = { 0 }; gos_VERTEX ForceGroupIcon:: bmpLocation[17][5] = {0}; // in screen coords GUI_RECT ForceGroupIcon:: textArea[17] = {0}; GUI_RECT ForceGroupIcon:: pilotRect[17] = {0}; GUI_RECT ForceGroupIcon:: selectionRect[17] = {0}; GUI_RECT ForceGroupIcon:: healthBar[17] = {0}; float ForceGroupIcon:: pilotLocation[17][4] = {0}; aFont* ForceGroupIcon::gosFontHandle = 0; int ForceGroupIcon::curScreenWidth = 800; #define ICON_REALSIZE 256 ForceGroupIcon::ForceGroupIcon( ) { unit = NULL; bDrawBack = 0; backDamageIndex = -1; damageIconIndex = 0; locationIndex = 0; if ( s_textureHandle[0] == -1 ) { // this is the textures that all icons are using long size = ( 256 * 256 * sizeof( long ) + sizeof( TGAFileHeader ) ); s_textureMemory = (TGAFileHeader*)new char[size]; memset( s_textureMemory, 0, size ); s_textureMemory->height = 256; s_textureMemory->width = 256; s_textureMemory->pixel_depth = 32; s_textureMemory->image_type = UNC_PAL; if ( s_textureHandle[0] == -1 ) s_textureHandle[0] = gos_NewTextureFromMemory( gos_Texture_Alpha, ".tga", (unsigned char*)s_textureMemory, size, 0 ); memset( s_slotUsed, 0, 240 * sizeof( bool ) ); } bool bFound = 0; for ( int index = 0; index < 240; index++ ) { if ( !s_slotUsed[ index ] ) { damageIconIndex = index; s_slotUsed[index] = 1; bFound = 1; break; } } Assert( bFound, bFound, "out of space for icon textures" ); deathAnimationTime = 0.0; msgPlayTime = 0.0f; } void ForceGroupIcon::resetResolution(bool bForce) { if ( curScreenWidth != Environment.screenWidth || bForce ) { delete [] MechIcon::s_MechTextures; MechIcon::s_MechTextures = 0; delete [] VehicleIcon::s_VehicleTextures; VehicleIcon::s_VehicleTextures = 0; setIconVariables(); PilotIcon::swapResolutions(); } curScreenWidth = Environment.screenWidth; } void ForceGroupIcon::swapResolutions( bool bForce ) { resetResolution(bForce); init( unit ); } ForceGroupIcon::~ForceGroupIcon() { if (pilotVideoPilot && pilotVideoPilot == unit->getPilot() ) { if ( bMovie ) { delete bMovie; bMovie = NULL; pilotVideoTexture = 0; } pilotVideoPilot = NULL; } s_slotUsed[damageIconIndex] = 0; if ( backDamageIndex != -1 ) s_slotUsed[ backDamageIndex ] = 0; } void ForceGroupIcon::init( FitIniFile& file, int which ) { char buffer[256]; sprintf( buffer, "MechIcon%ld", which ); if ( NO_ERR != file.seekBlock( buffer ) ) Assert( 0, 0, "couldn't find the icon" ); if ( !gosFontHandle ) gosFontHandle = new aFont(); file.readIdLong( "TextAReaLeft", textArea[which].left ); file.readIdLong( "TextAreaRight", textArea[which].right ); file.readIdLong( "TextAReaTop", textArea[which].top ); file.readIdLong( "TextAreaBottom", textArea[which].bottom ); textArea[which].left += ControlGui::hiResOffsetX; textArea[which].right += ControlGui::hiResOffsetX; textArea[which].top += ControlGui::hiResOffsetY; textArea[which].bottom += ControlGui::hiResOffsetY; file.readIdLong( "PilotTextTop", pilotTextTop[which] ); pilotTextTop[which] += ControlGui::hiResOffsetY; long left, right, top, bottom; file.readIdLong( "MechIconAreaLeft", left ); file.readIdLong( "MechIconArearight", right ); file.readIdLong( "MechIconAreaTop", top ); file.readIdLong( "MechIconAreaBottom", bottom ); left += ControlGui::hiResOffsetX; right += ControlGui::hiResOffsetX; top += ControlGui::hiResOffsetY; bottom += ControlGui::hiResOffsetY; for ( int i = 0; i < 4; i++ ) { bmpLocation[which][i].x = left; bmpLocation[which][i].y = top; bmpLocation[which][i].argb = 0xffffffff; bmpLocation[which][i].rhw = 0.5; } bmpLocation[which][2].x = bmpLocation[which][3].x = right; bmpLocation[which][1].y = bmpLocation[which][2].y = bottom; bmpLocation[which][4] = bmpLocation[which][0]; file.readIdLong( "PilotAreaLeft", left ); file.readIdLong( "PilotAreaRight", right ); file.readIdLong( "PilotAreaTop", top ); file.readIdLong( "PilotAreaBottom", bottom ); left += ControlGui::hiResOffsetX; right += ControlGui::hiResOffsetX; top += ControlGui::hiResOffsetY; bottom += ControlGui::hiResOffsetY; pilotLocation[which][0] = left; pilotLocation[which][1] = top; pilotLocation[which][2] = right; pilotLocation[which][3] = bottom; file.readIdLong( "PilotRectLeft", pilotRect[which].left ); file.readIdLong( "PilotRectRight", pilotRect[which].right ); file.readIdLong( "PilotRectTop", pilotRect[which].top ); file.readIdLong( "PilotRectBottom", pilotRect[which].bottom ); pilotRect[which].left += ControlGui::hiResOffsetX; pilotRect[which].right += ControlGui::hiResOffsetX; pilotRect[which].top += ControlGui::hiResOffsetY; pilotRect[which].bottom += ControlGui::hiResOffsetY; file.readIdLong( "SelectionRectLeft", selectionRect[which].left ); file.readIdLong( "SelectionRectRight", selectionRect[which].right ); file.readIdLong( "SelectionRectTop", selectionRect[which].top ); file.readIdLong( "SelectionRectBottom", selectionRect[which].bottom ); selectionRect[which].left += ControlGui::hiResOffsetX; selectionRect[which].right += ControlGui::hiResOffsetX; selectionRect[which].top += ControlGui::hiResOffsetY; selectionRect[which].bottom += ControlGui::hiResOffsetY; file.readIdLong( "HealthBarLeft", healthBar[which].left ); file.readIdLong( "HealthBarRight", healthBar[which].right ); file.readIdLong( "HealthBarTop", healthBar[which].top ); file.readIdLong( "HealthBarBottom", healthBar[which].bottom ); healthBar[which].left += ControlGui::hiResOffsetX; healthBar[which].right += ControlGui::hiResOffsetX; healthBar[which].top += ControlGui::hiResOffsetY; healthBar[which].bottom += ControlGui::hiResOffsetY; if ( !jumpJetIcon ) jumpJetIcon = new StaticInfo; jumpJetIcon->init( file, "JumpJetIcon", 0, 0 ); } void MechIcon::setDrawBack( bool bSet) { bDrawBack = bSet; bool bFound = 0; for ( int index = 0; index < 240; index++ ) { if ( !s_slotUsed[ index ] ) { backDamageIndex = index; s_slotUsed[index] = 1; bFound = 1; break; } } int iconsPerLine = ((int)s_textureMemory->width/(int)unitIconX); int iconsPerPage = ((int)s_textureMemory->width/(int)unitIconY); long textureIndex = 0; long row = (backDamageIndex/iconsPerLine); if ( row >= iconsPerPage ) { textureIndex = row/iconsPerPage; row = row % iconsPerPage; } long column = (backDamageIndex % iconsPerLine); long offsetY = row * unitIconY; long offsetX = column * unitIconX; Assert( bFound, bFound, "out of space for icon textures" ); if ( s_textureHandle[textureIndex] == -1 ) { long size = ( 256 * 256 * sizeof( long ) + sizeof( TGAFileHeader ) ); s_textureHandle[textureIndex] = gos_NewTextureFromMemory( gos_Texture_Alpha, ".tga", (unsigned char*)s_textureMemory, size, 0 ); } // now need to make a copy of the data TEXTUREPTR textureData; gos_LockTexture( s_textureHandle[textureIndex], 0, 0, &textureData ); unsigned long* pDestData, *pDestRow = textureData.pTexture + offsetY * textureData.Width + offsetX; char* pTmp = (char*)s_MechTextures + sizeof ( TGAFileHeader ); unsigned long* pSrcRow = (unsigned long*)pTmp; long whichMech = unit->getIconPictureIndex(); offsetY = unitIconY; offsetX = whichMech * unitIconX; long tmpOffset = ((s_MechTextures->width) * (offsetY ) + offsetX); pSrcRow += tmpOffset; unsigned long* pSrcData = pSrcRow; for( int j = 0; j < unitIconY; ++j ) { pDestData = pDestRow; pSrcData = pSrcRow; for ( int i = 0; i < unitIconX; ++i ) // do four icons per row { bool bDraw = 0; // compare colors, only draw back ones which are 4, 5, 6, and 7 for ( int i = 0; i < 3; i++ ) { long compColor = damageColors[0][i]; long srcColor = *pSrcData; long compMin = compColor >> 16; compMin += 4; long compMax = compMin + 3; if ( srcColor >> 16 >= compMin && srcColor >> 16 <= compMax ) { bDraw = 1; } } if ( *pSrcData == 0xff505050 ) bDraw = 1; if ( bDraw ) *pDestData++ = *pSrcData; else *pDestData++ = 0; pSrcData++; } pSrcRow += s_MechTextures->width; pDestRow += textureData.Width; } gos_UnLockTexture( s_textureHandle[textureIndex] ); } bool ForceGroupIcon::inRegion( int x, int y ) { return ( x >= selectionRect[locationIndex].left && x <= selectionRect[locationIndex].right && y >= selectionRect[locationIndex].top && y <= selectionRect[locationIndex].bottom ); } void ForceGroupIcon::rightClick() { ((GameCamera*)eye)->setTarget( unit ); } void ForceGroupIcon::click( bool shiftDn ) { if ( shiftDn && !unit->isSelected() ) { unit->setSelected( true ); } else if ( !shiftDn ) { unit->setSelected( true ); } else { unit->setSelected( false ); } soundSystem->playDigitalSample( LOG_SELECT ); } void ForceGroupIcon::init( ) { } bool MechIcon::initTextures() { if ( !s_MechTextures ) { File file; char path[256]; strcpy( path, artPath ); if ( Environment.screenWidth == 800 ) strcat( path, "mcui_med4.tga" ); else if ( Environment.screenWidth == 640 ) strcat( path, "mcui_low4.tga" ); else strcat( path, "mcui_high7.tga" ); _strlwr( path ); if ( NO_ERR != file.open( path ) ) { Assert( 0, 0, "Couldn't open the mech parts" ); return false; } setIconVariables(); int size = file.getLength(); s_MechTextures = (TGAFileHeader*)new char[size]; file.read( (BYTE*)s_MechTextures, size ); BYTE* pTmp = (BYTE*)(s_MechTextures + 1); flipTopToBottom (pTmp, s_MechTextures->pixel_depth, s_MechTextures->width, s_MechTextures->height ); } return true; } bool MechIcon::init( Mover* pMover ) { ForceGroupIcon::init(); if ( !pMover ) return 0; long whichMech = pMover->getIconPictureIndex(); bool bRetVal = init( whichMech ); unit = pMover; pilotIcon.setPilot( pMover->getPilot() ); return bRetVal; } bool MechIcon::init( long whichIndex ) { initTextures(); int pixelDepth = s_MechTextures->pixel_depth/8; if ( pixelDepth != 4 ) PAUSE(("Texture for MechIcon not 32-bit")); int iconsPerLine = ((int)s_textureMemory->width/(int)unitIconX); int iconsPerPage = ((int)s_textureMemory->width/(int)unitIconY); long textureIndex = 0; long row = (damageIconIndex/iconsPerLine); if ( row >= iconsPerPage ) { textureIndex = row/iconsPerPage; row = row % iconsPerPage; } long column = (damageIconIndex % iconsPerLine); long offsetY = (row) * unitIconY; long offsetX = (column) * unitIconX; if ( s_textureHandle[textureIndex] == -1 ) { long size = ( 256 * 256 * sizeof( long ) + sizeof( TGAFileHeader ) ); s_textureHandle[textureIndex] = gos_NewTextureFromMemory( gos_Texture_Alpha, ".tga", (unsigned char*)s_textureMemory, size, 0 ); } // now need to make a copy of the data TEXTUREPTR textureData; gos_LockTexture( s_textureHandle[textureIndex], 0, 0, &textureData ); unsigned long* pDestData, *pDestRow = textureData.pTexture + offsetY * textureData.Width + offsetX; char* pTmp = (char*)s_MechTextures + sizeof ( TGAFileHeader ); unsigned long* pSrcRow = (unsigned long*)pTmp; offsetY = 0; offsetX = whichIndex * unitIconX; long tmpOffset = ((s_MechTextures->width) * (offsetY ) + offsetX); pSrcRow += tmpOffset; unsigned long* pSrcData = pSrcRow; for( int j = 0; j < unitIconY; ++j ) { pDestData = pDestRow; pSrcData = pSrcRow; for ( int i = 0; i < unitIconX; ++i ) // do four icons per row { *pDestData++ = *pSrcData++; } pSrcRow += s_MechTextures->width; pDestRow += textureData.Width; } gos_UnLockTexture( s_textureHandle[textureIndex] ); for ( int i = 0; i < 5; ++i ) { bmpLocation[locationIndex][i].argb = 0xffffffff; bmpLocation[locationIndex][i].frgb = 0; bmpLocation[locationIndex][i].rhw = .5; bmpLocation[locationIndex][i].u = 0.; bmpLocation[locationIndex][i].v = 0.; bmpLocation[locationIndex][i].z = 0.; } memset( damage, 0, 8 ); memset( backDamage, 0, 8 ); return true; } void MechIcon::update() { // need to check object's status here char newDamage[8]; char rearDamage[8]; memset( newDamage, 0, 8 ); memset( rearDamage, 0, 8 ); // do check against armor location ArmorLocation armor = unit->armor[MECH_ARMOR_LOCATION_HEAD]; float tmp = armor.curArmor/(float)armor.maxArmor; if (unit->body[MECH_BODY_LOCATION_HEAD].damageState == IS_DAMAGE_DESTROYED) tmp = -1.0f; float backTmp = 0; if ( tmp < .0 ) newDamage[7] = 3; else if ( tmp < .3 ) newDamage[7] = 2; else if ( tmp < .6 ) newDamage[7] = 1; tmp = unit->armor[MECH_ARMOR_LOCATION_CTORSO].curArmor/(float)unit->armor[MECH_ARMOR_LOCATION_CTORSO].maxArmor; if ( !bDrawBack ) { if ( (float)unit->armor[MECH_ARMOR_LOCATION_RCTORSO].maxArmor ) tmp += unit->armor[MECH_ARMOR_LOCATION_RCTORSO].curArmor/(float)unit->armor[MECH_ARMOR_LOCATION_RCTORSO].maxArmor; tmp/= 2.f; } else { backTmp = unit->armor[MECH_ARMOR_LOCATION_RCTORSO].curArmor/(float)unit->armor[MECH_ARMOR_LOCATION_RCTORSO].maxArmor; } if (unit->body[MECH_BODY_LOCATION_CTORSO].damageState == IS_DAMAGE_DESTROYED) { tmp = -1.0f; backTmp = -1.0f; } if ( tmp < .0 ) newDamage[6] = 3; else if ( tmp < .3 ) newDamage[6] = 2; else if ( tmp < .6 ) newDamage[6] = 1; if ( backTmp < .0 ) rearDamage[6] = 3; else if ( backTmp < .3 ) rearDamage[6] = 2; else if ( backTmp < .6 ) rearDamage[6] = 1; tmp = unit->armor[MECH_ARMOR_LOCATION_LTORSO].curArmor/(float)unit->armor[MECH_ARMOR_LOCATION_LTORSO].maxArmor; if ( !bDrawBack ) { if ( (float)unit->armor[MECH_ARMOR_LOCATION_RLTORSO].maxArmor ) tmp += unit->armor[MECH_ARMOR_LOCATION_RLTORSO].curArmor/(float)unit->armor[MECH_ARMOR_LOCATION_RLTORSO].maxArmor; tmp/= 2.f; } else { backTmp = unit->armor[MECH_ARMOR_LOCATION_RLTORSO].curArmor/(float)unit->armor[MECH_ARMOR_LOCATION_RLTORSO].maxArmor; } if (bMovie) { bool result = bMovie->update(); if (result) { delete bMovie; bMovie = NULL; } } if (unit->body[MECH_BODY_LOCATION_LTORSO].damageState == IS_DAMAGE_DESTROYED) { tmp = -1.0f; backTmp = -1.0f; } if ( tmp < .0 ) newDamage[5] = 3; else if ( tmp < .3 ) newDamage[5] = 2; else if ( tmp < .6 ) newDamage[5] = 1; if ( backTmp < .0 ) rearDamage[5] = 3; else if ( backTmp < .3 ) rearDamage[5] = 2; else if ( backTmp < .5 ) rearDamage[5] = 1; tmp = unit->armor[MECH_ARMOR_LOCATION_RTORSO].curArmor/(float)unit->armor[MECH_ARMOR_LOCATION_RTORSO].maxArmor; if ( !bDrawBack ) { if ( (float)unit->armor[MECH_ARMOR_LOCATION_RRTORSO].maxArmor ) tmp += unit->armor[MECH_ARMOR_LOCATION_RRTORSO].curArmor/(float)unit->armor[MECH_ARMOR_LOCATION_RRTORSO].maxArmor; tmp/= 2.f; } else { backTmp = unit->armor[MECH_ARMOR_LOCATION_RRTORSO].curArmor/(float)unit->armor[MECH_ARMOR_LOCATION_RRTORSO].maxArmor; } if (unit->body[MECH_BODY_LOCATION_RTORSO].damageState == IS_DAMAGE_DESTROYED) { tmp = -1.0f; backTmp = -1.0f; } if ( tmp < .0 ) newDamage[4] = 3; else if ( tmp < .3 ) newDamage[4] = 2; else if ( tmp < .6 ) newDamage[4] = 1; if ( backTmp < .0 ) rearDamage[4] = 3; else if ( backTmp < .3 ) rearDamage[4] = 2; else if ( backTmp < .4 ) rearDamage[4] = 1; armor = unit->armor[MECH_ARMOR_LOCATION_LLEG]; tmp = armor.curArmor/(float)armor.maxArmor; if (unit->body[MECH_BODY_LOCATION_LLEG].damageState == IS_DAMAGE_DESTROYED) { tmp = -1.0f; } if ( tmp < .0 ) newDamage[0] = 3; else if ( tmp < .3 ) newDamage[0] = 2; else if ( tmp < .6 ) newDamage[0] = 1; armor = unit->armor[MECH_ARMOR_LOCATION_RLEG]; tmp = armor.curArmor/(float)armor.maxArmor; if (unit->body[MECH_BODY_LOCATION_RLEG].damageState == IS_DAMAGE_DESTROYED) { tmp = -1.0f; } if ( tmp < .0 ) newDamage[1] = 3; else if ( tmp < .3 ) newDamage[1] = 2; else if ( tmp < .6 ) newDamage[1] = 1; armor = unit->armor[MECH_ARMOR_LOCATION_LARM]; tmp = armor.curArmor/(float)armor.maxArmor; if (unit->body[MECH_BODY_LOCATION_LARM].damageState == IS_DAMAGE_DESTROYED) { tmp = -1.0f; } if ( tmp < .0 ) newDamage[2] = 3; else if ( tmp < .3 ) newDamage[2] = 2; else if ( tmp < .6 ) newDamage[2] = 1; armor = unit->armor[MECH_ARMOR_LOCATION_RARM]; tmp = armor.curArmor/(float)armor.maxArmor; if (unit->body[MECH_BODY_LOCATION_RARM].damageState == IS_DAMAGE_DESTROYED) { tmp = -1.0f; backTmp = -1.0f; } if ( tmp < .0 ) newDamage[3] = 3; else if ( tmp < .3 ) newDamage[3] = 2; else if ( tmp < .6 ) newDamage[3] = 1; doDraw( newDamage, damage, -1, damageIconIndex ); if ( bDrawBack ) { float lratio = 1.f; float rratio = 1.f; if ( (float)unit->armor[MECH_ARMOR_LOCATION_RCTORSO].maxArmor ) { lratio = (float)unit->armor[MECH_ARMOR_LOCATION_RLTORSO].maxArmor/(float)unit->armor[MECH_ARMOR_LOCATION_RCTORSO].maxArmor; rratio = (float)unit->armor[MECH_ARMOR_LOCATION_RRTORSO].maxArmor/(float)unit->armor[MECH_ARMOR_LOCATION_RCTORSO].maxArmor; } rearDamage[7] = .5 + (float)((rratio * rearDamage[4] + lratio * rearDamage[5] + rearDamage[6]))/(lratio + rratio + 1.f); backDamage[7] = .5 + (float)((rratio * backDamage[4] + lratio * backDamage[5] + backDamage[6]))/(lratio + rratio + 1.f); doDraw( rearDamage, backDamage, -1, backDamageIndex ); } } void MechIcon::doDraw( char* newDamage, char* oldDamage, unsigned long handle, unsigned long index ) { int i = 0; int maxToCheck = 8; if ( index == backDamageIndex ) i = 7; for ( ; i < maxToCheck; ++i ) { // if damage has changeed, update that part of the icon, we really don't want to do this // every frame if ( newDamage[i] != oldDamage[i] ) { // find the icon long texIndex = 0; int iconsPerLine = ((int)s_textureMemory->width/(int)unitIconX); int iconsPerPage = ((int)s_textureMemory->width/(int)unitIconY); int yIndex = index / iconsPerLine; if ( yIndex >= iconsPerPage ) { texIndex = yIndex/iconsPerPage; yIndex = yIndex % iconsPerPage; } int xIndex = index % iconsPerLine; if ( s_textureHandle[texIndex] == -1 ) { long size = ( 256 * 256 * sizeof( long ) + sizeof( TGAFileHeader ) ); s_textureHandle[texIndex] = gos_NewTextureFromMemory( gos_Texture_Alpha, ".tga", (unsigned char*)s_textureMemory, size, 0 ); } TEXTUREPTR textureData; gos_LockTexture( s_textureHandle[texIndex], 0, 0, &textureData ); unsigned long* pData = textureData.pTexture; // go to write spot in texture int jLine = yIndex * unitIconY; int iLine = xIndex * unitIconX; unsigned long* pLine = (unsigned long*)(pData + (jLine * textureData.Width) + iLine); unsigned long* pChange = pLine; unsigned long oldColors[3]; unsigned long newColors[3]; // find the colors we're looking for for ( int p = 0; p < 3; p++ ) { int tmp = damageColors[damage[i]][p]; int redVal = (tmp >> 16) & 0x000000ff; redVal += i; oldColors[p] = ( tmp & 0xff00ffff ) | (redVal << 16); tmp = damageColors[newDamage[i]][p]; redVal = (tmp >> 16) & 0x000000ff; redVal += i; newColors[p] = ( tmp & 0xff00ffff ) | (redVal << 16); } // look through the entire bitmap, changing old colors to new colors for ( int k = 0; k < unitIconY; ++k ) { pChange = pLine; for ( int j = 0; j < unitIconX; ++j ) { if ( (*pChange)&0xff000000 ) // not transparent { for ( p = 0; p < 3; p++ ) { if ( oldColors[p] == *pChange ) { *pChange = newColors[p]; } } } pChange++; } pLine += textureData.Width; } gos_UnLockTexture( s_textureHandle[texIndex] ); } oldDamage[i] = newDamage[i]; } } bool IsDbcsString(const char* pszString) { if (pszString) { while (*pszString) { if (IsDBCSLeadByte((BYTE)*pszString)) return true; pszString++; } } return false; } void ForceGroupIcon::render() { // here I draw the text if ( !unit ) return; int forceGroup = -1; for ( int i = 0; i < 10; ++i ) { if ( unit->isInUnitGroup( i ) ) forceGroup = i; } // draw little colored background if ( forceGroup == 0 ) forceGroup = 10; int color = forceGroup == -1 ? ForceGroupColors[10] : ForceGroupColors[forceGroup-1]; float health = unit->getAppearance()->barStatus; // draw pilotName GUI_RECT tmpRect = { textArea[locationIndex].left, textArea[locationIndex].top, textArea[locationIndex].right, textArea[locationIndex].bottom }; drawRect( tmpRect, color); char buffer[256]; strcpy( buffer, unit->getPilot()->getName() ); for ( i = 0; i < strlen( buffer ); i++ ) CharUpper( buffer ); gosFontHandle->render( buffer, textArea[locationIndex].left + 1, pilotTextTop[locationIndex], 0, 0, 0xffffffff, 0, 0 ); // draw the health bar drawBar( health ); // draw the little unit icon renderUnitIcon( bmpLocation[locationIndex][0].x, bmpLocation[locationIndex][0].y, bmpLocation[locationIndex][2].x, bmpLocation[locationIndex][2].y ); pilotIcon.render( pilotLocation[locationIndex][0], pilotLocation[locationIndex][1], pilotLocation[locationIndex][2], pilotLocation[locationIndex][3] ); drawEmptyRect( pilotRect[locationIndex], 0xff002f55, 0xff002f55 ); // if has jumpjets, draws jump jet icon if ( unit->canJump() ) { jumpJetIcon->move( selectionRect[locationIndex].left, selectionRect[locationIndex].bottom ); jumpJetIcon->render( ); jumpJetIcon->move( -selectionRect[locationIndex].left, -selectionRect[locationIndex].bottom ); } if ( pilotVideoPilot == unit->getPilot() ) { gos_VERTEX v[4]; for ( i = 0; i < 4; i++ ) { v[i] = bmpLocation[locationIndex][i]; v[i].u = 0.f; v[i].v = 0.f; } v[2].x = v[3].x = pilotLocation[locationIndex][2]; v[2].u = v[3].u = .59375; v[1].v = v[2].v = .828125f; RECT vRect; vRect.left = bmpLocation[locationIndex][1].x; vRect.right = pilotLocation[locationIndex][2]; vRect.top = bmpLocation[locationIndex][3].y; vRect.bottom = bmpLocation[locationIndex][1].y; if ( bMovie ) { if ( unit && (unit->getStatus () == OBJECT_STATUS_SHUTDOWN) ) { bMovie->stop(); delete bMovie; bMovie = NULL; pilotVideoPilot = NULL; } else { bMovie->setRect(vRect); bMovie->render(); } } else if ( pilotVideoTexture ) { gos_SetRenderState( gos_State_Texture, pilotVideoTexture ); v[1].v = v[2].v = .4140625; gos_DrawQuads( v, 4 ); } } if ( unit && (unit->getStatus () == OBJECT_STATUS_SHUTDOWN) ) { drawRect( selectionRect[locationIndex], 0xaa000000 ); } // if selected, draw white rectangle if ( unit->getSelected() ) { drawEmptyRect( selectionRect[locationIndex], 0xffffffff, 0xffffffff ); } if ( unit->getPilot() ) { if ( unit->getPilot()->getMessagePlaying() ) { long color = 0xffffff00; msgPlayTime += frameLength; if ( msgPlayTime > .25 ) msgPlayTime = 0; if ( msgPlayTime > .125 ) color = 0x00000000; drawEmptyRect( selectionRect[locationIndex], color, color ); } else msgPlayTime = 0; } // draw dying effect if ( deathAnimationTime ) { drawDeathEffect(); } } void ForceGroupIcon::renderUnitIcon( float left, float top, float right, float bottom ) { int texIndex = 0; int iconsPerLine = ((int)s_textureMemory->width/(int)unitIconX); int iconsPerPage= ((int)s_textureMemory->width/(int)unitIconY); int yIndex = damageIconIndex / iconsPerLine; if ( yIndex >= iconsPerPage ) { texIndex = yIndex / iconsPerPage; yIndex = yIndex % iconsPerPage; } int xIndex = damageIconIndex % iconsPerLine; float u = xIndex * unitIconX/s_textureMemory->width + (.1f / 256.f); float v = yIndex * unitIconY/s_textureMemory->height+ (.1f / 256.f); float uDelta = unitIconX/s_textureMemory->width + (.1f / 256.f ); float vDelta = unitIconY/s_textureMemory->height + (.1f / 256.f); gos_SetRenderState( gos_State_Texture, s_textureHandle[texIndex] ); gos_SetRenderState( gos_State_AlphaMode, gos_Alpha_AlphaInvAlpha); gos_SetRenderState( gos_State_Filter, gos_FilterNone); gos_SetRenderState( gos_State_AlphaTest, true); bmpLocation[locationIndex][0].u = bmpLocation[locationIndex][1].u = u; bmpLocation[locationIndex][2].u = bmpLocation[locationIndex][3].u = u + uDelta; bmpLocation[locationIndex][0].v = bmpLocation[locationIndex][3].v = v; bmpLocation[locationIndex][1].v = bmpLocation[locationIndex][2].v = v + vDelta; bmpLocation[locationIndex][0].x = bmpLocation[locationIndex][1].x = left; bmpLocation[locationIndex][2].x = bmpLocation[locationIndex][3].x = right; bmpLocation[locationIndex][0].y = bmpLocation[locationIndex][3].y = top; bmpLocation[locationIndex][1].y = bmpLocation[locationIndex][2].y = bottom; bmpLocation[locationIndex][4] = bmpLocation[locationIndex][0]; gos_DrawTriangles( bmpLocation[locationIndex], 3 ); gos_DrawTriangles( &bmpLocation[locationIndex][2], 3 ); } void ForceGroupIcon::renderUnitIconBack( float left, float top, float right, float bottom ) { int iconsPerLine = ((int)s_textureMemory->width/(int)unitIconX); int yIndex = backDamageIndex / iconsPerLine; int xIndex = backDamageIndex % iconsPerLine; float u = xIndex * unitIconX/s_textureMemory->width+ (.1f / (float)256.f); float v = yIndex * unitIconY/s_textureMemory->height+ (.1f / (float)256.f); float uDelta = unitIconX/s_textureMemory->width + (.1f / (float)256.f ); float vDelta = unitIconY/s_textureMemory->height + (.1f / (float)256.f); gos_SetRenderState( gos_State_Texture, s_textureHandle[0] ); gos_SetRenderState( gos_State_AlphaMode, gos_Alpha_AlphaInvAlpha); gos_SetRenderState( gos_State_Filter, gos_FilterNone); gos_SetRenderState( gos_State_AlphaTest, true); gos_VERTEX vertices[5]; for ( int i = 0; i < 5; i++ ) { vertices[i].argb = 0xffffffff; vertices[i].frgb = 0; vertices[i].z = 0; vertices[i].rhw = .5; } vertices[0].u = vertices[1].u = u; vertices[2].u = vertices[3].u = u + uDelta; vertices[0].v = vertices[3].v = v; vertices[1].v = vertices[2].v = v + vDelta; vertices[0].x = vertices[1].x = left; vertices[2].x = vertices[3].x = right; vertices[0].y = vertices[3].y = top; vertices[1].y = vertices[2].y = bottom; vertices[4] = vertices[0]; gos_DrawTriangles( vertices, 3 ); gos_DrawTriangles( &vertices[2], 3 ); } void ForceGroupIcon::renderPilotIcon( float left, float top, float right, float bottom ) { pilotIcon.render( left, top, right, bottom ); } bool VehicleIcon::init( Mover* pMover ) { if ( !s_VehicleTextures ) { File file; char path[256]; strcpy( path, artPath ); if ( Environment.screenWidth == 800 ) strcat( path, "mcui_med5.tga" ); else if ( Environment.screenWidth == 640 ) strcat( path, "mcui_low5.tga" ); else strcat( path, "mcui_high8.tga" ); setIconVariables(); if ( NO_ERR != file.open( path ) ) { Assert( 0, 0, "Couldn't open the vehicle parts" ); return false; } int size = file.getLength(); s_VehicleTextures = (TGAFileHeader*)new char[size]; file.read( (BYTE*)s_VehicleTextures, size ); BYTE* pTmp = (BYTE*)(s_VehicleTextures + 1); flipTopToBottom (pTmp, s_VehicleTextures->pixel_depth, s_VehicleTextures->width, s_VehicleTextures->height ); } pilotIcon.setTextureIndex( 26 ); if ( !pMover ) return 0; gosASSERT( unitIconX * 4 < ICON_REALSIZE && unitIconY * 4 < ICON_REALSIZE ); int pixelDepth = s_VehicleTextures->pixel_depth/8; if ( pixelDepth != 4 ) PAUSE(("Texture for VehicleIcon not 32-bit")); // now need to make a copy of the data // now need to make a copy of the data long texIndex = 0; int iconsPerLine = ((int)s_textureMemory->width/(int)unitIconX); int iconsPerPage = ((int)s_textureMemory->width/(int)unitIconY); long row = damageIconIndex/iconsPerLine; long column = (damageIconIndex % iconsPerLine); if ( row >= iconsPerPage ) { texIndex = row/iconsPerPage; row = row % iconsPerPage; } long offsetX = column * unitIconX; long offsetY = row * unitIconY; if ( s_textureHandle[texIndex] == -1 ) { long size = ( 256 * 256 * sizeof( long ) + sizeof( TGAFileHeader ) ); s_textureHandle[texIndex] = gos_NewTextureFromMemory( gos_Texture_Alpha, ".tga", (unsigned char*)s_textureMemory, size, 0 ); } TEXTUREPTR textureData; gos_LockTexture( s_textureHandle[texIndex], 0, 0, &textureData ); unsigned long* pDestData, *pDestRow = textureData.pTexture + offsetY * textureData.Width + offsetX; char* pTmp = (char*)s_VehicleTextures + sizeof ( TGAFileHeader ); unsigned long* pSrcRow = (unsigned long*)pTmp; long whichMech = pMover->getIconPictureIndex(); offsetY = 0; offsetX = whichMech * unitIconX; long tmpOffset = ((s_VehicleTextures->width) * (offsetY ) + offsetX); pSrcRow += tmpOffset; unsigned long* pSrcData = pSrcRow; for( int j = 0; j < unitIconY; ++j ) { pDestData = pDestRow; pSrcData = pSrcRow; for ( int i = 0; i < unitIconX; ++i ) // do four icons per row { *pDestData++ = *pSrcData++; } pSrcRow += s_VehicleTextures->width; pDestRow += textureData.Width; } gos_UnLockTexture( s_textureHandle[texIndex] ); unit = pMover; for ( int i = 0; i < 5; ++i ) { bmpLocation[locationIndex][i].argb = 0xffffffff; bmpLocation[locationIndex][i].frgb = 0; bmpLocation[locationIndex][i].rhw = .5; bmpLocation[locationIndex][i].u = 0.; bmpLocation[locationIndex][i].v = 0.; bmpLocation[locationIndex][i].z = 0.; } memset( damage, 0, 5 ); return true; } void VehicleIcon::update() { char newDamage[5]; memset( newDamage, 0, 5 ); // do check against armor location ArmorLocation armor = unit->armor[GROUNDVEHICLE_LOCATION_FRONT]; float tmp = armor.curArmor/(float)armor.maxArmor; if ( tmp < .1 ) newDamage[0] = 3; else if ( tmp < .3 ) newDamage[0] = 2; else if ( tmp < .6 ) newDamage[0] = 1; tmp = unit->armor[GROUNDVEHICLE_LOCATION_REAR].curArmor/(float)unit->armor[GROUNDVEHICLE_LOCATION_REAR].maxArmor; if ( tmp < .1 ) newDamage[1] = 3; else if ( tmp < .3 ) newDamage[1] = 2; else if ( tmp < .6 ) newDamage[1] = 1; tmp = unit->armor[GROUNDVEHICLE_LOCATION_LEFT].curArmor/(float)unit->armor[GROUNDVEHICLE_LOCATION_LEFT].maxArmor; if ( tmp < .1 ) newDamage[2] = 3; else if ( tmp < .3 ) newDamage[2] = 2; else if ( tmp < .6 ) newDamage[2] = 1; tmp = unit->armor[GROUNDVEHICLE_LOCATION_RIGHT].curArmor/(float)unit->armor[GROUNDVEHICLE_LOCATION_RIGHT].maxArmor; if ( tmp < .1 ) newDamage[3] = 3; else if ( tmp < .3 ) newDamage[3] = 2; else if ( tmp < .6 ) newDamage[3] = 1; armor = unit->armor[GROUNDVEHICLE_LOCATION_TURRET]; tmp = armor.curArmor/(float)armor.maxArmor; if ( tmp < .1 ) newDamage[4] = 3; else if ( tmp < .3 ) newDamage[4] = 2; else if ( tmp < .6 ) newDamage[4] = 1; for ( int i = 0; i < 5; ++i ) { if ( newDamage[i] != damage[i] ) { long texIndex = 0; int iconsPerLine = ((int)s_textureMemory->width/(int)unitIconX); int iconsPerPage = ((int)s_textureMemory->width/(int)unitIconY); int yIndex = damageIconIndex / iconsPerLine; int xIndex = damageIconIndex % iconsPerLine; if ( yIndex >= iconsPerPage ) { texIndex = yIndex/iconsPerPage; yIndex = yIndex % iconsPerPage; } TEXTUREPTR textureData; gos_LockTexture( s_textureHandle[texIndex], 0, 0, &textureData ); unsigned long* pData = textureData.pTexture; // go to write spot in texture int jLine = yIndex * unitIconY; int iLine = xIndex * unitIconX; unsigned long* pLine = (unsigned long*)(pData + (jLine * textureData.Width) + iLine); unsigned long* pChange = pLine; unsigned long oldColors[3]; unsigned long newColors[3]; for ( int p = 0; p < 3; p++ ) { int tmp = damageColors[damage[i]][p]; int redVal = (tmp >> 16) & 0x000000ff; redVal += i; oldColors[p] = ( tmp & 0xff00ffff ) | (redVal << 16); tmp = damageColors[newDamage[i]][p]; redVal = (tmp >> 16) & 0x000000ff; redVal += i; newColors[p] = ( tmp & 0xff00ffff ) | (redVal << 16); } for ( int k = 0; k < unitIconY; ++k ) { pChange = pLine; for ( int j = 0; j < unitIconX; ++j ) { if ( (*pChange)&0xff000000 ) // not transparent { for ( int p = 0; p < 3; p++ ) { if ( oldColors[p] == *pChange ) { *pChange = newColors[p]; } } } pChange++; } pLine += textureData.Width; } gos_UnLockTexture( s_textureHandle[texIndex] ); } damage[i] = newDamage[i]; } } void ForceGroupIcon::drawBar( float barStatus ) { DWORD color = SB_GREEN; float barLength = (healthBar[locationIndex].right - healthBar[locationIndex].left) * barStatus; /*if (barStatus >= 0.5) color = SB_GREEN; else if (barStatus > 0.2) color = SB_YELLOW; else color = SB_RED;*/ GUI_RECT rect = { healthBar[locationIndex].left, healthBar[locationIndex].top,healthBar[locationIndex].left + barLength, healthBar[locationIndex].bottom }; drawRect( rect, color ); drawEmptyRect( healthBar[locationIndex], color, color & 0x7f7f7f ); } int ForceGroupIcon::sort( const void* p1, const void* p2 ) { ForceGroupIcon* m1 = *(ForceGroupIcon**)p1; ForceGroupIcon* m2 = *(ForceGroupIcon**)p2; bool bv1 = dynamic_cast(m1) ? 1 : 0; bool bv2 = dynamic_cast(m2) ? 1 : 0; for ( int i = 1; i < 10; ++i ) { bool bM1 = m1->unit->isInUnitGroup( i == 10 ? 0 : i ); bool bM2 = m2->unit->isInUnitGroup( i == 10 ? 0 : i ); if ( bM1 && !bM2 ) return -1; if ( bM2 && !bM1 ) return 1; if ( bM2 && bM1 ) // if same force group, use weight { break; } } if ( bv2 && !bv1 ) return -1; else if ( bv1 && !bv2 ) return 1; int w1 = m1->unit->getTonnage(); int w2 = m2->unit->getTonnage(); if ( w1 < w2 ) return -1; else if ( w2 < w1) return 1; // OK these are exactly the same, compare pilot names int retVal = ( strcmp( m1->getPilotName(), m2->getPilotName() ) ); if ( retVal == 0 ) return m1 < m2; return retVal; } const char* ForceGroupIcon::getPilotName() { return unit->getPilot()->getName(); } void ForceGroupIcon::setLocationIndex( int i ) { locationIndex = i; } void ForceGroupIcon::drawDeathEffect() { unit->setSelected( 0 ); bool bFinished = true; deathAnimationTime += frameLength; for ( int i = 0; i < NUM_DEATH_INFOS - 1; i++ ) { if ( animationInfos[i].time < deathAnimationTime && animationInfos[i+1].time > deathAnimationTime ) { float totalTime = animationInfos[i+1].time - animationInfos[i].time; float currentTime = deathAnimationTime - animationInfos[i].time; float percent = currentTime/totalTime; // since I know we're going from white to black, I'm only going to much with the alpha separately long alphaMin = (animationInfos[i].color >> 24) & 0xff; long alphaMax = (animationInfos[i+1].color >> 24)& 0xff; long newAlpha = (float)alphaMin + ((float)(alphaMax - alphaMin))*percent; long redMin = (animationInfos[i].color & 0x00ff0000)>>16; long redMax = (animationInfos[i+1].color & 0x00ff0000)>>16; long newRed = (float)redMin + ((float)(redMax - redMin))*percent; long greenMin = (animationInfos[i].color & 0x0000ff00)>>8; long greenMax = (animationInfos[i+1].color & 0x0000ff00)>>8; long newGreen = (float)greenMin + ((float)(greenMax - greenMin))*percent; long blueMin = animationInfos[i].color & 0x000000ff; long blueMax = animationInfos[i+1].color & 0x000000ff; long newBlue = (float)blueMin + ((float)(blueMax - blueMin))*percent; long newColor = newBlue + (newGreen << 8) + (newRed << 16) + (newAlpha <<24); drawRect( selectionRect[locationIndex], newColor ); bFinished = false; if ( i == 0 ) { long color = 0xff000000; if ( deathAnimationTime < .4 || (deathAnimationTime > .8 && deathAnimationTime < 1.2) || deathAnimationTime > 1.6 && deathAnimationTime < 2.0) { color = 0xffff0000; } drawEmptyRect( selectionRect[locationIndex], color, color ); } } } if ( bFinished ) { drawRect( selectionRect[locationIndex], animationInfos[i].color ); unit->addToUnitGroup( -1 ); //------------------------------------------------------------ // This tells all machines to drop this mover from the team... if (MPlayer) MPlayer->sendReinforcement(0, unit->netRosterIndex, "noname", 0, unit->getPosition(), 7); } } void ForceGroupIcon::setIconVariables() { switch( Environment.screenWidth ) { case 800: PilotIcon::pilotIconX = 25; PilotIcon::pilotIconY = 36; unitIconX = 32; unitIconY = 38; break; case 640: PilotIcon::pilotIconX = 20; PilotIcon::pilotIconY = 28; unitIconX = 25; unitIconY = 30; break; default: PilotIcon::pilotIconX = 33; PilotIcon::pilotIconY = 46; unitIconX = 40; unitIconY = 48; break; } curScreenWidth = Environment.screenWidth; } PilotIcon::PilotIcon() { pilotTextureIndex = 0; if ( !s_pilotTextureHandle ) { // find proper file based on resolution char path[256]; strcpy( path, "data\\art\\"); if ( Environment.screenWidth == 640 ) { strcat( path, "mcui_low2.tga" ); } else if ( Environment.screenWidth == 800 ) { strcat( path, "mcui_med2.tga" ); } else { strcat( path, "mcui_high2.tga" ); } s_pilotTextureHandle = mcTextureManager->loadTexture( path, gos_Texture_Alpha, 0, 0, 0x2); // find its width and store it for future reference. int gosID = mcTextureManager->get_gosTextureHandle( s_pilotTextureHandle ); TEXTUREPTR textureData; gos_LockTexture( gosID, 0, 0, &textureData ); s_pilotTextureWidth = textureData.Width; gos_UnLockTexture( gosID ); } } void PilotIcon::render( float left, float top, float right, float bottom ) { gos_VERTEX pilotLocation[5]; for ( int i = 0; i < 5; i++ ) { pilotLocation[i].argb = 0xffffffff; pilotLocation[i].rhw = .5; pilotLocation[i].frgb = 0; pilotLocation[i].z = 0; } pilotLocation[0].x = pilotLocation[1].x = left; pilotLocation[3].x = pilotLocation[2].x = right; pilotLocation[0].y = pilotLocation[3].y = top; pilotLocation[1].y = pilotLocation[2].y = bottom; pilotLocation[4] = pilotLocation[0]; int iconsPerRow = s_pilotTextureWidth / pilotIconX; int xIndex = pilotTextureIndex % iconsPerRow; int yIndex = pilotTextureIndex / iconsPerRow; float xLocation = xIndex * pilotIconX; float yLocation = yIndex * pilotIconY; pilotLocation[0].u = pilotLocation[1].u = xLocation/s_pilotTextureWidth + (.1f/s_pilotTextureWidth); pilotLocation[3].u = pilotLocation[2].u = (xLocation + pilotIconX)/s_pilotTextureWidth+ (.1f/s_pilotTextureWidth); pilotLocation[0].v = pilotLocation[3].v = yLocation/s_pilotTextureWidth+ (.1f/s_pilotTextureWidth); pilotLocation[1].v = pilotLocation[2].v = (yLocation + pilotIconY)/s_pilotTextureWidth+ (.1f/s_pilotTextureWidth); pilotLocation[4] = pilotLocation[0]; int gosID = mcTextureManager->get_gosTextureHandle( s_pilotTextureHandle ); gos_SetRenderState( gos_State_Texture, gosID ); // here I need to draw the pilot icon gos_DrawTriangles( pilotLocation, 3 ); gos_DrawTriangles( &pilotLocation[2], 3 ); } void PilotIcon::setPilot( MechWarrior* pWarrior ) { if ( pWarrior ) pilotTextureIndex = pWarrior->getPhoto(); } void PilotIcon::swapResolutions( bool bForce) { if ( s_pilotTextureHandle ) { int gosID = mcTextureManager->get_gosTextureHandle( s_pilotTextureHandle ); mcTextureManager->removeTexture( gosID ); } s_pilotTextureHandle = 0; if ( !s_pilotTextureHandle ) { // find proper file based on resolution char path[256]; strcpy( path, "data\\art\\"); if ( Environment.screenWidth == 640 ) { strcat( path, "mcui_low2.tga" ); } else if ( Environment.screenWidth == 800 ) { strcat( path, "mcui_med2.tga" ); } else { strcat( path, "mcui_high2.tga" ); } s_pilotTextureHandle = mcTextureManager->loadTexture( path, gos_Texture_Alpha, 0, 0, 0x2); // find its width and store it for future reference. int gosID = mcTextureManager->get_gosTextureHandle( s_pilotTextureHandle ); TEXTUREPTR textureData; gos_LockTexture( gosID, 0, 0, &textureData ); s_pilotTextureWidth = textureData.Width; gos_UnLockTexture( gosID ); } } //************************************************************************************************* // end of file ( MechIcon.cpp )