diff --git a/GameSettings.cpp b/GameSettings.cpp index faa38f71..6009c0ee 100644 --- a/GameSettings.cpp +++ b/GameSettings.cpp @@ -264,6 +264,7 @@ BOOLEAN LoadGameSettings() gGameSettings.fOptions[TOPTION_STAT_PROGRESS_BARS] = iniReader.ReadBoolean("JA2 Game Settings","TOPTION_STAT_PROGRESS_BARS" , TRUE ); // HEADROCK HAM 3.6: Progress Bars gGameSettings.fOptions[TOPTION_MERCENARY_FORMATIONS] = iniReader.ReadBoolean("JA2 Game Settings","TOPTION_MERCENARY_FORMATIONS" , TRUE ); // Flugente: mercenary formations gGameSettings.fOptions[TOPTION_REPORT_MISS_MARGIN] = iniReader.ReadBoolean("JA2 Game Settings","TOPTION_REPORT_MISS_MARGIN" , FALSE ); // HEADROCK HAM 4: Shot offset report + gGameSettings.fOptions[TOPTION_USE_LOGICAL_BODYTYPES] = iniReader.ReadBoolean("JA2 Game Settings","TOPTION_USE_LOGICAL_BODYTYPES" , FALSE ); gGameSettings.fOptions[TOPTION_ALT_MAP_COLOR] = iniReader.ReadBoolean("JA2 Game Settings","TOPTION_ALT_MAP_COLOR" , FALSE ); // HEADROCK HAM 4: Strategic Map Colors gGameSettings.fOptions[TOPTION_ALTERNATE_BULLET_GRAPHICS] = iniReader.ReadBoolean("JA2 Game Settings","TOPTION_ALTERNATE_BULLET_GRAPHICS" , TRUE ); gGameSettings.fOptions[TOPTION_SHOW_MERC_RANKS] = iniReader.ReadBoolean("JA2 Game Settings","TOPTION_SHOW_MERC_RANKS" , FALSE ); @@ -477,6 +478,7 @@ BOOLEAN SaveGameSettings() settings << "TOPTION_CHEAT_MODE_OPTIONS_END = " << (gGameSettings.fOptions[TOPTION_CHEAT_MODE_OPTIONS_END] ? "TRUE" : "FALSE" ) << endl; settings << "TOPTION_DEBUG_MODE_OPTIONS_HEADER = " << (gGameSettings.fOptions[TOPTION_DEBUG_MODE_OPTIONS_HEADER] ? "TRUE" : "FALSE" ) << endl; settings << "TOPTION_REPORT_MISS_MARGIN = " << (gGameSettings.fOptions[TOPTION_REPORT_MISS_MARGIN] ? "TRUE" : "FALSE" ) << endl; // HEADROCK HAM 4: Shot offset report + settings << "TOPTION_USE_LOGICAL_BODYTYPES = " << (gGameSettings.fOptions[TOPTION_USE_LOGICAL_BODYTYPES] ? "TRUE" : "FALSE" ) << endl; // BIO settings << "TOPTION_SHOW_RESET_ALL_OPTIONS = " << (gGameSettings.fOptions[TOPTION_SHOW_RESET_ALL_OPTIONS] ? "TRUE" : "FALSE" ) << endl; settings << "TOPTION_RESET_ALL_OPTIONS = " << (gGameSettings.fOptions[TOPTION_RESET_ALL_OPTIONS] ? "TRUE" : "FALSE" ) << endl; settings << "TOPTION_RETAIN_DEBUG_OPTIONS_IN_RELEASE = " << (gGameSettings.fOptions[TOPTION_RETAIN_DEBUG_OPTIONS_IN_RELEASE] ? "TRUE" : "FALSE" ) << endl; @@ -591,6 +593,9 @@ void InitGameSettings() gGameSettings.fOptions[ TOPTION_REPORT_MISS_MARGIN ] = FALSE; + // BIO + gGameSettings.fOptions[ TOPTION_USE_LOGICAL_BODYTYPES ] = FALSE; + gGameSettings.fOptions[ TOPTION_DISABLE_CURSOR_SWAP ] = FALSE; gGameSettings.fOptions[ TOPTION_QUIET_TRAINING ] = FALSE; gGameSettings.fOptions[ TOPTION_QUIET_REPAIRING ] = FALSE; diff --git a/GameSettings.h b/GameSettings.h index 0b168714..d8e01598 100644 --- a/GameSettings.h +++ b/GameSettings.h @@ -75,6 +75,9 @@ enum // WANNE: Moved alternate bullets graphics (tracers) to options TOPTION_ALTERNATE_BULLET_GRAPHICS, + // BIO LOBOT: + TOPTION_USE_LOGICAL_BODYTYPES, + // CHRISL: HAM 4: Activate/Deactivate NCTH mode //TOPTION_USE_NCTH, //Jenilee's Merc Ranks diff --git a/Init.cpp b/Init.cpp index 7a904fd1..857a6459 100644 --- a/Init.cpp +++ b/Init.cpp @@ -438,6 +438,14 @@ BOOLEAN LoadExternalGameplayData(STR directoryName) strcpy(fileName, directoryName); strcat(fileName, LBEPOCKETFILENAME); SGP_THROW_IFFALSE(ReadInLBEPocketStats(fileName,FALSE),LBEPOCKETFILENAME); + { + using namespace LogicalBodyTypes; + SGP_THROW_IFFALSE(Layers::Instance().LoadFromFile(directoryName, LBT_LAYERSFILENAME), LBT_LAYERSFILENAME); + SGP_THROW_IFFALSE(PaletteDB::Instance().LoadFromFile(directoryName, LBT_PALETTESFILENAME), LBT_PALETTESFILENAME); + SGP_THROW_IFFALSE(SurfaceDB::Instance().LoadFromFile(directoryName, LBT_ANIMSURFACESFILENAME), LBT_ANIMSURFACESFILENAME); + SGP_THROW_IFFALSE(FilterDB::Instance().LoadFromFile(directoryName, LBT_FILTERSFILENAME), LBT_FILTERSFILENAME); + SGP_THROW_IFFALSE(BodyTypeDB::Instance().LoadFromFile(directoryName, LBT_BODYTYPESFILENAME), LBT_BODYTYPESFILENAME); + } #ifndef ENGLISH AddLanguagePrefix(fileName); @@ -1396,7 +1404,7 @@ BackupBRandEncyclopedia ( gBriefingRoomData, gBriefingRoomDataBackup, 0); MusicSoundValues[iloop].SoundTacticalBattleGroup[iloop] = -1; } } - + CHAR8 zFileName[255]; sprintf( zFileName, "scripts\\Music.lua" ); if (FileExists( zFileName ) ) @@ -1404,12 +1412,12 @@ BackupBRandEncyclopedia ( gBriefingRoomData, gBriefingRoomDataBackup, 0); LetLuaMusicControl(0); } #endif - + strcpy(fileName, directoryName); strcat(fileName, DIFFICULTYFILENAME); DebugMsg (TOPIC_JA2,DBG_LEVEL_3,String("LoadExternalGameplayData, fileName = %s", fileName)); SGP_THROW_IFFALSE(ReadInDifficultySettings(fileName,FALSE), DIFFICULTYFILENAME); - + #ifndef ENGLISH AddLanguagePrefix(fileName); if ( FileExists(fileName) ) @@ -1417,8 +1425,8 @@ BackupBRandEncyclopedia ( gBriefingRoomData, gBriefingRoomDataBackup, 0); DebugMsg (TOPIC_JA2,DBG_LEVEL_3,String("LoadExternalGameplayData, fileName = %s", fileName)); SGP_THROW_IFFALSE(ReadInDifficultySettings(fileName,TRUE), fileName); } - #endif - + #endif + LuaState::INIT(lua::LUA_STATE_STRATEGIC_MINES_AND_UNDERGROUND, true); g_luaUnderground.LoadScript(GetLanguagePrefix()); // load Lua for Strategic Mines initialization @@ -1438,7 +1446,7 @@ UINT32 InitializeJA2(void) HandleJA2CDCheck( ); gfWorldLoaded = FALSE; - + //Load external game mechanic data //if ( !LoadExternalGameplayData(TABLEDATA_DIRECTORY)) //{ @@ -1455,7 +1463,7 @@ UINT32 InitializeJA2(void) //dnl ch54 111009 //gsRenderCenterX = 805; //gsRenderCenterY = 805; - + // Init data InitializeSystemVideoObjects( ); @@ -1530,7 +1538,7 @@ UINT32 InitializeJA2(void) //ADB When a merc calcs CTGT for a thrown item he uses a GLOCK temp item //but we don't want to recreate it every single time CTGT is called, so init the GLOCK here //CreateItem(GLOCK_17, 100, &GLOCK_17_ForUseWithLOS);//dnl ch86 120214 move to LOS.cpp - + #ifdef JA2BETAVERSION #ifdef JA2EDITOR @@ -1573,7 +1581,7 @@ UINT32 InitializeJA2(void) #ifdef JA2BETAVERSION #ifdef JA2EDITOR - + // CHECK COMMANDLINE FOR SPECIAL UTILITY if( !strcmp( gzCommandLine, "-EDITORAUTO" ) ) { diff --git a/Init.h b/Init.h index 5553378b..5ead7790 100644 --- a/Init.h +++ b/Init.h @@ -1,6 +1,20 @@ #ifndef _INIT_H #define _INIT_H +#ifndef PRECOMPILEDHEADERS +#include "LogicalBodyTypes/BodyTypeDB.h" +#include "LogicalBodyTypes/Layers.h" +#include "LogicalBodyTypes/AbstractXMLLoader.h" +#include "LogicalBodyTypes/SurfaceDB.h" +#include "LogicalBodyTypes/FilterDB.h" +#include "LogicalBodyTypes/EnumeratorDB.h" +#include "LogicalBodyTypes/BodyTypeDB.h" +#include "LogicalBodyTypes/PaletteDB.h" +#endif + +#include +#include + UINT32 InitializeJA2( ); void ShutdownJA2( ); diff --git a/JA2 All.h b/JA2 All.h index 768f5b78..8b94935e 100644 --- a/JA2 All.h +++ b/JA2 All.h @@ -5,10 +5,10 @@ #include "builddefines.h" -#include +#include #include #include -#include "sgp.h" +#include "sgp.h" #include "gameloop.h" #include "himage.h" #include "vobject.h" @@ -108,7 +108,7 @@ #include "tile cache.h" #include "Shade Table Util.h" #include "Exit Grids.h" -#include "Summary Info.h" +#include "Summary Info.h" #include #include "font.h" #include "timer.h" @@ -160,5 +160,13 @@ #include "Scheduling.h" #include "_JA25EnglishText.h" #include "XML.h" +#include "LogicalBodyTypes/BodyTypeDB.h" +#include "LogicalBodyTypes/Layers.h" +#include "LogicalBodyTypes/AbstractXMLLoader.h" +#include "LogicalBodyTypes/PaletteDB.h" +#include "LogicalBodyTypes/SurfaceDB.h" +#include "LogicalBodyTypes/FilterDB.h" +#include "LogicalBodyTypes/EnumeratorDB.h" +#include "LogicalBodyTypes/BodyTypeDB.h" #endif diff --git a/Standard Gaming Platform/vobject_blitters.cpp b/Standard Gaming Platform/vobject_blitters.cpp index 23ea2674..7e317eb5 100644 --- a/Standard Gaming Platform/vobject_blitters.cpp +++ b/Standard Gaming Platform/vobject_blitters.cpp @@ -25,6 +25,107 @@ std::map g_SurfaceRectangle; static UINT8 g_AlphaTimesValueCache[256][256]; +static const unsigned short maxChar = 0xff; +unsigned short blendWithAlpha(unsigned int rgb565New, unsigned int rgb565Old, unsigned int alpha) +{ + unsigned short value = 0; + float alphaF; + unsigned short oldR, oldG, oldB, newR, newG, newB, outR, outG, outB; + unsigned short alphaC = (unsigned short)alpha; + __asm { + xor ebx, ebx + xor ecx, ecx + mov ecx, rgb565Old + xor eax, eax + xor edx, edx + mov ax, cx + shr ax, 11 + xor ah, ah + mov oldR, ax + xor edx, edx + mov ax, cx + and ax, 0x7e0 + shr ax, 5 + xor ah, ah + mov oldG, ax + xor edx, edx + mov ax, cx + and ax, 0x1f + xor ah, ah + mov oldB, ax + xor ebx, ebx + xor ecx, ecx + mov ecx, rgb565New + xor eax, eax + xor edx, edx + mov ax, cx + shr ax, 11 + xor ah, ah + mov newR, ax + xor edx, edx + mov ax, cx + and ax, 0x7e0 + shr ax, 5 + xor ah, ah + mov newG, ax + xor edx, edx + mov ax, cx + and ax, 0x1f + xor ah, ah + mov newB, ax + fld1 + fild alphaC + fild maxChar + fdiv + fst alphaF + fsub + fild oldR + fmul + fild newR + fld alphaF + fmul + fadd + fistp outR + fld1 + fild alphaC + fild maxChar + fdiv + fst alphaF + fsub + fild oldG + fmul + fild newG + fld alphaF + fmul + fadd + fistp outG + fld1 + fild alphaC + fild maxChar + fdiv + fst alphaF + fsub + fild oldB + fmul + fild newB + fld alphaF + fmul + fadd + fistp outB + xor eax, eax + xor ebx, ebx + mov ax, outB + mov bx, outG + shl bx, 5 + add eax, ebx + mov bx, outR + shl bx, 11 + add eax, ebx + mov value, ax + } + return value; +} + class InitAlphaTimesValueCache { public: @@ -8723,7 +8824,7 @@ BlitDone: The Z-buffer is 16 bit, and must be the same dimensions (including Pitch) as the destination. **********************************************************************************************/ -BOOLEAN Blt8BPPDataTo16BPPBufferTransShadow( UINT16 *pBuffer, UINT32 uiDestPitchBYTES, HVOBJECT hSrcVObject, INT32 iX, INT32 iY, UINT16 usIndex, UINT16 *p16BPPPalette ) +BOOLEAN Blt8BPPDataTo16BPPBufferTransShadow(UINT16 *pBuffer, UINT32 uiDestPitchBYTES, HVOBJECT hSrcVObject, INT32 iX, INT32 iY, UINT16 usIndex, UINT16 *p16BPPPalette, BOOLEAN fIgnoreShadows) { UINT32 uiOffset; UINT32 usHeight, usWidth; @@ -8781,6 +8882,10 @@ BlitNTL4: cmp al, 254 jne BlitNTL6 + mov al, fIgnoreShadows + cmp al, 0 + jne BlitNTL5 + mov ax, [edi] mov ax, ShadeTable[eax*2] mov [edi], ax @@ -8824,6 +8929,156 @@ BlitDone: } +/********************************************************************************************** + Blt8BPPDataTo16BPPBufferTransShadow + + Blits an image into the destination buffer, using an ETRLE brush as a source, and a 16-bit + buffer as a destination. As it is blitting, it checks the Z value of the ZBuffer, and if the + pixel's Z level is below that of the current pixel, it is written on, and the Z value is + updated to the current value, for any non-transparent pixels. If the source pixel is 254, + it is considered a shadow, and the destination buffer is darkened rather than blitted on. + The Z-buffer is 16 bit, and must be the same dimensions (including Pitch) as the destination. + +**********************************************************************************************/ +BOOLEAN Blt8BPPDataTo16BPPBufferTransShadowAlpha(UINT16 *pBuffer, UINT32 uiDestPitchBYTES, HVOBJECT hSrcVObject, HVOBJECT hAlphaVObject, INT32 iX, INT32 iY, UINT16 usIndex, UINT16 *p16BPPPalette, BOOLEAN fIgnoreShadows) +{ + UINT32 uiOffset; + UINT32 usHeight, usWidth; + UINT8 *SrcPtr, *DestPtr, *AlphaPtr; + UINT32 LineSkip; + ETRLEObject *pTrav; + INT32 iTempX, iTempY; + + + // Assertions + Assert(hSrcVObject != NULL); + Assert(hAlphaVObject != NULL); + Assert(pBuffer != NULL); + + // Get Offsets from Index into structure + pTrav = &(hSrcVObject->pETRLEObject[usIndex]); + usHeight = (UINT32)pTrav->usHeight; + usWidth = (UINT32)pTrav->usWidth; + uiOffset = pTrav->uiDataOffset; + + // Add to start position of dest buffer + iTempX = iX + pTrav->sOffsetX; + iTempY = iY + pTrav->sOffsetY; + + // Validations + CHECKF(iTempX >= 0); + CHECKF(iTempY >= 0); + + + SrcPtr = (UINT8 *)hSrcVObject->pPixData + uiOffset; + AlphaPtr = (UINT8 *)hAlphaVObject->pPixData + (hAlphaVObject->pETRLEObject[usIndex]).uiDataOffset; + DestPtr = (UINT8 *)pBuffer + (uiDestPitchBYTES*iTempY) + (iTempX * 2); + LineSkip = (uiDestPitchBYTES - (usWidth * 2)); + + __asm { + + mov esi, SrcPtr + mov edi, DestPtr + mov edx, p16BPPPalette + xor eax, eax + xor ecx, ecx + + BlitDispatch : + + mov cl, [esi] + inc esi + + push esi + mov esi, AlphaPtr + inc esi + mov AlphaPtr, esi + pop esi + + or cl, cl + js BlitTransparent + jz BlitDoneLine + + //BlitNonTransLoop: + + BlitNTL4 : + + xor eax, eax + mov al, [esi] + cmp al, 254 + jne BlitNTL6 + + mov al, fIgnoreShadows + cmp al, 0 + jne BlitNTL5 + + mov ax, [edi] + mov ax, ShadeTable[eax * 2] + mov[edi], ax + jmp BlitNTL5 + + + BlitNTL6 : + mov ax, [edx + eax * 2] + + push edx + push ecx + push ebx + push esi + mov esi, AlphaPtr + xor ebx, ebx + mov bl, [esi] + pop esi + push ebx + push[edi] + push eax + call blendWithAlpha + add esp, 12 + pop ebx + pop ecx + pop edx + + mov[edi], ax + + BlitNTL5 : + inc esi + + push esi + mov esi, AlphaPtr + inc esi + mov AlphaPtr, esi + pop esi + + add edi, 2 + dec cl + jnz BlitNTL4 + + jmp BlitDispatch + + + BlitTransparent : + + and ecx, 07fH + // shl ecx, 1 + add ecx, ecx + add edi, ecx + jmp BlitDispatch + + + BlitDoneLine : + + dec usHeight + jz BlitDone + add edi, LineSkip + jmp BlitDispatch + + + BlitDone : + } + + return(TRUE); + +} + /********************************************************************************************** Blt8BPPDataTo16BPPBufferTransShadowZ @@ -8835,7 +9090,166 @@ BlitDone: The Z-buffer is 16 bit, and must be the same dimensions (including Pitch) as the destination. **********************************************************************************************/ -BOOLEAN Blt8BPPDataTo16BPPBufferTransShadowZ( UINT16 *pBuffer, UINT32 uiDestPitchBYTES, UINT16 *pZBuffer, UINT16 usZValue, HVOBJECT hSrcVObject, INT32 iX, INT32 iY, UINT16 usIndex, UINT16 *p16BPPPalette ) +BOOLEAN Blt8BPPDataTo16BPPBufferTransShadowZAlpha(UINT16 *pBuffer, UINT32 uiDestPitchBYTES, UINT16 *pZBuffer, UINT16 usZValue, HVOBJECT hSrcVObject, HVOBJECT hAlphaVObject, INT32 iX, INT32 iY, UINT16 usIndex, UINT16 *p16BPPPalette, BOOLEAN fIgnoreShadows) +{ + UINT32 uiOffset; + UINT32 usHeight, usWidth; + UINT8 *SrcPtr, *DestPtr, *ZPtr, *AlphaPtr; + UINT32 LineSkip; + ETRLEObject *pTrav; + INT32 iTempX, iTempY; + + + // Assertions + Assert(hSrcVObject != NULL); + Assert(hAlphaVObject != NULL); + Assert(pBuffer != NULL); + + // Get Offsets from Index into structure + pTrav = &(hSrcVObject->pETRLEObject[usIndex]); + usHeight = (UINT32)pTrav->usHeight; + usWidth = (UINT32)pTrav->usWidth; + uiOffset = pTrav->uiDataOffset; + + // Add to start position of dest buffer + iTempX = iX + pTrav->sOffsetX; + iTempY = iY + pTrav->sOffsetY; + + // Validations + CHECKF(iTempX >= 0); + CHECKF(iTempY >= 0); + + + SrcPtr = (UINT8 *)hSrcVObject->pPixData + uiOffset; + AlphaPtr = (UINT8 *)hAlphaVObject->pPixData + (hAlphaVObject->pETRLEObject[usIndex]).uiDataOffset; + DestPtr = (UINT8 *)pBuffer + (uiDestPitchBYTES*iTempY) + (iTempX * 2); + ZPtr = (UINT8 *)pZBuffer + (uiDestPitchBYTES*iTempY) + (iTempX * 2); + LineSkip = (uiDestPitchBYTES - (usWidth * 2)); + + __asm { + + mov esi, SrcPtr + mov edi, DestPtr + mov edx, p16BPPPalette + xor eax, eax + mov ebx, ZPtr + xor ecx, ecx + + BlitDispatch : + + mov cl, [esi] + inc esi + push esi + mov esi, AlphaPtr + inc esi + mov AlphaPtr, esi + pop esi + or cl, cl + js BlitTransparent + jz BlitDoneLine + + //BlitNonTransLoop: + + BlitNTL4 : + + mov ax, [ebx] + cmp ax, usZValue + jae BlitNTL5 + + mov ax, usZValue + mov[ebx], ax + + xor eax, eax + mov al, [esi] + cmp al, 254 + jne BlitNTL6 + + mov al, fIgnoreShadows + cmp al, 0 + jne BlitNTL5 + + mov ax, [edi] + mov ax, ShadeTable[eax * 2] + mov[edi], ax + jmp BlitNTL5 + + + BlitNTL6 : + mov ax, [edx + eax * 2] + + push edx + push ecx + push ebx + push esi + mov esi, AlphaPtr + xor ebx, ebx + mov bl, [esi] + pop esi + push ebx + push[edi] + push eax + call blendWithAlpha + add esp, 12 + pop ebx + pop ecx + pop edx + + mov[edi], ax + + BlitNTL5 : + inc esi + push esi + mov esi, AlphaPtr + inc esi + mov AlphaPtr, esi + pop esi + add edi, 2 + add ebx, 2 + dec cl + jnz BlitNTL4 + + jmp BlitDispatch + + + BlitTransparent : + + and ecx, 07fH + // shl ecx, 1 + add ecx, ecx + add edi, ecx + add ebx, ecx + jmp BlitDispatch + + + BlitDoneLine : + + dec usHeight + jz BlitDone + add edi, LineSkip + add ebx, LineSkip + jmp BlitDispatch + + + BlitDone : + } + + return(TRUE); + +} + + +/********************************************************************************************** + Blt8BPPDataTo16BPPBufferTransShadowZ + + Blits an image into the destination buffer, using an ETRLE brush as a source, and a 16-bit + buffer as a destination. As it is blitting, it checks the Z value of the ZBuffer, and if the + pixel's Z level is below that of the current pixel, it is written on, and the Z value is + updated to the current value, for any non-transparent pixels. If the source pixel is 254, + it is considered a shadow, and the destination buffer is darkened rather than blitted on. + The Z-buffer is 16 bit, and must be the same dimensions (including Pitch) as the destination. + +**********************************************************************************************/ +BOOLEAN Blt8BPPDataTo16BPPBufferTransShadowZ(UINT16 *pBuffer, UINT32 uiDestPitchBYTES, UINT16 *pZBuffer, UINT16 usZValue, HVOBJECT hSrcVObject, INT32 iX, INT32 iY, UINT16 usIndex, UINT16 *p16BPPPalette, BOOLEAN fIgnoreShadows) { UINT32 uiOffset; UINT32 usHeight, usWidth; @@ -8902,7 +9316,11 @@ BlitNTL4: cmp al, 254 jne BlitNTL6 + mov al, fIgnoreShadows + cmp al, 0 + jne BlitNTL5 mov ax, [edi] + mov ax, ShadeTable[eax*2] mov [edi], ax jmp BlitNTL5 @@ -8959,7 +9377,7 @@ BlitDone: dimensions (including Pitch) as the destination. **********************************************************************************************/ -BOOLEAN Blt8BPPDataTo16BPPBufferTransShadowZNB( UINT16 *pBuffer, UINT32 uiDestPitchBYTES, UINT16 *pZBuffer, UINT16 usZValue, HVOBJECT hSrcVObject, INT32 iX, INT32 iY, UINT16 usIndex, UINT16 *p16BPPPalette ) +BOOLEAN Blt8BPPDataTo16BPPBufferTransShadowZNB(UINT16 *pBuffer, UINT32 uiDestPitchBYTES, UINT16 *pZBuffer, UINT16 usZValue, HVOBJECT hSrcVObject, INT32 iX, INT32 iY, UINT16 usIndex, UINT16 *p16BPPPalette, BOOLEAN fIgnoreShadows) { UINT32 uiOffset; UINT32 usHeight, usWidth; @@ -9027,6 +9445,10 @@ BlitNTL4: cmp ax, usZValue jae BlitNTL5 + mov al, fIgnoreShadows + cmp al, 0 + jne BlitNTL5 + mov ax, [edi] mov ax, ShadeTable[eax*2] mov [edi], ax @@ -9073,6 +9495,169 @@ BlitDone: } +/********************************************************************************************** + Blt8BPPDataTo16BPPBufferTransShadowZNB + + Blits an image into the destination buffer, using an ETRLE brush as a source, and a 16-bit + buffer as a destination. As it is blitting, it checks the Z value of the ZBuffer, and if the + pixel's Z level is below that of the current pixel, it is written on. The Z value is NOT + updated. If the source pixel is 254, it is considered a shadow, and the destination + buffer is darkened rather than blitted on. The Z-buffer is 16 bit, and must be the same + dimensions (including Pitch) as the destination. + +**********************************************************************************************/ +BOOLEAN Blt8BPPDataTo16BPPBufferTransShadowZNBAlpha(UINT16 *pBuffer, UINT32 uiDestPitchBYTES, UINT16 *pZBuffer, UINT16 usZValue, HVOBJECT hSrcVObject, HVOBJECT hAlphaVObject, INT32 iX, INT32 iY, UINT16 usIndex, UINT16 *p16BPPPalette, BOOLEAN fIgnoreShadows) +{ + UINT32 uiOffset; + UINT32 usHeight, usWidth; + UINT8 *SrcPtr, *DestPtr, *ZPtr, *AlphaPtr; + UINT32 LineSkip; + ETRLEObject *pTrav; + INT32 iTempX, iTempY; + + + // Assertions + Assert(hSrcVObject != NULL); + Assert(hAlphaVObject != NULL); + Assert(pBuffer != NULL); + + // Get Offsets from Index into structure + pTrav = &(hSrcVObject->pETRLEObject[usIndex]); + usHeight = (UINT32)pTrav->usHeight; + usWidth = (UINT32)pTrav->usWidth; + uiOffset = pTrav->uiDataOffset; + + // Add to start position of dest buffer + iTempX = iX + pTrav->sOffsetX; + iTempY = iY + pTrav->sOffsetY; + + // Validations + CHECKF(iTempX >= 0); + CHECKF(iTempY >= 0); + + + SrcPtr = (UINT8 *)hSrcVObject->pPixData + uiOffset; + AlphaPtr = (UINT8 *)hAlphaVObject->pPixData + (hAlphaVObject->pETRLEObject[usIndex]).uiDataOffset; + DestPtr = (UINT8 *)pBuffer + (uiDestPitchBYTES*iTempY) + (iTempX * 2); + ZPtr = (UINT8 *)pZBuffer + (uiDestPitchBYTES*iTempY) + (iTempX * 2); + LineSkip = (uiDestPitchBYTES - (usWidth * 2)); + + __asm { + + mov esi, SrcPtr + mov edi, DestPtr + mov edx, p16BPPPalette + xor eax, eax + mov ebx, ZPtr + xor ecx, ecx + + BlitDispatch : + + mov cl, [esi] + inc esi + + push esi + mov esi, AlphaPtr + inc esi + mov AlphaPtr, esi + pop esi + + or cl, cl + js BlitTransparent + jz BlitDoneLine + + //BlitNonTransLoop: + + BlitNTL4 : + + mov ax, [ebx] + cmp ax, usZValue + ja BlitNTL5 + + xor eax, eax + mov al, [esi] + cmp al, 254 + jne BlitNTL6 + + mov ax, [ebx] + cmp ax, usZValue + jae BlitNTL5 + + mov al, fIgnoreShadows + cmp al, 0 + jne BlitNTL5 + + mov ax, [edi] + mov ax, ShadeTable[eax * 2] + mov[edi], ax + jmp BlitNTL5 + + + BlitNTL6 : + mov ax, [edx + eax * 2] + + push edx + push ecx + push ebx + push esi + mov esi, AlphaPtr + xor ebx, ebx + mov bl, [esi] + pop esi + push ebx + push[edi] + push eax + call blendWithAlpha + add esp, 12 + pop ebx + pop ecx + pop edx + + mov[edi], ax + + BlitNTL5 : + inc esi + + push esi + mov esi, AlphaPtr + inc esi + mov AlphaPtr, esi + pop esi + + add edi, 2 + add ebx, 2 + dec cl + jnz BlitNTL4 + + jmp BlitDispatch + + + BlitTransparent : + + and ecx, 07fH + // shl ecx, 1 + add ecx, ecx + add edi, ecx + add ebx, ecx + jmp BlitDispatch + + + BlitDoneLine : + + dec usHeight + jz BlitDone + add edi, LineSkip + add ebx, LineSkip + jmp BlitDispatch + + + BlitDone : + } + + return(TRUE); + +} + #if 0 @@ -9132,7 +9717,7 @@ BlitNTL10: dimensions (including Pitch) as the destination. **********************************************************************************************/ -BOOLEAN Blt8BPPDataTo16BPPBufferTransShadowZNBObscured( UINT16 *pBuffer, UINT32 uiDestPitchBYTES, UINT16 *pZBuffer, UINT16 usZValue, HVOBJECT hSrcVObject, INT32 iX, INT32 iY, UINT16 usIndex, UINT16 *p16BPPPalette ) +BOOLEAN Blt8BPPDataTo16BPPBufferTransShadowZNBObscured(UINT16 *pBuffer, UINT32 uiDestPitchBYTES, UINT16 *pZBuffer, UINT16 usZValue, HVOBJECT hSrcVObject, INT32 iX, INT32 iY, UINT16 usIndex, UINT16 *p16BPPPalette, BOOLEAN fIgnoreShadows) { UINT32 uiOffset; UINT32 usHeight, usWidth; @@ -9205,6 +9790,10 @@ BlitNTL4: cmp ax, usZValue jae BlitNTL5 + mov al, fIgnoreShadows + cmp al, 0 + jne BlitNTL5 + mov ax, [edi] mov ax, ShadeTable[eax*2] mov [edi], ax @@ -9276,6 +9865,357 @@ BlitDone: } +/********************************************************************************************** + Blt8BPPDataTo16BPPBufferTransShadowZNBObscured + + Blits an image into the destination buffer, using an ETRLE brush as a source, and a 16-bit + buffer as a destination. As it is blitting, it checks the Z value of the ZBuffer, and if the + pixel's Z level is below that of the current pixel, it is written on. The Z value is NOT + updated. If the source pixel is 254, it is considered a shadow, and the destination + buffer is darkened rather than blitted on. The Z-buffer is 16 bit, and must be the same + dimensions (including Pitch) as the destination. + +**********************************************************************************************/ +BOOLEAN Blt8BPPDataTo16BPPBufferTransShadowZNBObscuredTest(UINT16 *pBuffer, UINT32 uiDestPitchBYTES, UINT16 *pZBuffer, UINT16 usZValue, HVOBJECT hSrcVObject, INT32 iX, INT32 iY, UINT16 usIndex, UINT16 *p16BPPPalette, BOOLEAN fIgnoreShadows) +{ + UINT32 uiOffset; + UINT32 usHeight, usWidth; + UINT8 *SrcPtr, *DestPtr, *ZPtr; + UINT32 LineSkip; + ETRLEObject *pTrav; + INT32 iTempX, iTempY; + UINT32 uiLineFlag; + + + + // Assertions + Assert(hSrcVObject != NULL); + Assert(pBuffer != NULL); + + // Get Offsets from Index into structure + pTrav = &(hSrcVObject->pETRLEObject[usIndex]); + usHeight = (UINT32)pTrav->usHeight; + usWidth = (UINT32)pTrav->usWidth; + uiOffset = pTrav->uiDataOffset; + + // Add to start position of dest buffer + iTempX = iX + pTrav->sOffsetX; + iTempY = iY + pTrav->sOffsetY; + + // Validations + CHECKF(iTempX >= 0); + CHECKF(iTempY >= 0); + + + SrcPtr = (UINT8 *)hSrcVObject->pPixData + uiOffset; + DestPtr = (UINT8 *)pBuffer + (uiDestPitchBYTES*iTempY) + (iTempX * 2); + ZPtr = (UINT8 *)pZBuffer + (uiDestPitchBYTES*iTempY) + (iTempX * 2); + LineSkip = (uiDestPitchBYTES - (usWidth * 2)); + uiLineFlag = (iTempY & 1); + + + __asm { + + mov esi, SrcPtr + mov edi, DestPtr + mov edx, p16BPPPalette + xor eax, eax + mov ebx, ZPtr + xor ecx, ecx + + BlitDispatch : + + mov cl, [esi] + inc esi + or cl, cl + js BlitTransparent + jz BlitDoneLine + + //BlitNonTransLoop: + + BlitNTL4 : + + + mov ax, [ebx] + cmp ax, usZValue + ja BlitNTL8 + + xor eax, eax + mov al, [esi] + cmp al, 254 + jne BlitNTL6 + + mov ax, [ebx] + cmp ax, usZValue + jae BlitNTL5 + + mov al, fIgnoreShadows + cmp al, 0 + jne BlitNTL5 + mov ax, [edi] + mov ax, ShadeTable[eax * 2] + mov[edi], ax + jmp BlitNTL5 + + + BlitNTL8 : + + xor eax, eax + mov al, [esi] + cmp al, 254 + je BlitNTL5 + + test uiLineFlag, 1 + jz BlitNTL9 + + test edi, 2 + jz BlitNTL5 + + jmp BlitNTL6 + + BlitNTL9 : + test edi, 2 + jnz BlitNTL5 + + BlitNTL6 : + + xor eax, eax + mov al, [esi] + mov ax, [edx + eax * 2] + + push edx + push ecx + push ebx + push 0x0000007f + push[edi] + push eax + call blendWithAlpha + add esp, 12 + pop ebx + pop ecx + pop edx + + mov[edi], ax + + BlitNTL5 : + inc esi + add edi, 2 + add ebx, 2 + dec cl + jnz BlitNTL4 + + jmp BlitDispatch + + + BlitTransparent : + + and ecx, 07fH + // shl ecx, 1 + add ecx, ecx + add edi, ecx + add ebx, ecx + jmp BlitDispatch + + + BlitDoneLine : + + dec usHeight + jz BlitDone + add edi, LineSkip + add ebx, LineSkip + xor uiLineFlag, 1 + jmp BlitDispatch + + + BlitDone : + } + + return(TRUE); + +} + +/********************************************************************************************** + Blt8BPPDataTo16BPPBufferTransShadowZNBObscured + + Blits an image into the destination buffer, using an ETRLE brush as a source, and a 16-bit + buffer as a destination. As it is blitting, it checks the Z value of the ZBuffer, and if the + pixel's Z level is below that of the current pixel, it is written on. The Z value is NOT + updated. If the source pixel is 254, it is considered a shadow, and the destination + buffer is darkened rather than blitted on. The Z-buffer is 16 bit, and must be the same + dimensions (including Pitch) as the destination. + +**********************************************************************************************/ +BOOLEAN Blt8BPPDataTo16BPPBufferTransShadowZNBObscuredAlpha(UINT16 *pBuffer, UINT32 uiDestPitchBYTES, UINT16 *pZBuffer, UINT16 usZValue, HVOBJECT hSrcVObject, HVOBJECT hAlphaVObject, INT32 iX, INT32 iY, UINT16 usIndex, UINT16 *p16BPPPalette, BOOLEAN fIgnoreShadows) +{ + UINT32 uiOffset; + UINT32 usHeight, usWidth; + UINT8 *SrcPtr, *DestPtr, *ZPtr, *AlphaPtr; + UINT32 LineSkip; + ETRLEObject *pTrav; + INT32 iTempX, iTempY; + UINT32 uiLineFlag; + + // Assertions + Assert(hSrcVObject != NULL); + Assert(hAlphaVObject != NULL); + Assert(pBuffer != NULL); + + // Get Offsets from Index into structure + pTrav = &(hSrcVObject->pETRLEObject[usIndex]); + usHeight = (UINT32)pTrav->usHeight; + usWidth = (UINT32)pTrav->usWidth; + uiOffset = pTrav->uiDataOffset; + + // Add to start position of dest buffer + iTempX = iX + pTrav->sOffsetX; + iTempY = iY + pTrav->sOffsetY; + + // Validations + CHECKF(iTempX >= 0); + CHECKF(iTempY >= 0); + + SrcPtr = (UINT8 *)hSrcVObject->pPixData + uiOffset; + AlphaPtr = (UINT8 *)hAlphaVObject->pPixData + (hAlphaVObject->pETRLEObject[usIndex]).uiDataOffset; + DestPtr = (UINT8 *)pBuffer + (uiDestPitchBYTES*iTempY) + (iTempX * 2); + ZPtr = (UINT8 *)pZBuffer + (uiDestPitchBYTES*iTempY) + (iTempX * 2); + LineSkip = (uiDestPitchBYTES - (usWidth * 2)); + uiLineFlag = (iTempY & 1); + + __asm { + + mov esi, SrcPtr + mov edi, DestPtr + mov edx, p16BPPPalette + xor eax, eax + mov ebx, ZPtr + xor ecx, ecx + + BlitDispatch : + + mov cl, [esi] + inc esi + push esi + mov esi, AlphaPtr + inc esi + mov AlphaPtr, esi + pop esi + or cl, cl + js BlitTransparent + jz BlitDoneLine + + //BlitNonTransLoop: + + BlitNTL4 : + + + mov ax, [ebx] + cmp ax, usZValue + ja BlitNTL8 + + xor eax, eax + mov al, [esi] + cmp al, 254 + jne BlitNTL6 + + mov ax, [ebx] + cmp ax, usZValue + jae BlitNTL5 + + mov al, fIgnoreShadows + cmp al, 0 + jne BlitNTL5 + mov ax, [edi] + mov ax, ShadeTable[eax * 2] + mov[edi], ax + jmp BlitNTL5 + + + BlitNTL8 : + + xor eax, eax + mov al, [esi] + cmp al, 254 + je BlitNTL5 + + test uiLineFlag, 1 + jz BlitNTL9 + + test edi, 2 + jz BlitNTL5 + + jmp BlitNTL6 + + BlitNTL9 : + test edi, 2 + jnz BlitNTL5 + + BlitNTL6 : + + xor eax, eax + mov al, [esi] + mov ax, [edx + eax * 2] + + push edx + push ecx + push ebx + push esi + mov esi, AlphaPtr + xor ebx, ebx + mov bl, [esi] + pop esi + push ebx + push[edi] + push eax + call blendWithAlpha + add esp, 12 + pop ebx + pop ecx + pop edx + + mov[edi], ax + + BlitNTL5 : + inc esi + push esi + mov esi, AlphaPtr + inc esi + mov AlphaPtr, esi + pop esi + add edi, 2 + add ebx, 2 + dec cl + jnz BlitNTL4 + + jmp BlitDispatch + + + BlitTransparent : + + and ecx, 07fH + // shl ecx, 1 + add ecx, ecx + add edi, ecx + add ebx, ecx + jmp BlitDispatch + + + BlitDoneLine : + + dec usHeight + jz BlitDone + add edi, LineSkip + add ebx, LineSkip + xor uiLineFlag, 1 + jmp BlitDispatch + + + BlitDone : + } + + return(TRUE); + +} + /********************************************************************************************** Blt8BPPDataTo16BPPBufferTransShadowZClip @@ -9287,7 +10227,7 @@ BlitDone: 254 are shaded instead of blitted. **********************************************************************************************/ -BOOLEAN Blt8BPPDataTo16BPPBufferTransShadowZClip( UINT16 *pBuffer, UINT32 uiDestPitchBYTES, UINT16 *pZBuffer, UINT16 usZValue, HVOBJECT hSrcVObject, INT32 iX, INT32 iY, UINT16 usIndex, SGPRect *clipregion, UINT16 *p16BPPPalette ) +BOOLEAN Blt8BPPDataTo16BPPBufferTransShadowZClip(UINT16 *pBuffer, UINT32 uiDestPitchBYTES, UINT16 *pZBuffer, UINT16 usZValue, HVOBJECT hSrcVObject, INT32 iX, INT32 iY, UINT16 usIndex, SGPRect *clipregion, UINT16 *p16BPPPalette, BOOLEAN fIgnoreShadows) { UINT32 uiOffset; UINT32 usHeight, usWidth, Unblitted; @@ -9474,6 +10414,10 @@ BlitNTL1: cmp al, 254 jne BlitNTL3 + mov al, fIgnoreShadows + cmp al, 0 + jne BlitNTL2 + mov ax, [edi] mov ax, ShadeTable[eax*2] mov [edi], ax @@ -9537,6 +10481,347 @@ BlitDone: } +/********************************************************************************************** + Blt8BPPDataTo16BPPBufferTransShadowZClip + + Blits an image into the destination buffer, using an ETRLE brush as a source, and a 16-bit + buffer as a destination. As it is blitting, it checks the Z value of the ZBuffer, and if the + pixel's Z level is below that of the current pixel, it is written on, and the Z value is + updated to the current value, for any non-transparent pixels. The Z-buffer is 16 bit, and + must be the same dimensions (including Pitch) as the destination. Pixels with a value of + 254 are shaded instead of blitted. + +**********************************************************************************************/ +BOOLEAN Blt8BPPDataTo16BPPBufferTransShadowZClipAlpha(UINT16 *pBuffer, UINT32 uiDestPitchBYTES, UINT16 *pZBuffer, UINT16 usZValue, HVOBJECT hSrcVObject, HVOBJECT hAlphaVObject, INT32 iX, INT32 iY, UINT16 usIndex, SGPRect *clipregion, UINT16 *p16BPPPalette, BOOLEAN fIgnoreShadows) +{ + UINT32 uiOffset; + UINT32 usHeight, usWidth, Unblitted; + UINT8 *SrcPtr, *DestPtr, *ZPtr, *AlphaPtr; + UINT32 LineSkip; + ETRLEObject *pTrav; + INT32 iTempX, iTempY, LeftSkip, RightSkip, TopSkip, BottomSkip, BlitLength, BlitHeight, LSCount; + INT32 ClipX1, ClipY1, ClipX2, ClipY2; + + // Assertions + Assert(hSrcVObject != NULL); + Assert(hAlphaVObject != NULL); + Assert(pBuffer != NULL); + + // Get Offsets from Index into structure + pTrav = &(hSrcVObject->pETRLEObject[usIndex]); + usHeight = (UINT32)pTrav->usHeight; + usWidth = (UINT32)pTrav->usWidth; + uiOffset = pTrav->uiDataOffset; + + // Add to start position of dest buffer + iTempX = iX + pTrav->sOffsetX; + iTempY = iY + pTrav->sOffsetY; + + if (clipregion == NULL) + { + ClipX1 = ClippingRect.iLeft; + ClipY1 = ClippingRect.iTop; + ClipX2 = ClippingRect.iRight; + ClipY2 = ClippingRect.iBottom; + } + else + { + ClipX1 = clipregion->iLeft; + ClipY1 = clipregion->iTop; + ClipX2 = clipregion->iRight; + ClipY2 = clipregion->iBottom; + } + + // Calculate rows hanging off each side of the screen + LeftSkip = __min(ClipX1 - min(ClipX1, iTempX), (INT32)usWidth); + RightSkip = __min(max(ClipX2, (iTempX + (INT32)usWidth)) - ClipX2, (INT32)usWidth); + TopSkip = __min(ClipY1 - __min(ClipY1, iTempY), (INT32)usHeight); + BottomSkip = __min(__max(ClipY2, (iTempY + (INT32)usHeight)) - ClipY2, (INT32)usHeight); + + // calculate the remaining rows and columns to blit + BlitLength = ((INT32)usWidth - LeftSkip - RightSkip); + BlitHeight = ((INT32)usHeight - TopSkip - BottomSkip); + + // check if whole thing is clipped + if ((LeftSkip >= (INT32)usWidth) || (RightSkip >= (INT32)usWidth)) + return(TRUE); + + // check if whole thing is clipped + if ((TopSkip >= (INT32)usHeight) || (BottomSkip >= (INT32)usHeight)) + return(TRUE); + + SrcPtr = (UINT8 *)hSrcVObject->pPixData + uiOffset; + AlphaPtr = (UINT8 *)hAlphaVObject->pPixData + (hAlphaVObject->pETRLEObject[usIndex]).uiDataOffset; + DestPtr = (UINT8 *)pBuffer + (uiDestPitchBYTES*(iTempY + TopSkip)) + ((iTempX + LeftSkip) * 2); + ZPtr = (UINT8 *)pZBuffer + (uiDestPitchBYTES*(iTempY + TopSkip)) + ((iTempX + LeftSkip) * 2); + LineSkip = (uiDestPitchBYTES - (BlitLength * 2)); + + __asm { + + mov esi, SrcPtr + mov edi, DestPtr + mov edx, p16BPPPalette + xor eax, eax + mov ebx, ZPtr + xor ecx, ecx + + cmp TopSkip, 0 // check for nothing clipped on top + je LeftSkipSetup + + TopSkipLoop : // Skips the number of lines clipped at the top + + mov cl, [esi] + inc esi + or cl, cl + js TopSkipLoop + jz TSEndLine + + add esi, ecx + + push esi + mov esi, AlphaPtr + add esi, ecx + mov AlphaPtr, esi + pop esi + + jmp TopSkipLoop + + TSEndLine : + dec TopSkip + jnz TopSkipLoop + + LeftSkipSetup : + + mov Unblitted, 0 + mov eax, LeftSkip + mov LSCount, eax + or eax, eax + jz BlitLineSetup + + LeftSkipLoop : + + mov cl, [esi] + inc esi + + or cl, cl + js LSTrans + + cmp ecx, LSCount + je LSSkip2 // if equal, skip whole, and start blit with new run + jb LSSkip1 // if less, skip whole thing + + add esi, LSCount // skip partial run, jump into normal loop for rest + + push esi + mov esi, AlphaPtr + add esi, LSCount + mov AlphaPtr, esi + pop esi + + sub ecx, LSCount + mov eax, BlitLength + mov LSCount, eax + mov Unblitted, 0 + jmp BlitNonTransLoop + + LSSkip2 : + add esi, ecx // skip whole run, and start blit with new run + + push esi + mov esi, AlphaPtr + add esi, ecx + mov AlphaPtr, esi + pop esi + + jmp BlitLineSetup + + + LSSkip1 : + add esi, ecx // skip whole run, continue skipping + + push esi + mov esi, AlphaPtr + add esi, ecx + mov AlphaPtr, esi + pop esi + + sub LSCount, ecx + jmp LeftSkipLoop + + + LSTrans : + and ecx, 07fH + cmp ecx, LSCount + je BlitLineSetup // if equal, skip whole, and start blit with new run + jb LSTrans1 // if less, skip whole thing + + sub ecx, LSCount // skip partial run, jump into normal loop for rest + mov eax, BlitLength + mov LSCount, eax + mov Unblitted, 0 + jmp BlitTransparent + + + LSTrans1 : + sub LSCount, ecx // skip whole run, continue skipping + jmp LeftSkipLoop + + + BlitLineSetup : // Does any actual blitting (trans/non) for the line + mov eax, BlitLength + mov LSCount, eax + mov Unblitted, 0 + + BlitDispatch : + + cmp LSCount, 0 // Check to see if we're done blitting + je RightSkipLoop + + mov cl, [esi] + inc esi + + push esi + mov esi, AlphaPtr + inc esi + mov AlphaPtr, esi + pop esi + + or cl, cl + js BlitTransparent + + BlitNonTransLoop : // blit non-transparent pixels + + cmp ecx, LSCount + jbe BNTrans1 + + sub ecx, LSCount + mov Unblitted, ecx + mov ecx, LSCount + + BNTrans1 : + sub LSCount, ecx + + BlitNTL1 : + + mov ax, [ebx] + cmp ax, usZValue + jae BlitNTL2 + + mov ax, usZValue + mov[ebx], ax + + xor eax, eax + + mov al, [esi] + cmp al, 254 + jne BlitNTL3 + + mov al, fIgnoreShadows + cmp al, 0 + jne BlitNTL2 + + mov ax, [edi] + mov ax, ShadeTable[eax * 2] + mov[edi], ax + jmp BlitNTL2 + + BlitNTL3 : + mov ax, [edx + eax * 2] + + push edx + push ecx + push ebx + push esi + mov esi, AlphaPtr + xor ebx, ebx + mov bl, [esi] + pop esi + push ebx + push[edi] + push eax + call blendWithAlpha + add esp, 12 + pop ebx + pop ecx + pop edx + + mov[edi], ax + + BlitNTL2 : + inc esi + + push esi + mov esi, AlphaPtr + inc esi + mov AlphaPtr, esi + pop esi + + add edi, 2 + add ebx, 2 + dec cl + jnz BlitNTL1 + + //BlitLineEnd: + add esi, Unblitted + + push esi + mov esi, AlphaPtr + add esi, Unblitted + mov AlphaPtr, esi + pop esi + + jmp BlitDispatch + + BlitTransparent : // skip transparent pixels + + and ecx, 07fH + cmp ecx, LSCount + jbe BTrans1 + + mov ecx, LSCount + + BTrans1 : + + sub LSCount, ecx + // shl ecx, 1 + add ecx, ecx + add edi, ecx + add ebx, ecx + jmp BlitDispatch + + + RightSkipLoop : // skip along until we hit and end-of-line marker + + + RSLoop1: + mov al, [esi] + inc esi + + push esi + mov esi, AlphaPtr + inc esi + mov AlphaPtr, esi + pop esi + + or al, al + jnz RSLoop1 + + dec BlitHeight + jz BlitDone + add edi, LineSkip + add ebx, LineSkip + + jmp LeftSkipSetup + + + BlitDone : + } + + return(TRUE); + +} + + /********************************************************************************************** Blt8BPPDataTo16BPPBufferTransShadowClip @@ -9548,7 +10833,7 @@ BlitDone: 254 are shaded instead of blitted. **********************************************************************************************/ -BOOLEAN Blt8BPPDataTo16BPPBufferTransShadowClip( UINT16 *pBuffer, UINT32 uiDestPitchBYTES, HVOBJECT hSrcVObject, INT32 iX, INT32 iY, UINT16 usIndex, SGPRect *clipregion, UINT16 *p16BPPPalette ) +BOOLEAN Blt8BPPDataTo16BPPBufferTransShadowClip(UINT16 *pBuffer, UINT32 uiDestPitchBYTES, HVOBJECT hSrcVObject, INT32 iX, INT32 iY, UINT16 usIndex, SGPRect *clipregion, UINT16 *p16BPPPalette, BOOLEAN fIgnoreShadows) { UINT32 uiOffset; UINT32 usHeight, usWidth, Unblitted; @@ -9725,6 +11010,10 @@ BlitNTL1: cmp al, 254 jne BlitNTL3 + mov al, fIgnoreShadows + cmp al, 0 + jne BlitNTL2 + mov ax, [edi] mov ax, ShadeTable[eax*2] mov [edi], ax @@ -9784,6 +11073,341 @@ BlitDone: } +/********************************************************************************************** + Blt8BPPDataTo16BPPBufferTransShadowClip + + Blits an image into the destination buffer, using an ETRLE brush as a source, and a 16-bit + buffer as a destination. As it is blitting, it checks the Z value of the ZBuffer, and if the + pixel's Z level is below that of the current pixel, it is written on, and the Z value is + updated to the current value, for any non-transparent pixels. The Z-buffer is 16 bit, and + must be the same dimensions (including Pitch) as the destination. Pixels with a value of + 254 are shaded instead of blitted. + +**********************************************************************************************/ +BOOLEAN Blt8BPPDataTo16BPPBufferTransShadowClipAlpha(UINT16 *pBuffer, UINT32 uiDestPitchBYTES, HVOBJECT hSrcVObject, HVOBJECT hAlphaVObject, INT32 iX, INT32 iY, UINT16 usIndex, SGPRect *clipregion, UINT16 *p16BPPPalette, BOOLEAN fIgnoreShadows) +{ + UINT32 uiOffset; + UINT32 usHeight, usWidth, Unblitted; + UINT8 *SrcPtr, *DestPtr, *AlphaPtr; + UINT32 LineSkip; + ETRLEObject *pTrav; + INT32 iTempX, iTempY, LeftSkip, RightSkip, TopSkip, BottomSkip, BlitLength, BlitHeight, LSCount; + INT32 ClipX1, ClipY1, ClipX2, ClipY2; + + // Assertions + Assert(hSrcVObject != NULL); + Assert(hAlphaVObject != NULL); + Assert(pBuffer != NULL); + + // Get Offsets from Index into structure + pTrav = &(hSrcVObject->pETRLEObject[usIndex]); + usHeight = (UINT32)pTrav->usHeight; + usWidth = (UINT32)pTrav->usWidth; + uiOffset = pTrav->uiDataOffset; + + // Add to start position of dest buffer + iTempX = iX + pTrav->sOffsetX; + iTempY = iY + pTrav->sOffsetY; + + if (clipregion == NULL) + { + ClipX1 = ClippingRect.iLeft; + ClipY1 = ClippingRect.iTop; + ClipX2 = ClippingRect.iRight; + ClipY2 = ClippingRect.iBottom; + } + else + { + ClipX1 = clipregion->iLeft; + ClipY1 = clipregion->iTop; + ClipX2 = clipregion->iRight; + ClipY2 = clipregion->iBottom; + } + + // Calculate rows hanging off each side of the screen + LeftSkip = __min(ClipX1 - min(ClipX1, iTempX), (INT32)usWidth); + RightSkip = __min(max(ClipX2, (iTempX + (INT32)usWidth)) - ClipX2, (INT32)usWidth); + TopSkip = __min(ClipY1 - __min(ClipY1, iTempY), (INT32)usHeight); + BottomSkip = __min(__max(ClipY2, (iTempY + (INT32)usHeight)) - ClipY2, (INT32)usHeight); + + // calculate the remaining rows and columns to blit + BlitLength = ((INT32)usWidth - LeftSkip - RightSkip); + BlitHeight = ((INT32)usHeight - TopSkip - BottomSkip); + + // check if whole thing is clipped + if ((LeftSkip >= (INT32)usWidth) || (RightSkip >= (INT32)usWidth)) + return(TRUE); + + // check if whole thing is clipped + if ((TopSkip >= (INT32)usHeight) || (BottomSkip >= (INT32)usHeight)) + return(TRUE); + + SrcPtr = (UINT8 *)hSrcVObject->pPixData + uiOffset; + AlphaPtr = (UINT8 *)hAlphaVObject->pPixData + (hAlphaVObject->pETRLEObject[usIndex]).uiDataOffset; + DestPtr = (UINT8 *)pBuffer + (uiDestPitchBYTES*(iTempY + TopSkip)) + ((iTempX + LeftSkip) * 2); + LineSkip = (uiDestPitchBYTES - (BlitLength * 2)); + + __asm { + + mov esi, SrcPtr + mov edi, DestPtr + mov edx, p16BPPPalette + xor eax, eax + xor ecx, ecx + + cmp TopSkip, 0 // check for nothing clipped on top + je LeftSkipSetup + + TopSkipLoop : // Skips the number of lines clipped at the top + + mov cl, [esi] + inc esi + + push esi + mov esi, AlphaPtr + inc esi + mov AlphaPtr, esi + pop esi + + or cl, cl + js TopSkipLoop + jz TSEndLine + + add esi, ecx + + push esi + mov esi, AlphaPtr + add esi, ecx + mov AlphaPtr, esi + pop esi + + jmp TopSkipLoop + + TSEndLine : + dec TopSkip + jnz TopSkipLoop + + LeftSkipSetup : + + mov Unblitted, 0 + mov eax, LeftSkip + mov LSCount, eax + or eax, eax + jz BlitLineSetup + + LeftSkipLoop : + + mov cl, [esi] + inc esi + + or cl, cl + js LSTrans + + cmp ecx, LSCount + je LSSkip2 // if equal, skip whole, and start blit with new run + jb LSSkip1 // if less, skip whole thing + + add esi, LSCount // skip partial run, jump into normal loop for rest + + push esi + mov esi, AlphaPtr + add esi, LSCount + mov AlphaPtr, esi + pop esi + + sub ecx, LSCount + mov eax, BlitLength + mov LSCount, eax + mov Unblitted, 0 + jmp BlitNonTransLoop + + LSSkip2 : + add esi, ecx // skip whole run, and start blit with new run + + push esi + mov esi, AlphaPtr + add esi, ecx + mov AlphaPtr, esi + pop esi + + jmp BlitLineSetup + + + LSSkip1 : + add esi, ecx // skip whole run, continue skipping + + push esi + mov esi, AlphaPtr + add esi, ecx + mov AlphaPtr, esi + pop esi + + sub LSCount, ecx + jmp LeftSkipLoop + + + LSTrans : + and ecx, 07fH + cmp ecx, LSCount + je BlitLineSetup // if equal, skip whole, and start blit with new run + jb LSTrans1 // if less, skip whole thing + + sub ecx, LSCount // skip partial run, jump into normal loop for rest + mov eax, BlitLength + mov LSCount, eax + mov Unblitted, 0 + jmp BlitTransparent + + + LSTrans1 : + sub LSCount, ecx // skip whole run, continue skipping + jmp LeftSkipLoop + + + BlitLineSetup : // Does any actual blitting (trans/non) for the line + mov eax, BlitLength + mov LSCount, eax + mov Unblitted, 0 + + BlitDispatch : + + cmp LSCount, 0 // Check to see if we're done blitting + je RightSkipLoop + + mov cl, [esi] + inc esi + + push esi + mov esi, AlphaPtr + inc esi + mov AlphaPtr, esi + pop esi + + or cl, cl + js BlitTransparent + + BlitNonTransLoop : // blit non-transparent pixels + + cmp ecx, LSCount + jbe BNTrans1 + + sub ecx, LSCount + mov Unblitted, ecx + mov ecx, LSCount + + BNTrans1 : + sub LSCount, ecx + + BlitNTL1 : + xor eax, eax + + mov al, [esi] + cmp al, 254 + jne BlitNTL3 + + mov al, fIgnoreShadows + cmp al, 0 + jne BlitNTL2 + + mov ax, [edi] + mov ax, ShadeTable[eax * 2] + mov[edi], ax + jmp BlitNTL2 + + BlitNTL3 : + mov ax, [edx + eax * 2] + + push edx + push ecx + push ebx + push esi + mov esi, AlphaPtr + xor ebx, ebx + mov bl, [esi] + pop esi + push ebx + push[edi] + push eax + call blendWithAlpha + add esp, 12 + pop ebx + pop ecx + pop edx + + mov[edi], ax + + BlitNTL2 : + inc esi + + push esi + mov esi, AlphaPtr + inc esi + mov AlphaPtr, esi + pop esi + + add edi, 2 + dec cl + jnz BlitNTL1 + + //BlitLineEnd: + add esi, Unblitted + + push esi + mov esi, AlphaPtr + add esi, Unblitted + mov AlphaPtr, esi + pop esi + + jmp BlitDispatch + + BlitTransparent : // skip transparent pixels + + and ecx, 07fH + cmp ecx, LSCount + jbe BTrans1 + + mov ecx, LSCount + + BTrans1 : + + sub LSCount, ecx + // shl ecx, 1 + add ecx, ecx + add edi, ecx + jmp BlitDispatch + + + RightSkipLoop : // skip along until we hit and end-of-line marker + + + RSLoop1: + mov al, [esi] + inc esi + + push esi + mov esi, AlphaPtr + inc esi + mov AlphaPtr, esi + pop esi + + or al, al + jnz RSLoop1 + + dec BlitHeight + jz BlitDone + add edi, LineSkip + + jmp LeftSkipSetup + + + BlitDone : + } + + return(TRUE); + +} + + /********************************************************************************************** Blt8BPPDataTo16BPPBufferTransShadowZNBClip @@ -9795,7 +11419,7 @@ BlitDone: NOT updated. **********************************************************************************************/ -BOOLEAN Blt8BPPDataTo16BPPBufferTransShadowZNBClip( UINT16 *pBuffer, UINT32 uiDestPitchBYTES, UINT16 *pZBuffer, UINT16 usZValue, HVOBJECT hSrcVObject, INT32 iX, INT32 iY, UINT16 usIndex, SGPRect *clipregion, UINT16 *p16BPPPalette ) +BOOLEAN Blt8BPPDataTo16BPPBufferTransShadowZNBClip(UINT16 *pBuffer, UINT32 uiDestPitchBYTES, UINT16 *pZBuffer, UINT16 usZValue, HVOBJECT hSrcVObject, INT32 iX, INT32 iY, UINT16 usIndex, SGPRect *clipregion, UINT16 *p16BPPPalette, BOOLEAN fIgnoreShadows) { UINT32 uiOffset; UINT32 usHeight, usWidth, Unblitted; @@ -9983,6 +11607,10 @@ BlitNTL1: cmp ax, usZValue jae BlitNTL2 + mov al, fIgnoreShadows + cmp al, 0 + jne BlitNTL2 + mov ax, [edi] mov ax, ShadeTable[eax*2] mov [edi], ax @@ -10057,7 +11685,363 @@ BlitDone: NOT updated. **********************************************************************************************/ -BOOLEAN Blt8BPPDataTo16BPPBufferTransShadowZNBObscuredClip( UINT16 *pBuffer, UINT32 uiDestPitchBYTES, UINT16 *pZBuffer, UINT16 usZValue, HVOBJECT hSrcVObject, INT32 iX, INT32 iY, UINT16 usIndex, SGPRect *clipregion, UINT16 *p16BPPPalette ) +BOOLEAN Blt8BPPDataTo16BPPBufferTransShadowZNBClipAlpha(UINT16 *pBuffer, UINT32 uiDestPitchBYTES, UINT16 *pZBuffer, UINT16 usZValue, HVOBJECT hSrcVObject, HVOBJECT hAlphaVObject, INT32 iX, INT32 iY, UINT16 usIndex, SGPRect *clipregion, UINT16 *p16BPPPalette, BOOLEAN fIgnoreShadows) +{ + UINT32 uiOffset; + UINT32 usHeight, usWidth, Unblitted; + UINT8 *SrcPtr, *DestPtr, *ZPtr, *AlphaPtr; + UINT32 LineSkip; + ETRLEObject *pTrav; + INT32 iTempX, iTempY, LeftSkip, RightSkip, TopSkip, BottomSkip, BlitLength, BlitHeight, LSCount; + INT32 ClipX1, ClipY1, ClipX2, ClipY2; + + // Assertions + Assert(hSrcVObject != NULL); + Assert(hAlphaVObject != NULL); + Assert(pBuffer != NULL); + + // Get Offsets from Index into structure + pTrav = &(hSrcVObject->pETRLEObject[usIndex]); + usHeight = (UINT32)pTrav->usHeight; + usWidth = (UINT32)pTrav->usWidth; + uiOffset = pTrav->uiDataOffset; + + // Add to start position of dest buffer + iTempX = iX + pTrav->sOffsetX; + iTempY = iY + pTrav->sOffsetY; + + if (clipregion == NULL) + { + ClipX1 = ClippingRect.iLeft; + ClipY1 = ClippingRect.iTop; + ClipX2 = ClippingRect.iRight; + ClipY2 = ClippingRect.iBottom; + } + else + { + ClipX1 = clipregion->iLeft; + ClipY1 = clipregion->iTop; + ClipX2 = clipregion->iRight; + ClipY2 = clipregion->iBottom; + } + + // Calculate rows hanging off each side of the screen + LeftSkip = __min(ClipX1 - min(ClipX1, iTempX), (INT32)usWidth); + RightSkip = __min(max(ClipX2, (iTempX + (INT32)usWidth)) - ClipX2, (INT32)usWidth); + TopSkip = __min(ClipY1 - __min(ClipY1, iTempY), (INT32)usHeight); + BottomSkip = __min(__max(ClipY2, (iTempY + (INT32)usHeight)) - ClipY2, (INT32)usHeight); + + // calculate the remaining rows and columns to blit + BlitLength = ((INT32)usWidth - LeftSkip - RightSkip); + BlitHeight = ((INT32)usHeight - TopSkip - BottomSkip); + + // check if whole thing is clipped + if ((LeftSkip >= (INT32)usWidth) || (RightSkip >= (INT32)usWidth)) + return(TRUE); + + // check if whole thing is clipped + if ((TopSkip >= (INT32)usHeight) || (BottomSkip >= (INT32)usHeight)) + return(TRUE); + + SrcPtr = (UINT8 *)hSrcVObject->pPixData + uiOffset; + AlphaPtr = (UINT8 *)hAlphaVObject->pPixData + (hAlphaVObject->pETRLEObject[usIndex]).uiDataOffset; + DestPtr = (UINT8 *)pBuffer + (uiDestPitchBYTES*(iTempY + TopSkip)) + ((iTempX + LeftSkip) * 2); + ZPtr = (UINT8 *)pZBuffer + (uiDestPitchBYTES*(iTempY + TopSkip)) + ((iTempX + LeftSkip) * 2); + LineSkip = (uiDestPitchBYTES - (BlitLength * 2)); + + __asm { + + mov esi, SrcPtr + mov edi, DestPtr + mov edx, p16BPPPalette + xor eax, eax + mov ebx, ZPtr + xor ecx, ecx + + cmp TopSkip, 0 // check for nothing clipped on top + je LeftSkipSetup + + TopSkipLoop : // Skips the number of lines clipped at the top + + mov cl, [esi] + inc esi + + push esi + mov esi, AlphaPtr + inc esi + mov AlphaPtr, esi + pop esi + + or cl, cl + js TopSkipLoop + jz TSEndLine + + add esi, ecx + + push esi + mov esi, AlphaPtr + add esi, ecx + mov AlphaPtr, esi + pop esi + + jmp TopSkipLoop + + TSEndLine : + dec TopSkip + jnz TopSkipLoop + + LeftSkipSetup : + + mov Unblitted, 0 + mov eax, LeftSkip + mov LSCount, eax + or eax, eax + jz BlitLineSetup + + LeftSkipLoop : + + mov cl, [esi] + + push esi + mov esi, AlphaPtr + inc esi + mov AlphaPtr, esi + pop esi + + inc esi + + or cl, cl + js LSTrans + + cmp ecx, LSCount + je LSSkip2 // if equal, skip whole, and start blit with new run + jb LSSkip1 // if less, skip whole thing + + add esi, LSCount // skip partial run, jump into normal loop for rest + + push esi + mov esi, AlphaPtr + add esi, LSCount + mov AlphaPtr, esi + pop esi + + sub ecx, LSCount + mov eax, BlitLength + mov LSCount, eax + mov Unblitted, 0 + jmp BlitNonTransLoop + + LSSkip2 : + add esi, ecx // skip whole run, and start blit with new run + + push esi + mov esi, AlphaPtr + add esi, ecx + mov AlphaPtr, esi + pop esi + + jmp BlitLineSetup + + + LSSkip1 : + add esi, ecx // skip whole run, continue skipping + + push esi + mov esi, AlphaPtr + add esi, ecx + mov AlphaPtr, esi + pop esi + + sub LSCount, ecx + jmp LeftSkipLoop + + + LSTrans : + and ecx, 07fH + cmp ecx, LSCount + je BlitLineSetup // if equal, skip whole, and start blit with new run + jb LSTrans1 // if less, skip whole thing + + sub ecx, LSCount // skip partial run, jump into normal loop for rest + mov eax, BlitLength + mov LSCount, eax + mov Unblitted, 0 + jmp BlitTransparent + + + LSTrans1 : + sub LSCount, ecx // skip whole run, continue skipping + jmp LeftSkipLoop + + + BlitLineSetup : // Does any actual blitting (trans/non) for the line + mov eax, BlitLength + mov LSCount, eax + mov Unblitted, 0 + + BlitDispatch : + + cmp LSCount, 0 // Check to see if we're done blitting + je RightSkipLoop + + mov cl, [esi] + inc esi + + push esi + mov esi, AlphaPtr + inc esi + mov AlphaPtr, esi + pop esi + + or cl, cl + js BlitTransparent + + BlitNonTransLoop : // blit non-transparent pixels + + cmp ecx, LSCount + jbe BNTrans1 + + sub ecx, LSCount + mov Unblitted, ecx + mov ecx, LSCount + + BNTrans1 : + sub LSCount, ecx + + BlitNTL1 : + + mov ax, [ebx] + cmp ax, usZValue + ja BlitNTL2 + + xor eax, eax + + mov al, [esi] + cmp al, 254 + jne BlitNTL3 + + mov ax, [ebx] + cmp ax, usZValue + jae BlitNTL2 + + mov al, fIgnoreShadows + cmp al, 0 + jne BlitNTL2 + + mov ax, [edi] + mov ax, ShadeTable[eax * 2] + mov[edi], ax + jmp BlitNTL2 + + BlitNTL3 : + mov ax, [edx + eax * 2] + + push edx + push ecx + push ebx + push esi + mov esi, AlphaPtr + xor ebx, ebx + mov bl, [esi] + pop esi + push ebx + push[edi] + push eax + call blendWithAlpha + add esp, 12 + pop ebx + pop ecx + pop edx + + mov[edi], ax + + BlitNTL2 : + inc esi + + push esi + mov esi, AlphaPtr + inc esi + mov AlphaPtr, esi + pop esi + + add edi, 2 + add ebx, 2 + dec cl + jnz BlitNTL1 + + //BlitLineEnd: + add esi, Unblitted + + push esi + mov esi, AlphaPtr + add esi, Unblitted + mov AlphaPtr, esi + pop esi + + jmp BlitDispatch + + BlitTransparent : // skip transparent pixels + + and ecx, 07fH + cmp ecx, LSCount + jbe BTrans1 + + mov ecx, LSCount + + BTrans1 : + + sub LSCount, ecx + // shl ecx, 1 + add ecx, ecx + add edi, ecx + add ebx, ecx + jmp BlitDispatch + + + RightSkipLoop : // skip along until we hit and end-of-line marker + + + RSLoop1: + mov al, [esi] + inc esi + + push esi + mov esi, AlphaPtr + inc esi + mov AlphaPtr, esi + pop esi + + or al, al + jnz RSLoop1 + + dec BlitHeight + jz BlitDone + add edi, LineSkip + add ebx, LineSkip + + jmp LeftSkipSetup + + + BlitDone : + } + + return(TRUE); + +} + + +/********************************************************************************************** + Blt8BPPDataTo16BPPBufferTransShadowZNBClip + + Blits an image into the destination buffer, using an ETRLE brush as a source, and a 16-bit + buffer as a destination. As it is blitting, it checks the Z value of the ZBuffer, and if the + pixel's Z level is below that of the current pixel, it is written on. + The Z-buffer is 16 bit, and must be the same dimensions (including Pitch) as the + destination. Pixels with a value of 254 are shaded instead of blitted. The Z buffer is + NOT updated. + +**********************************************************************************************/ +BOOLEAN Blt8BPPDataTo16BPPBufferTransShadowZNBObscuredClip(UINT16 *pBuffer, UINT32 uiDestPitchBYTES, UINT16 *pZBuffer, UINT16 usZValue, HVOBJECT hSrcVObject, INT32 iX, INT32 iY, UINT16 usIndex, SGPRect *clipregion, UINT16 *p16BPPPalette, BOOLEAN fIgnoreShadows) { UINT32 uiOffset; UINT32 usHeight, usWidth, Unblitted, uiLineFlag; @@ -10246,6 +12230,10 @@ BlitNTL1: cmp ax, usZValue jae BlitNTL2 + mov al, fIgnoreShadows + cmp al, 0 + jne BlitNTL2 + mov ax, [edi] mov ax, ShadeTable[eax*2] mov [edi], ax @@ -10331,6 +12319,377 @@ BlitDone: } +/********************************************************************************************** + Blt8BPPDataTo16BPPBufferTransShadowZNBClip + + Blits an image into the destination buffer, using an ETRLE brush as a source, and a 16-bit + buffer as a destination. As it is blitting, it checks the Z value of the ZBuffer, and if the + pixel's Z level is below that of the current pixel, it is written on. + The Z-buffer is 16 bit, and must be the same dimensions (including Pitch) as the + destination. Pixels with a value of 254 are shaded instead of blitted. The Z buffer is + NOT updated. + +**********************************************************************************************/ +BOOLEAN Blt8BPPDataTo16BPPBufferTransShadowZNBObscuredClipAlpha(UINT16 *pBuffer, UINT32 uiDestPitchBYTES, UINT16 *pZBuffer, UINT16 usZValue, HVOBJECT hSrcVObject, HVOBJECT hAlphaVObject, INT32 iX, INT32 iY, UINT16 usIndex, SGPRect *clipregion, UINT16 *p16BPPPalette, BOOLEAN fIgnoreShadows) +{ + UINT32 uiOffset; + UINT32 usHeight, usWidth, Unblitted, uiLineFlag; + UINT8 *SrcPtr, *DestPtr, *ZPtr, *AlphaPtr; + UINT32 LineSkip; + ETRLEObject *pTrav; + INT32 iTempX, iTempY, LeftSkip, RightSkip, TopSkip, BottomSkip, BlitLength, BlitHeight, LSCount; + INT32 ClipX1, ClipY1, ClipX2, ClipY2; + + // Assertions + Assert(hSrcVObject != NULL); + Assert(hAlphaVObject != NULL); + Assert(pBuffer != NULL); + + // Get Offsets from Index into structure + pTrav = &(hSrcVObject->pETRLEObject[usIndex]); + usHeight = (UINT32)pTrav->usHeight; + usWidth = (UINT32)pTrav->usWidth; + uiOffset = pTrav->uiDataOffset; + + // Add to start position of dest buffer + iTempX = iX + pTrav->sOffsetX; + iTempY = iY + pTrav->sOffsetY; + + if (clipregion == NULL) + { + ClipX1 = ClippingRect.iLeft; + ClipY1 = ClippingRect.iTop; + ClipX2 = ClippingRect.iRight; + ClipY2 = ClippingRect.iBottom; + } + else + { + ClipX1 = clipregion->iLeft; + ClipY1 = clipregion->iTop; + ClipX2 = clipregion->iRight; + ClipY2 = clipregion->iBottom; + } + + // Calculate rows hanging off each side of the screen + LeftSkip = __min(ClipX1 - min(ClipX1, iTempX), (INT32)usWidth); + RightSkip = __min(max(ClipX2, (iTempX + (INT32)usWidth)) - ClipX2, (INT32)usWidth); + TopSkip = __min(ClipY1 - __min(ClipY1, iTempY), (INT32)usHeight); + BottomSkip = __min(__max(ClipY2, (iTempY + (INT32)usHeight)) - ClipY2, (INT32)usHeight); + + // calculate the remaining rows and columns to blit + BlitLength = ((INT32)usWidth - LeftSkip - RightSkip); + BlitHeight = ((INT32)usHeight - TopSkip - BottomSkip); + + // check if whole thing is clipped + if ((LeftSkip >= (INT32)usWidth) || (RightSkip >= (INT32)usWidth)) + return(TRUE); + + // check if whole thing is clipped + if ((TopSkip >= (INT32)usHeight) || (BottomSkip >= (INT32)usHeight)) + return(TRUE); + + SrcPtr = (UINT8 *)hSrcVObject->pPixData + uiOffset; + AlphaPtr = (UINT8 *)hAlphaVObject->pPixData + (hAlphaVObject->pETRLEObject[usIndex]).uiDataOffset; + DestPtr = (UINT8 *)pBuffer + (uiDestPitchBYTES*(iTempY + TopSkip)) + ((iTempX + LeftSkip) * 2); + ZPtr = (UINT8 *)pZBuffer + (uiDestPitchBYTES*(iTempY + TopSkip)) + ((iTempX + LeftSkip) * 2); + LineSkip = (uiDestPitchBYTES - (BlitLength * 2)); + + __asm { + + mov esi, SrcPtr + mov edi, DestPtr + mov edx, p16BPPPalette + xor eax, eax + mov ebx, ZPtr + xor ecx, ecx + + cmp TopSkip, 0 // check for nothing clipped on top + je LeftSkipSetup + + TopSkipLoop : // Skips the number of lines clipped at the top + + mov cl, [esi] + inc esi + + push esi + mov esi, AlphaPtr + inc esi + mov AlphaPtr, esi + pop esi + + or cl, cl + js TopSkipLoop + jz TSEndLine + + add esi, ecx + + push esi + mov esi, AlphaPtr + add esi, ecx + mov AlphaPtr, esi + pop esi + + jmp TopSkipLoop + + TSEndLine : + + xor uiLineFlag, 1 + dec TopSkip + jnz TopSkipLoop + + LeftSkipSetup : + + mov Unblitted, 0 + mov eax, LeftSkip + mov LSCount, eax + or eax, eax + jz BlitLineSetup + + LeftSkipLoop : + + mov cl, [esi] + inc esi + + or cl, cl + js LSTrans + + cmp ecx, LSCount + je LSSkip2 // if equal, skip whole, and start blit with new run + jb LSSkip1 // if less, skip whole thing + + add esi, LSCount // skip partial run, jump into normal loop for rest + + push esi + mov esi, AlphaPtr + add esi, LSCount + mov AlphaPtr, esi + pop esi + + sub ecx, LSCount + mov eax, BlitLength + mov LSCount, eax + mov Unblitted, 0 + jmp BlitNonTransLoop + + LSSkip2 : + add esi, ecx // skip whole run, and start blit with new run + + push esi + mov esi, AlphaPtr + add esi, ecx + mov AlphaPtr, esi + pop esi + + jmp BlitLineSetup + + + LSSkip1 : + add esi, ecx // skip whole run, continue skipping + + push esi + mov esi, AlphaPtr + add esi, ecx + mov AlphaPtr, esi + pop esi + + sub LSCount, ecx + jmp LeftSkipLoop + + + LSTrans : + and ecx, 07fH + cmp ecx, LSCount + je BlitLineSetup // if equal, skip whole, and start blit with new run + jb LSTrans1 // if less, skip whole thing + + sub ecx, LSCount // skip partial run, jump into normal loop for rest + mov eax, BlitLength + mov LSCount, eax + mov Unblitted, 0 + jmp BlitTransparent + + + LSTrans1 : + sub LSCount, ecx // skip whole run, continue skipping + jmp LeftSkipLoop + + + BlitLineSetup : // Does any actual blitting (trans/non) for the line + mov eax, BlitLength + mov LSCount, eax + mov Unblitted, 0 + + BlitDispatch : + + cmp LSCount, 0 // Check to see if we're done blitting + je RightSkipLoop + + mov cl, [esi] + inc esi + + push esi + mov esi, AlphaPtr + inc esi + mov AlphaPtr, esi + pop esi + + or cl, cl + js BlitTransparent + + BlitNonTransLoop : // blit non-transparent pixels + + cmp ecx, LSCount + jbe BNTrans1 + + sub ecx, LSCount + mov Unblitted, ecx + mov ecx, LSCount + + BNTrans1 : + sub LSCount, ecx + + BlitNTL1 : + + mov ax, [ebx] + cmp ax, usZValue + ja BlitPixellate + + xor eax, eax + mov al, [esi] + cmp al, 254 + jne BlitNTL3 + + mov ax, [ebx] + cmp ax, usZValue + jae BlitNTL2 + + mov al, fIgnoreShadows + cmp al, 0 + jne BlitNTL2 + + mov ax, [edi] + mov ax, ShadeTable[eax * 2] + mov[edi], ax + jmp BlitNTL2 + + BlitPixellate : + + xor eax, eax + mov al, [esi] + cmp al, 254 + je BlitNTL2 + + test uiLineFlag, 1 + jz BlitNTL9 + + test edi, 2 + jz BlitNTL2 + jmp BlitNTL3 + + BlitNTL9 : + test edi, 2 + jnz BlitNTL2 + + + BlitNTL3 : + + xor eax, eax + mov al, [esi] + mov ax, [edx + eax * 2] + + push edx + push ecx + push ebx + push esi + mov esi, AlphaPtr + xor ebx, ebx + mov bl, [esi] + pop esi + push ebx + push[edi] + push eax + call blendWithAlpha + add esp, 12 + pop ebx + pop ecx + pop edx + + mov[edi], ax + + BlitNTL2 : + inc esi + + push esi + mov esi, AlphaPtr + inc esi + mov AlphaPtr, esi + pop esi + + add edi, 2 + add ebx, 2 + dec cl + jnz BlitNTL1 + + //BlitLineEnd: + add esi, Unblitted + + push esi + mov esi, AlphaPtr + add esi, Unblitted + mov AlphaPtr, esi + pop esi + + jmp BlitDispatch + + BlitTransparent : // skip transparent pixels + + and ecx, 07fH + cmp ecx, LSCount + jbe BTrans1 + + mov ecx, LSCount + + BTrans1 : + + sub LSCount, ecx + // shl ecx, 1 + add ecx, ecx + add edi, ecx + add ebx, ecx + jmp BlitDispatch + + + RightSkipLoop : // skip along until we hit and end-of-line marker + + + RSLoop1: + mov al, [esi] + inc esi + + push esi + mov esi, AlphaPtr + inc esi + mov AlphaPtr, esi + pop esi + + or al, al + jnz RSLoop1 + + xor uiLineFlag, 1 + dec BlitHeight + jz BlitDone + add edi, LineSkip + add ebx, LineSkip + + jmp LeftSkipSetup + + + BlitDone : + } + + return(TRUE); + +} /********************************************************************************************** @@ -16063,22 +18422,33 @@ BOOLEAN Blt8BPPDataTo16BPPBufferOutlineZ( UINT16 *pBuffer, UINT32 uiDestPitchBYT p16BPPPalette = hSrcVObject->pShadeCurrent; LineSkip=(uiDestPitchBYTES-(usWidth*2)); + + // Compressed sequence consist of multiple subsequences of transparent and non - transparent bytes(SirTech have transparent color as zero). + // Every subsequence on transparent bytes is replaced by one byte with highest bit set to 1. Lower 7 bits hold number of transparent bytes. + // If sequence of transparent bytes is longer than 127, then new byte for transparent bytes encoding used and so on. + + // One service byte used before subsequence of non - transparent bytes. Its highest bit is set to 0. + // Lower 7 bits hold number of non - transparent byte in subsequence. + // If non - transparent bytes subsequence exceeds 127, new service byte is used and so on. + // Every row has zero byte on its end. + + __asm { - mov esi, SrcPtr - mov edi, DestPtr - mov edx, p16BPPPalette - xor eax, eax - mov ebx, ZPtr + mov esi, SrcPtr // Load source pixel data to ESI, starting at the place SrcPtr is pointing to. + mov edi, DestPtr // Load destination buffer to EDI, starting at the place DestPtr is pointing to. + mov edx, p16BPPPalette // Load 16 bit palette to EDX + xor eax, eax // Zero EAX + mov ebx, ZPtr // Load zbuffer to EBX xor ecx, ecx BlitDispatch: - mov cl, [esi] - inc esi + mov cl, [esi] // Read a byte from source and load it to CL. CL is the least signifigant byte of CX, which is the least significant word of ECX + inc esi // Go forward one byte in source data or cl, cl - js BlitTransparent - jz BlitDoneLine + js BlitTransparent // if highest bit is 1 -> we have transparent pixels + jz BlitDoneLine // Zero means end of a row //BlitNonTransLoop: @@ -16086,65 +18456,66 @@ BlitDispatch: BlitNTL4: - mov ax, usZValue - cmp ax, [ebx] + // Do not draw pixel if its z value is less than Z-buffer + mov ax, usZValue // Move Z value we want to compare to, to EAX + cmp ax, [ebx] // Compare against the Z-buffer jb BlitNTL5 // CHECK FOR OUTLINE, BLIT DIFFERENTLY IF WE WANT IT TO! - mov al, [esi] + mov al, [esi] // Load byte from source into AL cmp al, 254 jne BlitNTL6 // DO OUTLINE // ONLY IF WE WANT IT! - mov al, fDoOutline; - cmp al, 1 - jne BlitNTL5 + mov al, fDoOutline; // Load BOOLEAN fDoOutline to AL + cmp al, 1 // Check if it's TRUE + jne BlitNTL5 // Jump if FALSE - mov ax, s16BPPColor - mov [edi], ax + mov ax, s16BPPColor // Load s16BPPColor value to AX + mov [edi], ax // Load color to destination jmp BlitNTL5 BlitNTL6: //Donot write to z-buffer - mov [ebx], ax + mov [ebx], ax // Original comment says to not write to zBuffer. This writes gibberish there so is most likely wrong. xor ah, ah - mov al, [esi] - mov ax, [edx+eax*2] - mov [edi], ax + mov al, [esi] // Load byte from source into AL + mov ax, [edx+eax*2] // Load value from address EDX+EAX*2. EDX holds the 16 bit palette. + mov [edi], ax // Load AX value into destination buffer, ie. color the destination pixel BlitNTL5: - inc esi - inc edi - inc ebx + inc esi // Move a byte forward in source data + inc edi // Move a byte forward in destination data. This is duplicated below so we move two bytes forward in destination data due to it being 16 bit. + inc ebx // Same thing with Z-buffer. inc edi inc ebx dec cl jnz BlitNTL4 - jmp BlitDispatch + jmp BlitDispatch // Jump to the next blit operation BlitTransparent: and ecx, 07fH // shl ecx, 1 - add ecx, ecx - add edi, ecx - add ebx, ecx + add ecx, ecx + add edi, ecx // Add value in ECX to destination buffer + add ebx, ecx // Add value in ECX to Z-buffer jmp BlitDispatch BlitDoneLine: - dec usHeight - jz BlitDone - add edi, LineSkip - add ebx, LineSkip - jmp BlitDispatch + dec usHeight // Decrement Height by 1. We're going through the blitting source data from the top, one row at a time + jz BlitDone // If Height is 0, we're done blitting. + add edi, LineSkip // Skip the rest of the current destination line, so we start at the correct spot for the next line blit. + add ebx, LineSkip // Same for Z-buffer. + jmp BlitDispatch // Jump to the next blit operation BlitDone: diff --git a/Standard Gaming Platform/vobject_blitters.h b/Standard Gaming Platform/vobject_blitters.h index 823ccb8a..2f7c1e1c 100644 --- a/Standard Gaming Platform/vobject_blitters.h +++ b/Standard Gaming Platform/vobject_blitters.h @@ -41,6 +41,8 @@ extern SGPRect ClippingRect; extern UINT32 guiTranslucentMask; extern UINT16 White16BPPPalette[ 256 ]; +unsigned short blendWithAlpha(unsigned int rgb565New, unsigned int rgb565Old, unsigned int alpha); + extern void SetClippingRect(SGPRect *clip); void GetClippingRect(SGPRect *clip); @@ -118,15 +120,21 @@ BOOLEAN Blt8BPPDataTo16BPPBufferTransZ( UINT16 *pBuffer, UINT32 uiDestPitchBYTES BOOLEAN Blt8BPPDataTo16BPPBufferTransZNB( UINT16 *pBuffer, UINT32 uiDestPitchBYTES, UINT16 *pZBuffer, UINT16 usZValue, HVOBJECT hSrcVObject, INT32 iX, INT32 iY, UINT16 usIndex ); BOOLEAN Blt8BPPDataTo16BPPBufferTransZClip( UINT16 *pBuffer, UINT32 uiDestPitchBYTES, UINT16 *pZBuffer, UINT16 usZValue, HVOBJECT hSrcVObject, INT32 iX, INT32 iY, UINT16 usIndex, SGPRect *clipregion); BOOLEAN Blt8BPPDataTo16BPPBufferTransZNBClip( UINT16 *pBuffer, UINT32 uiDestPitchBYTES, UINT16 *pZBuffer, UINT16 usZValue, HVOBJECT hSrcVObject, INT32 iX, INT32 iY, UINT16 usIndex, SGPRect *clipregion); -BOOLEAN Blt8BPPDataTo16BPPBufferTransShadowZ( UINT16 *pBuffer, UINT32 uiDestPitchBYTES, UINT16 *pZBuffer, UINT16 usZValue, HVOBJECT hSrcVObject, INT32 iX, INT32 iY, UINT16 usIndex, UINT16 *p16BPPPalette ); -BOOLEAN Blt8BPPDataTo16BPPBufferTransShadowClip( UINT16 *pBuffer, UINT32 uiDestPitchBYTES, HVOBJECT hSrcVObject, INT32 iX, INT32 iY, UINT16 usIndex, SGPRect *clipregion, UINT16 *p16BPPPalette ); -BOOLEAN Blt8BPPDataTo16BPPBufferTransShadowZNB( UINT16 *pBuffer, UINT32 uiDestPitchBYTES, UINT16 *pZBuffer, UINT16 usZValue, HVOBJECT hSrcVObject, INT32 iX, INT32 iY, UINT16 usIndex, UINT16 *p16BPPPalette ); +BOOLEAN Blt8BPPDataTo16BPPBufferTransShadowZ(UINT16 *pBuffer, UINT32 uiDestPitchBYTES, UINT16 *pZBuffer, UINT16 usZValue, HVOBJECT hSrcVObject, INT32 iX, INT32 iY, UINT16 usIndex, UINT16 *p16BPPPalette, BOOLEAN fIgnoreShadows); +BOOLEAN Blt8BPPDataTo16BPPBufferTransShadowZAlpha(UINT16 *pBuffer, UINT32 uiDestPitchBYTES, UINT16 *pZBuffer, UINT16 usZValue, HVOBJECT hSrcVObject, HVOBJECT hAlphaVObject, INT32 iX, INT32 iY, UINT16 usIndex, UINT16 *p16BPPPalette, BOOLEAN fIgnoreShadows); + +BOOLEAN Blt8BPPDataTo16BPPBufferTransShadowClip(UINT16 *pBuffer, UINT32 uiDestPitchBYTES, HVOBJECT hSrcVObject, INT32 iX, INT32 iY, UINT16 usIndex, SGPRect *clipregion, UINT16 *p16BPPPalette, BOOLEAN fIgnoreShadows); +BOOLEAN Blt8BPPDataTo16BPPBufferTransShadowClipAlpha(UINT16 *pBuffer, UINT32 uiDestPitchBYTES, HVOBJECT hSrcVObject, HVOBJECT hAlphaVObject, INT32 iX, INT32 iY, UINT16 usIndex, SGPRect *clipregion, UINT16 *p16BPPPalette, BOOLEAN fIgnoreShadows); +BOOLEAN Blt8BPPDataTo16BPPBufferTransShadowZNB(UINT16 *pBuffer, UINT32 uiDestPitchBYTES, UINT16 *pZBuffer, UINT16 usZValue, HVOBJECT hSrcVObject, INT32 iX, INT32 iY, UINT16 usIndex, UINT16 *p16BPPPalette, BOOLEAN fIgnoreShadows); +BOOLEAN Blt8BPPDataTo16BPPBufferTransShadowZNBAlpha(UINT16 *pBuffer, UINT32 uiDestPitchBYTES, UINT16 *pZBuffer, UINT16 usZValue, HVOBJECT hSrcVObject, HVOBJECT hAlphaVObject, INT32 iX, INT32 iY, UINT16 usIndex, UINT16 *p16BPPPalette, BOOLEAN fIgnoreShadows); BOOLEAN Blt8BPPDataTo16BPPBufferShadowZNB( UINT16 *pBuffer, UINT32 uiDestPitchBYTES, UINT16 *pZBuffer, UINT16 usZValue, HVOBJECT hSrcVObject, INT32 iX, INT32 iY, UINT16 usIndex ); BOOLEAN Blt8BPPDataTo16BPPBufferShadowZNBClip( UINT16 *pBuffer, UINT32 uiDestPitchBYTES, UINT16 *pZBuffer, UINT16 usZValue, HVOBJECT hSrcVObject, INT32 iX, INT32 iY, UINT16 usIndex, SGPRect *clipregion); BOOLEAN Blt8BPPDataTo16BPPBufferShadowZ( UINT16 *pBuffer, UINT32 uiDestPitchBYTES, UINT16 *pZBuffer, UINT16 usZValue, HVOBJECT hSrcVObject, INT32 iX, INT32 iY, UINT16 usIndex ); BOOLEAN Blt8BPPDataTo16BPPBufferShadowZClip( UINT16 *pBuffer, UINT32 uiDestPitchBYTES, UINT16 *pZBuffer, UINT16 usZValue, HVOBJECT hSrcVObject, INT32 iX, INT32 iY, UINT16 usIndex, SGPRect *clipregion); -BOOLEAN Blt8BPPDataTo16BPPBufferTransShadowZClip( UINT16 *pBuffer, UINT32 uiDestPitchBYTES, UINT16 *pZBuffer, UINT16 usZValue, HVOBJECT hSrcVObject, INT32 iX, INT32 iY, UINT16 usIndex, SGPRect *clipregion, UINT16 *p16BPPPalette); -BOOLEAN Blt8BPPDataTo16BPPBufferTransShadowZNBClip( UINT16 *pBuffer, UINT32 uiDestPitchBYTES, UINT16 *pZBuffer, UINT16 usZValue, HVOBJECT hSrcVObject, INT32 iX, INT32 iY, UINT16 usIndex, SGPRect *clipregion, UINT16 *p16BPPPalette); +BOOLEAN Blt8BPPDataTo16BPPBufferTransShadowZClip(UINT16 *pBuffer, UINT32 uiDestPitchBYTES, UINT16 *pZBuffer, UINT16 usZValue, HVOBJECT hSrcVObject, INT32 iX, INT32 iY, UINT16 usIndex, SGPRect *clipregion, UINT16 *p16BPPPalette, BOOLEAN fIgnoreShadows); +BOOLEAN Blt8BPPDataTo16BPPBufferTransShadowZClipAlpha(UINT16 *pBuffer, UINT32 uiDestPitchBYTES, UINT16 *pZBuffer, UINT16 usZValue, HVOBJECT hSrcVObject, HVOBJECT hAlphaVObject, INT32 iX, INT32 iY, UINT16 usIndex, SGPRect *clipregion, UINT16 *p16BPPPalette, BOOLEAN fIgnoreShadows); +BOOLEAN Blt8BPPDataTo16BPPBufferTransShadowZNBClip(UINT16 *pBuffer, UINT32 uiDestPitchBYTES, UINT16 *pZBuffer, UINT16 usZValue, HVOBJECT hSrcVObject, INT32 iX, INT32 iY, UINT16 usIndex, SGPRect *clipregion, UINT16 *p16BPPPalette, BOOLEAN fIgnoreShadows); +BOOLEAN Blt8BPPDataTo16BPPBufferTransShadowZNBClipAlpha(UINT16 *pBuffer, UINT32 uiDestPitchBYTES, UINT16 *pZBuffer, UINT16 usZValue, HVOBJECT hSrcVObject, HVOBJECT hAlphaVObject, INT32 iX, INT32 iY, UINT16 usIndex, SGPRect *clipregion, UINT16 *p16BPPPalette, BOOLEAN fIgnoreShadows); // Next blitters are for blitting mask as intensity BOOLEAN Blt8BPPDataTo16BPPBufferIntensityZNB( UINT16 *pBuffer, UINT32 uiDestPitchBYTES, UINT16 *pZBuffer, UINT16 usZValue, HVOBJECT hSrcVObject, INT32 iX, INT32 iY, UINT16 usIndex ); @@ -140,7 +148,8 @@ BOOLEAN Blt8BPPDataTo16BPPBufferIntensity( UINT16 *pBuffer, UINT32 uiDestPitchBY BOOLEAN Blt8BPPDataTo16BPPBufferTransparentClip( UINT16 *pBuffer, UINT32 uiDestPitchBYTES, HVOBJECT hSrcVObject, INT32 iX, INT32 iY, UINT16 usIndex, SGPRect *clipregion); BOOLEAN Blt8BPPDataTo16BPPBufferTransparent( UINT16 *pBuffer, UINT32 uiDestPitchBYTES, HVOBJECT hSrcVObject, INT32 iX, INT32 iY, UINT16 usIndex ); -BOOLEAN Blt8BPPDataTo16BPPBufferTransShadow( UINT16 *pBuffer, UINT32 uiDestPitchBYTES, HVOBJECT hSrcVObject, INT32 iX, INT32 iY, UINT16 usIndex, UINT16 *p16BPPPalette ); +BOOLEAN Blt8BPPDataTo16BPPBufferTransShadow(UINT16 *pBuffer, UINT32 uiDestPitchBYTES, HVOBJECT hSrcVObject, INT32 iX, INT32 iY, UINT16 usIndex, UINT16 *p16BPPPalette, BOOLEAN fIgnoreShadows); +BOOLEAN Blt8BPPDataTo16BPPBufferTransShadowAlpha(UINT16 *pBuffer, UINT32 uiDestPitchBYTES, HVOBJECT hSrcVObject, HVOBJECT hAlphaVObject, INT32 iX, INT32 iY, UINT16 usIndex, UINT16 *p16BPPPalette, BOOLEAN fIgnoreShadows); BOOLEAN Blt8BPPDataTo16BPPBufferShadowClip( UINT16 *pBuffer, UINT32 uiDestPitchBYTES, HVOBJECT hSrcVObject, INT32 iX, INT32 iY, UINT16 usIndex, SGPRect *clipregion); BOOLEAN DDBlt8BPPDataTo16BPPBufferShadow( HVOBJECT hDestVObject, HVOBJECT hSrcVObject, UINT8 level, COLORVAL maskrgb, UINT16 usX, UINT16 usY, SGPRect *srcRect); @@ -208,9 +217,12 @@ BOOLEAN Blt8BPPDataTo16BPPBufferOutlineZClip( UINT16 *pBuffer, UINT32 uiDestPitc // ATE: New blitter for included shadow, but pixellate if obscured by z -BOOLEAN Blt8BPPDataTo16BPPBufferTransShadowZNBObscured( UINT16 *pBuffer, UINT32 uiDestPitchBYTES, UINT16 *pZBuffer, UINT16 usZValue, HVOBJECT hSrcVObject, INT32 iX, INT32 iY, UINT16 usIndex, UINT16 *p16BPPPalette ); +BOOLEAN Blt8BPPDataTo16BPPBufferTransShadowZNBObscured(UINT16 *pBuffer, UINT32 uiDestPitchBYTES, UINT16 *pZBuffer, UINT16 usZValue, HVOBJECT hSrcVObject, INT32 iX, INT32 iY, UINT16 usIndex, UINT16 *p16BPPPalette, BOOLEAN fIgnoreShadows = FALSE); +BOOLEAN Blt8BPPDataTo16BPPBufferTransShadowZNBObscuredTest(UINT16 *pBuffer, UINT32 uiDestPitchBYTES, UINT16 *pZBuffer, UINT16 usZValue, HVOBJECT hSrcVObject, INT32 iX, INT32 iY, UINT16 usIndex, UINT16 *p16BPPPalette, BOOLEAN fIgnoreShadows = FALSE); +BOOLEAN Blt8BPPDataTo16BPPBufferTransShadowZNBObscuredAlpha(UINT16 *pBuffer, UINT32 uiDestPitchBYTES, UINT16 *pZBuffer, UINT16 usZValue, HVOBJECT hSrcVObject, HVOBJECT hAlphaVObject, INT32 iX, INT32 iY, UINT16 usIndex, UINT16 *p16BPPPalette, BOOLEAN fIgnoreShadows = FALSE); -BOOLEAN Blt8BPPDataTo16BPPBufferTransShadowZNBObscuredClip( UINT16 *pBuffer, UINT32 uiDestPitchBYTES, UINT16 *pZBuffer, UINT16 usZValue, HVOBJECT hSrcVObject, INT32 iX, INT32 iY, UINT16 usIndex, SGPRect *clipregion, UINT16 *p16BPPPalette ); +BOOLEAN Blt8BPPDataTo16BPPBufferTransShadowZNBObscuredClip(UINT16 *pBuffer, UINT32 uiDestPitchBYTES, UINT16 *pZBuffer, UINT16 usZValue, HVOBJECT hSrcVObject, INT32 iX, INT32 iY, UINT16 usIndex, SGPRect *clipregion, UINT16 *p16BPPPalette, BOOLEAN fIgnoreShadows); +BOOLEAN Blt8BPPDataTo16BPPBufferTransShadowZNBObscuredClipAlpha(UINT16 *pBuffer, UINT32 uiDestPitchBYTES, UINT16 *pZBuffer, UINT16 usZValue, HVOBJECT hSrcVObject, HVOBJECT hAlphaVObject, INT32 iX, INT32 iY, UINT16 usIndex, SGPRect *clipregion, UINT16 *p16BPPPalette, BOOLEAN fIgnoreShadows); BOOLEAN Blt8BPPDataTo16BPPBufferTransZClipPixelateObscured( UINT16 *pBuffer, UINT32 uiDestPitchBYTES, UINT16 *pZBuffer, UINT16 usZValue, HVOBJECT hSrcVObject, INT32 iX, INT32 iY, UINT16 usIndex, SGPRect *clipregion); BOOLEAN Blt8BPPDataTo16BPPBufferTransZPixelateObscured( UINT16 *pBuffer, UINT32 uiDestPitchBYTES, UINT16 *pZBuffer, UINT16 usZValue, HVOBJECT hSrcVObject, INT32 iX, INT32 iY, UINT16 usIndex ); diff --git a/Tactical/LogicalBodyTypes/AbstractXMLLoader.cpp b/Tactical/LogicalBodyTypes/AbstractXMLLoader.cpp new file mode 100644 index 00000000..c1eb1ea4 --- /dev/null +++ b/Tactical/LogicalBodyTypes/AbstractXMLLoader.cpp @@ -0,0 +1,212 @@ +#include "AbstractXMLLoader.h" + +namespace LogicalBodyTypes { + + AbstractXMLLoader::AbstractXMLLoader(XML_StartElementHandler startHandler, XML_EndElementHandler endHandler, XML_CharacterDataHandler charHandler, ParseDataFactoryFunc parseDataFactF) { + startElementHandler = startHandler; + endElementHandler = endHandler; + characterDataHandler = charHandler; + parseDataFactFuncPntr = parseDataFactF; +} + +AbstractXMLLoader::~AbstractXMLLoader(void) { +} + +AbstractXMLLoader::ParseData::ParseData(XML_Parser* parser) { + pParser = parser; + state = E_NONE; + level = 0; + szCharData[0] = '\0'; + szErrorTxt[0] = '\0'; +} + +AbstractXMLLoader::ParseData* AbstractXMLLoader::MakeParseData(XML_Parser* parser) { + return new ParseData(parser); +} + +bool AbstractXMLLoader::LoadFromFile(const char* directoryName, const char* fileName) { + HWFILE hFile; + UINT32 uiBytesRead; + UINT32 uiFSize; + CHAR8* lpcBuffer; + char fileNameFull[MAX_PATH + 1]; + if (strlen(fileName) + strlen(directoryName) >= MAX_PATH) { + LiveMessage("Can't load file. Concatinated filename too long for buffer!"); + return false; + } + SetDirectoryName(directoryName); + SetFileName(fileName); + strcpy(fileNameFull, directoryName); + strcat(fileNameFull, fileName); + XML_Parser parser = XML_ParserCreate(NULL); + AbstractXMLLoader::ParseData* data = parseDataFactFuncPntr(&parser); + + std::string msg = "Loading "; + msg += fileName; + DebugMsg(TOPIC_JA2, DBG_LEVEL_3, msg.c_str()); + hFile = FileOpen(fileNameFull, FILE_ACCESS_READ, FALSE); + if (!hFile) { + delete data; + return false; + } + uiFSize = FileGetSize(hFile); + lpcBuffer = (CHAR8*)MemAlloc(uiFSize + 1); + if (!FileRead(hFile, lpcBuffer, uiFSize, &uiBytesRead)) { + MemFree(lpcBuffer); + delete data; + return false; + } + lpcBuffer[uiFSize] = 0; + FileClose(hFile); + + ExternalEntityArgs eeArgs; + eeArgs.directoryName = directoryName; + eeArgs.fileName = fileName; + eeArgs.pParser = &parser; + + XML_SetElementHandler(parser, startElementHandler, endElementHandler); + XML_SetCharacterDataHandler(parser, characterDataHandler); + XML_SetUserData(parser, data); + XML_SetExternalEntityRefHandler(parser, ExternalEntityHandler); + XML_SetExternalEntityRefHandlerArg(parser, (void*)&eeArgs); + + try { + if (!XML_Parse(parser, lpcBuffer, uiFSize, TRUE)) { + CHAR8 errorBuf[512]; + sprintf(errorBuf, "XML Parser Error in %s[%d]: %s", fileNameFull, XML_GetCurrentLineNumber(parser), XML_ErrorString(XML_GetErrorCode(parser))); + LiveMessage(errorBuf); + MemFree(lpcBuffer); + delete data; + return false; + } + } catch (XMLParseException e) { + CHAR8 errorBuf[512]; + sprintf(errorBuf, "XML Parser Exception in %s[%d]: %s", fileNameFull, e._LINE, e.what()); + LiveMessage(errorBuf); + MemFree(lpcBuffer); + XML_ParserFree(parser); + delete data; + return false; + } + MemFree(lpcBuffer); + XML_ParserFree(parser); + delete data; + return true; +} + +int XMLCALL AbstractXMLLoader::ExternalEntityHandler(XML_Parser args, const XML_Char* context, const XML_Char* base, const XML_Char* systemId, const XML_Char* publicId) { + ExternalEntityArgs* eArgs = (ExternalEntityArgs*)args; + char fileNameFull[MAX_PATH + 1]; + UINT32 uiBytesRead; + UINT32 uiFSize; + CHAR8* lpcBuffer; + HWFILE hFile; + if (strlen(eArgs->directoryName) + strlen(systemId) >= MAX_PATH) { + LiveMessage("Can't load file specified in external entity. Concatinated filename too long for buffer!"); + return XML_STATUS_ERROR; + } + strcpy(fileNameFull, eArgs->directoryName); + strcat(fileNameFull, systemId); + + hFile = FileOpen(fileNameFull, FILE_ACCESS_READ, FALSE); + if (!hFile) { + LiveMessage("File specified in external entity can't be opened!"); + return XML_STATUS_ERROR; + } + uiFSize = FileGetSize(hFile); + lpcBuffer = (CHAR8*)MemAlloc(uiFSize + 1); + if (!FileRead(hFile, lpcBuffer, uiFSize, &uiBytesRead)) { + LiveMessage("File specified in external entity couldn't be read!"); + MemFree(lpcBuffer); + return XML_STATUS_ERROR; + } + lpcBuffer[uiFSize] = 0; + FileClose(hFile); + + XML_Parser extParser = XML_ExternalEntityParserCreate(*eArgs->pParser, context, NULL); + ParseData* data = (ParseData*)XML_GetUserData(*eArgs->pParser); + data->pParser = &extParser; + try { + if (!XML_Parse(extParser, lpcBuffer, uiFSize, TRUE)) { + CHAR8 errorBuf[512]; + sprintf(errorBuf, "XML Parser Error in external entity %s[%d]: %s", systemId, XML_GetCurrentLineNumber(extParser), XML_ErrorString(XML_GetErrorCode(extParser))); + LiveMessage(errorBuf); + return XML_STATUS_ERROR; + } + } catch (XMLParseException e) { + CHAR8 errorBuf[512]; + sprintf(errorBuf, "XML Parser Exception in external entity %s[%d]: %s", systemId, e._LINE, e.what()); + LiveMessage(errorBuf); + XML_ParserFree(extParser); + return XML_STATUS_ERROR; + } + data->pParser = eArgs->pParser; + XML_ParserFree(extParser); + return XML_STATUS_OK; +}; + + +const char* AbstractXMLLoader::GetFileName() { + return fileName; +} + +const char* AbstractXMLLoader::GetDirectoryName() { + return directoryName; +} + +void AbstractXMLLoader::SetFileName(const char* fileName) { + strcpy(this->fileName, fileName); +} + +void AbstractXMLLoader::SetDirectoryName(const char* directoryName) { + strcpy(this->directoryName, directoryName); +} + +const XML_Char* AbstractXMLLoader::GetAttribute(const XML_Char* name, const XML_Char** atts) { + for (const XML_Char** pIter = atts; *pIter != NULL; pIter++) { + const XML_Char* key = *pIter++; + if (strcmp(key, name) == 0) return *pIter; + } + return NULL; +} + +bool AbstractXMLLoader::ConvertStringToINT8(const XML_Char* num, INT8* int8) { + long l = strtol(num, NULL, 10); + if (l > 127 || l < -128) return false; + if (l == 0 && strcmp(num, "0") != 0) return false; + *int8 = (INT8)l; + return true; +} + +bool AbstractXMLLoader::ConvertStringToUINT8(const XML_Char* num, UINT8* uInt8) { + unsigned long ul = strtoul(num, NULL, 10); + if (ul > 255) return false; + if (ul == 0 && strcmp(num, "0") != 0) return false; + *uInt8 = (UINT8)ul; + return true; +} + +bool AbstractXMLLoader::ConvertStringToINT32(const XML_Char* num, INT32* int32) { + long l = strtol(num, NULL, 10); + // TODO: add range checks also for long types (and use the defined macros) + // TODO: string should be trimmed (other convert functions also) + if (l == 0 && strcmp(num, "0") != 0) return false; + *int32 = (INT32)l; + return true; +} + +bool AbstractXMLLoader::ConvertStringToUINT32(const XML_Char* num, UINT32* uInt32) { + unsigned long ul = strtoul(num, NULL, 10); + if (ul == 0 && strcmp(num, "0") != 0) return false; + *uInt32 = ul; + return true; +} + +bool AbstractXMLLoader::ConvertStringToBOOLEAN(const XML_Char* num, BOOLEAN* fBoolean) { + unsigned long ul = strtoul(num, NULL, 10); + if (ul == 0 && strcmp(num, "0") != 0) return false; + *fBoolean = ul != 0; + return true; +} + +} diff --git a/Tactical/LogicalBodyTypes/AbstractXMLLoader.h b/Tactical/LogicalBodyTypes/AbstractXMLLoader.h new file mode 100644 index 00000000..765c127b --- /dev/null +++ b/Tactical/LogicalBodyTypes/AbstractXMLLoader.h @@ -0,0 +1,84 @@ +#pragma once + +#ifndef _LBT_ABSTRACTXMLLOADER__H_ +#define _LBT_ABSTRACTXMLLOADER__H_ + +#include +#include +#include "expat.h" +#include "Types.h" +#include "XML.h" +#include "TopicIDs.h" +#include "TopicOps.h" +#include "DEBUG.H" +#include "FileMan.h" +#include "MemMan.h" +#include "Debug Control.h" +#include "Sys Globals.h" +#include "LogicalBodyTypes/Singleton.h" +#include "LogicalBodyTypes/XMLParseException.h" + +namespace LogicalBodyTypes { + +class AbstractXMLLoader : public ISingleton +{ + +protected: + enum ParseState { + E_NONE, + FIRST_SUBCLASS_STATE + }; + class ParseData { + public: + ParseData(XML_Parser* parser = NULL); + XML_Parser* pParser; + int state; // we sacrifice type safety for the enumerators so subclasses can define their own states + UINT32 level; + CHAR8 szCharData[MAX_CHAR_DATA_LENGTH + 1]; + CHAR8 szErrorTxt[MAX_PATH + 1]; + } typedef ParseData; + struct ExternalEntityArgs { + const char* directoryName; + const char* fileName; + XML_Parser* pParser; + } typedef ExternalEntityArgs; + typedef ParseData* (*ParseDataFactoryFunc) (XML_Parser* parser); + +private: + XML_StartElementHandler startElementHandler; + XML_EndElementHandler endElementHandler; + XML_CharacterDataHandler characterDataHandler; + ParseDataFactoryFunc parseDataFactFuncPntr; + char directoryName[MAX_PATH + 1]; + char fileName[MAX_PATH + 1]; + +public: + AbstractXMLLoader(XML_StartElementHandler startHandler, XML_EndElementHandler endHandler, XML_CharacterDataHandler charHandler, ParseDataFactoryFunc parseDataFactF = MakeParseData); + ~AbstractXMLLoader(void); + bool LoadFromFile(const char* directoryName, const char* fileName); + const char* GetFileName(); + const char* GetDirectoryName(); + void SetFileName(const char* fileName); + void SetDirectoryName(const char* directoryName); + +protected: + static const XML_Char* GetAttribute(const XML_Char* name, const XML_Char** atts); + static bool ConvertStringToINT8(const XML_Char* num, INT8* uInt8); + static bool ConvertStringToUINT8(const XML_Char* num, UINT8* uInt8); + static bool ConvertStringToINT32(const XML_Char* num, INT32* int32); + static bool ConvertStringToUINT32(const XML_Char* num, UINT32* uInt32); + static bool ConvertStringToBOOLEAN(const XML_Char* num, BOOLEAN* fBoolean); + static ParseData* MakeParseData(XML_Parser* parser); + +private: + static AbstractXMLLoader& Instance(); + static void XMLCALL StartElementHandle(void* userData, const XML_Char* name, const XML_Char** atts); + static void XMLCALL EndElementHandle(void* userData, const XML_Char* name); + static void XMLCALL CharacterDataHandle(void* userData, const XML_Char* str, int len); + static int XMLCALL ExternalEntityHandler(XML_Parser args, const XML_Char *context, const XML_Char *base, const XML_Char *systemId, const XML_Char *publicId); + +}; + +} + +#endif diff --git a/Tactical/LogicalBodyTypes/BodyType.cpp b/Tactical/LogicalBodyTypes/BodyType.cpp new file mode 100644 index 00000000..c4f9b122 --- /dev/null +++ b/Tactical/LogicalBodyTypes/BodyType.cpp @@ -0,0 +1,59 @@ +#include "BodyType.h" + +namespace LogicalBodyTypes { + +BodyType::BodyType(UINT32 cacheSize, Filter* filterP) { + filter = filterP; + hasSurfaces = false; + cache = new SurfaceCache(cacheSize); + animstates.resize(NUMANIMATIONSTATES); + physAnimSurfaces.resize(NUMANIMATIONSURFACETYPES); + for (int i = 0; i < NUMANIMATIONSTATES; i++) { + animstates[i].resize(Layers::Instance().GetCount()); + } + for (int i = 0; i < NUMANIMATIONSURFACETYPES; i++) { + physAnimSurfaces[i].resize(Layers::Instance().GetCount()); + } + // initialize body type specific layer properties with the layer specific layer properties. + Layers::LayerPropertiesVector::size_type numLayers = Layers::Instance().GetCount(); + layerProperties.resize(numLayers); + for (Layers::LayerPropertiesVector::size_type layer = 0; layer < numLayers; layer++) { + layerProperties[layer] = Layers::Instance().GetLayerProperties(layer); + } +} + +BodyType::~BodyType(void) { + delete cache; +} + +void BodyType::AddSurfaceForAnimState(UINT16 usAnimState, Layers::LayerPropertiesVector::size_type layer, AnimationSurfaceType* animSurfaceType, AnimationSurfaceType* alphaSurfaceType, Filter* filter, PaletteTable* paletteTable) { + STRUCTURE_FILE_REF* pStructFile = SurfaceDB::Instance().GetStructFile(animSurfaceType); + UINT32 idx = cache->AddSurface(animSurfaceType, pStructFile); + UINT32 idxAlpha = 0; + if (alphaSurfaceType != NULL) { + idxAlpha = cache->AddSurface(alphaSurfaceType, pStructFile); + } + animstates[usAnimState][layer].push_back(FilterSurfaceTypePair(filter, FilterSurfaceTypePair::second_type(idx, LogicalSurfaceType(animSurfaceType, alphaSurfaceType, idxAlpha, paletteTable)))); + hasSurfaces = true; +} + +void BodyType::AddSurfaceForPhysSurface(UINT16 usAnimSurface, Layers::LayerPropertiesVector::size_type layer, AnimationSurfaceType* animSurfaceType, AnimationSurfaceType* alphaSurfaceType, Filter* filter, PaletteTable* paletteTable) { + STRUCTURE_FILE_REF* pStructFile = SurfaceDB::Instance().GetStructFile(animSurfaceType); + UINT32 idx = cache->AddSurface(animSurfaceType, pStructFile); + UINT32 idxAlpha = 0; + if (alphaSurfaceType != NULL) { + idxAlpha = cache->AddSurface(alphaSurfaceType, pStructFile); + } + physAnimSurfaces[usAnimSurface][layer].push_back(FilterSurfaceTypePair(filter, FilterSurfaceTypePair::second_type(idx, LogicalSurfaceType(animSurfaceType, alphaSurfaceType, idxAlpha, paletteTable)))); + hasSurfaces = true; +} + +void BodyType::SetLayerProperties(Layers::LayerPropertiesVector::size_type index, Layers::LayerProperties properties) { + layerProperties[index] = properties; // TODO range check? +} + +const Layers::LayerProperties* BodyType::GetLayerProperties(Layers::LayerPropertiesVector::size_type index) { + return &layerProperties[index]; // TODO range check? +} + +} diff --git a/Tactical/LogicalBodyTypes/BodyType.h b/Tactical/LogicalBodyTypes/BodyType.h new file mode 100644 index 00000000..edb40f34 --- /dev/null +++ b/Tactical/LogicalBodyTypes/BodyType.h @@ -0,0 +1,107 @@ +#pragma once + +#ifndef _LBT_BODYTYPE__H_ +#define _LBT_BODYTYPE__H_ + +#include "LogicalBodyTypes/Layers.h" +#include "LogicalBodyTypes/Filter.h" +#include "LogicalBodyTypes/SurfaceCache.h" +#include "LogicalBodyTypes/SurfaceDB.h" +#include "LogicalBodyTypes/PaletteDB.h" +#include "LogicalBodyTypes/PaletteTable.h" +#include "Animation Data.h" +#include "Animation Control.h" + +namespace LogicalBodyTypes { + +class BodyType { + +public: + struct LogicalSurfaceType { + LogicalSurfaceType(AnimationSurfaceType* physicalSurfaceType, AnimationSurfaceType* alphaSurfaceType, UINT32 alphaSurfaceIdx, PaletteTable* paletteTable) + : paletteTable(paletteTable), physicalSurfaceType(physicalSurfaceType), alphaSurfaceType(alphaSurfaceType), alphaSurfaceIdx(alphaSurfaceIdx) {}; + const PaletteTable* paletteTable; + const AnimationSurfaceType* physicalSurfaceType; + const AnimationSurfaceType* alphaSurfaceType; + UINT32 alphaSurfaceIdx; + } typedef LogicalSurfaceType; + +private: + typedef std::pair > FilterSurfaceTypePair; + typedef std::list FilterSurfaceTypeList; + typedef std::vector LayerVector; + typedef std::vector AnimStateVector; + typedef std::vector PhysAnimSurfaceVector; + AnimStateVector animstates; + PhysAnimSurfaceVector physAnimSurfaces; + Layers::LayerPropertiesVector layerProperties; + Filter* filter; + bool hasSurfaces; + UINT32 numCacheNodes; + UINT32 maxCacheNodes; + SurfaceCache* cache; + +public: + BodyType(UINT32 cacheSize, Filter* filterP = NULL); + ~BodyType(void); + void AddSurfaceForAnimState(UINT16 usAnimState, Layers::LayerPropertiesVector::size_type layer, AnimationSurfaceType* animSurfaceType, AnimationSurfaceType* alphaSurfaceType = NULL, Filter* filter = NULL, PaletteTable* paletteTable = NULL); + void AddSurfaceForPhysSurface(UINT16 usAnimSurface, Layers::LayerPropertiesVector::size_type layer, AnimationSurfaceType* animSurfaceType, AnimationSurfaceType* alphaSurfaceType = NULL, Filter* filter = NULL, PaletteTable* paletteTable = NULL); + void SetLayerProperties(Layers::LayerPropertiesVector::size_type index, Layers::LayerProperties properties); + const Layers::LayerProperties* GetLayerProperties(Layers::LayerPropertiesVector::size_type index); + + inline bool Match(SOLDIERTYPE* pSoldier) { + if (filter != NULL) return filter->Match(pSoldier); + return false; // no filter specified - matches none + }; + + inline bool HasSurfaces() { + return hasSurfaces; + } + + inline BodyType::LogicalSurfaceType* GetLogicalSurfaceType(Layers::LayerPropertiesVector::size_type layer, SOLDIERTYPE* pSoldier) { + FilterSurfaceTypeList::iterator end = animstates[pSoldier->usAnimState][layer].end(); + for (FilterSurfaceTypeList::iterator i = animstates[pSoldier->usAnimState][layer].begin(); i != end; i++) { + Filter* f = (*i).first; + if (f != NULL) { + if (f->Match(pSoldier)) { + bool isLoaded = cache->GetLoadedSurface((*i).second.first) != NULL; + if ((*i).second.second.alphaSurfaceType != NULL) { + isLoaded = isLoaded && (cache->GetLoadedSurface((*i).second.second.alphaSurfaceIdx) != NULL); + } + return (isLoaded) ? &(*i).second.second : NULL; + } + } else { // no filter specified - matches all + bool isLoaded = cache->GetLoadedSurface((*i).second.first) != NULL; + if ((*i).second.second.alphaSurfaceType != NULL) { + isLoaded = isLoaded && (cache->GetLoadedSurface((*i).second.second.alphaSurfaceIdx) != NULL); + } + return (isLoaded) ? &(*i).second.second : NULL; + } + } + end = physAnimSurfaces[pSoldier->usAnimSurface][layer].end(); + for (FilterSurfaceTypeList::iterator i = physAnimSurfaces[pSoldier->usAnimSurface][layer].begin(); i != end; i++) { + Filter* f = (*i).first; + if (f != NULL) { + if (f->Match(pSoldier)) { + bool isLoaded = cache->GetLoadedSurface((*i).second.first) != NULL; + if ((*i).second.second.alphaSurfaceType != NULL) { + isLoaded = isLoaded && (cache->GetLoadedSurface((*i).second.second.alphaSurfaceIdx) != NULL); + } + return (isLoaded) ? &(*i).second.second : NULL; + } + } else { // no filter specified - matches all + bool isLoaded = cache->GetLoadedSurface((*i).second.first) != NULL; + if ((*i).second.second.alphaSurfaceType != NULL) { + isLoaded = isLoaded && (cache->GetLoadedSurface((*i).second.second.alphaSurfaceIdx) != NULL); + } + return (isLoaded) ? &(*i).second.second : NULL; + } + } + return NULL; + }; + +}; + +} + +#endif diff --git a/Tactical/LogicalBodyTypes/BodyTypeDB.cpp b/Tactical/LogicalBodyTypes/BodyTypeDB.cpp new file mode 100644 index 00000000..a4703993 --- /dev/null +++ b/Tactical/LogicalBodyTypes/BodyTypeDB.cpp @@ -0,0 +1,1096 @@ +#include "BodyTypeDB.h" + +namespace LogicalBodyTypes { + + BodyTypeDB::BodyTypeDB(void) : AbstractXMLLoader(StartElementHandle, EndElementHandle, CharacterDataHandle, MakeParseData) { + RegisterEnumerators(); + } + + BodyTypeDB::~BodyTypeDB(void) { + for (BodyTypeList::iterator i = bodyTypes.begin(); i != bodyTypes.end(); i++) { + delete *i; + } + } + + void BodyTypeDB::Add(BodyType* bodyType) { + bodyTypes.push_back(bodyType); + } + + AbstractXMLLoader::ParseData* BodyTypeDB::MakeParseData(XML_Parser* parser) { + return new ParseData(parser); + } + + void BodyTypeDB::StartElementHandle(void* userData, const XML_Char* name, const XML_Char** atts) { + ParseData* data = (ParseData*)userData; + switch (data->state) { + case E_NONE: + if (strcmp(name, "LogicalBodyTypes") == 0) { + data->state = E_ELEMENT_BODYTYPES; + break; + } + case E_ELEMENT_BODYTYPES: + if (strcmp(name, "LogicalBodyType") == 0) { + data->state = E_ELEMENT_BODYTYPE; + XML_Char const* filterIdent = GetAttribute("filter", atts); + XML_Char const* cacheSize = GetAttribute("cachesize", atts); + Filter* f = NULL; + if (filterIdent != NULL && strcmp(filterIdent, "") != 0) { + f = FilterDB::Instance().FindFilter(filterIdent); + if (f == NULL) throw XMLParseException("Unknown filter specified!", name, data->pParser); + } + UINT32 size = 16; + if (cacheSize != NULL) { + if (!ConvertStringToUINT32(cacheSize, &size)) throw XMLParseException("Attribute 'value' doesn't have a valid value!", name, data->pParser); + if (size < 2) throw XMLParseException("Minimum cache size is 2!", name, data->pParser); + } + data->currentBodyType = new BodyType(size, f); + data->layerPropertiesConfig.clear(); + break; + } + case E_ELEMENT_BODYTYPE: + if (strcmp(name, "LayerConfigurations") == 0) { + data->state = E_ELEMENT_LAYER_CONFIGS; + break; + } + if (strcmp(name, "LogicalAnimationSurfaces") == 0) { + data->state = E_ELEMENT_SURFACES; + break; + } + case E_ELEMENT_LAYER_CONFIGS: + if (strcmp(name, "LayerConfiguration") == 0) { + data->state = E_ELEMENT_LAYER_CONFIG; + XML_Char const* aName = GetAttribute("name", atts); + XML_Char const* aRender = GetAttribute("render", atts); + XML_Char const* aShadow = GetAttribute("shadow", atts); + if (aName == NULL) { + throw XMLParseException("Mandatory attribute missing!", name, data->pParser); + } + std::string strLayer = aName; + Layers::LayerPropertiesVector::size_type layer = Layers::Instance().GetIndex(strLayer); + if (layer == -1) throw XMLParseException("Unknown layer specified!", name, data->pParser); + Layers::LayerProperties temp = Layers::Instance().GetLayerProperties(layer); // copy default configuration for layer + if (aRender != NULL) { + BOOLEAN fRender; + if (!ConvertStringToBOOLEAN(aRender, &fRender)) throw XMLParseException("Attribute 'value' doesn't have a valid value!", name, data->pParser); + temp.render = fRender == TRUE; + + } + if (aShadow != NULL) { + BOOLEAN fShadow; + if (!ConvertStringToBOOLEAN(aShadow, &fShadow)) throw XMLParseException("Attribute 'value' doesn't have a valid value!", name, data->pParser); + temp.renderShadows = fShadow == TRUE; + } + data->layerPropertiesConfig[layer] = temp; + break; + } + case E_ELEMENT_SURFACES: + if (strcmp(name, "Layer") == 0) { + data->state = E_ELEMENT_LAYER; + XML_Char const* aLayer = GetAttribute("name", atts); + if (aLayer == NULL) { + throw XMLParseException("Mandatory attribute missing!", name, data->pParser); + } + std::string strLayer = aLayer; + data->layer = Layers::Instance().GetIndex(strLayer); + if (data->layer == -1) throw XMLParseException("Unknown layer specified!", name, data->pParser); + break; + } + case E_ELEMENT_LAYER: + if (strcmp(name, "LayerProp") == 0) { + data->state = E_ELEMENT_PROP; + XML_Char const* aFilter = GetAttribute("filter", atts); + XML_Char const* aPalette = GetAttribute("palette", atts); + data->filter = NULL; + data->paletteTable = NULL; + if (aFilter != NULL && strcmp(aFilter, "") != 0) { + data->filter = FilterDB::Instance().FindFilter(aFilter); + if (data->filter == NULL) throw XMLParseException("Unknown filter specified!", name, data->pParser); + } + if (aPalette != NULL && strcmp(aFilter, "") != 0 && strcmp(aFilter, "default") != 0) { + data->paletteTable = PaletteDB::Instance().FindPaletteTable(aPalette); + if (data->paletteTable == NULL) throw XMLParseException("Unknown palette specified!", name, data->pParser); + } + break; + } + case E_ELEMENT_PROP: + if (strcmp(name, "Surface") == 0) { + data->state = E_ELEMENT_SURFACE; + XML_Char const* aSurface = GetAttribute("name", atts); + XML_Char const* aAnimState = GetAttribute("animstate", atts); + XML_Char const* aPhysSurface = GetAttribute("animsurface", atts); + if (aSurface == NULL || (aAnimState == NULL && aPhysSurface == NULL)) { + throw XMLParseException("Mandatory attribute missing!", name, data->pParser); + } + if (aAnimState == NULL && aPhysSurface == NULL) { + // we could allow this + // but we should than make 2 seperate animation surface type instances (that are equivalent) which is not nice + // we could use the same instance, but it has to bee ascertained that the cache can handle it first! + throw XMLParseException("Only one attribute of animstate and animsurface may be specified!!", name, data->pParser); + } + AnimationSurfaceType* surface = SurfaceDB::Instance().GetAnimSurfaceType(aSurface); + std::string nameAlpha = aSurface; + nameAlpha += "###ALPHA"; + AnimationSurfaceType* surfaceAlpha = SurfaceDB::Instance().GetAnimSurfaceType(nameAlpha.c_str()); + if (surface == NULL) throw XMLParseException("Unknown animation surface specified!", name, data->pParser); + if (aAnimState != NULL) { + int iAnimState; + if (!EnumeratorDB::Instance().GetEnumeratorByStr("AnimationStates", aAnimState, iAnimState)) { + throw XMLParseException("Unknown animation state specified!", name, data->pParser); + } + data->currentBodyType->AddSurfaceForAnimState(iAnimState, data->layer, surface, surfaceAlpha, data->filter, data->paletteTable); + } + if (aPhysSurface != NULL) { + int iAnimSurface; + if (!EnumeratorDB::Instance().GetEnumeratorByStr("AnimationSurfaces", aPhysSurface, iAnimSurface)) { + throw XMLParseException("Unknown animation surface specified!", name, data->pParser); + } + data->currentBodyType->AddSurfaceForPhysSurface(iAnimSurface, data->layer, surface, surfaceAlpha, data->filter, data->paletteTable); + } + break; + } + default: + throw XMLParseException("Unexpected element!", name, data->pParser); + } + } + + void BodyTypeDB::EndElementHandle(void* userData, const XML_Char* name) { + ParseData* data = (ParseData*)userData; + switch (data->state) { + case E_ELEMENT_SURFACE: + if (strcmp(name, "Surface") == 0) { + data->state = E_ELEMENT_PROP; + break; + } + case E_ELEMENT_PROP: + if (strcmp(name, "LayerProp") == 0) { + data->state = E_ELEMENT_LAYER; + break; + } + case E_ELEMENT_LAYER: + if (strcmp(name, "Layer") == 0) { + data->state = E_ELEMENT_SURFACES; + break; + } + case E_ELEMENT_SURFACES: + if (strcmp(name, "LogicalAnimationSurfaces") == 0) { + data->state = E_ELEMENT_BODYTYPE; + break; + } + case E_ELEMENT_LAYER_CONFIG: + if (strcmp(name, "LayerConfiguration") == 0) { + data->state = E_ELEMENT_LAYER_CONFIGS; + break; + } + case E_ELEMENT_LAYER_CONFIGS: + if (strcmp(name, "LayerConfigurations") == 0) { + data->state = E_ELEMENT_BODYTYPE; + break; + } + case E_ELEMENT_BODYTYPE: + if (strcmp(name, "LogicalBodyType") == 0) { + data->state = E_ELEMENT_BODYTYPES; + std::map::iterator i = data->layerPropertiesConfig.begin(); + for (; i != data->layerPropertiesConfig.end(); i++) { + data->currentBodyType->SetLayerProperties(i->first, i->second); + } + BodyTypeDB::Instance().Add(data->currentBodyType); + data->currentBodyType = NULL; // in case an exception is raised between here and the start of the next bodytype element + break; + } + case E_ELEMENT_BODYTYPES: + if (strcmp(name, "LogicalBodyTypes") == 0) { + data->state = E_NONE; + break; + } + default: + throw XMLParseException("Unexpected element! Closing tag missing?", name, data->pParser); + return; + } + } + + void BodyTypeDB::CharacterDataHandle(void* userData, const XML_Char* str, int len) { + } + + void BodyTypeDB::RegisterEnumerators() { + + /***************************************** + Animation states + ******************************************/ + LOGBT_ENUMDB_ADD("AnimationStates", NUMANIMATIONSTATES, + WALKING, + STANDING, + KNEEL_DOWN, + CROUCHING, + KNEEL_UP, + SWATTING, + RUNNING, + PRONE_DOWN, + CRAWLING, + PRONE_UP, + PRONE, + READY_RIFLE_STAND, + AIM_RIFLE_STAND, + SHOOT_RIFLE_STAND, + END_RIFLE_STAND, + START_SWAT, + END_SWAT, + FLYBACK_HIT, + READY_RIFLE_PRONE, + AIM_RIFLE_PRONE, + SHOOT_RIFLE_PRONE, + END_RIFLE_PRONE, + FALLBACK_DEATHTWICH, + GENERIC_HIT_STAND, + FLYBACK_HIT_BLOOD_STAND, + FLYBACK_HIT_DEATH, + READY_RIFLE_CROUCH, + AIM_RIFLE_CROUCH, + SHOOT_RIFLE_CROUCH, + END_RIFLE_CROUCH, + FALLBACK_HIT_STAND, + ROLLOVER, + CLIMBUPROOF, + FALLOFF, + GETUP_FROM_ROLLOVER, + CLIMBDOWNROOF, + FALLFORWARD_ROOF, + GENERIC_HIT_DEATHTWITCHNB, + GENERIC_HIT_DEATHTWITCHB, + FALLBACK_HIT_DEATHTWITCHNB, + FALLBACK_HIT_DEATHTWITCHB, + GENERIC_HIT_DEATH, + FALLBACK_HIT_DEATH, + GENERIC_HIT_CROUCH, + STANDING_BURST, + STANDING_BURST_HIT, + FALLFORWARD_FROMHIT_STAND, + FALLFORWARD_FROMHIT_CROUCH, + ENDFALLFORWARD_FROMHIT_CROUCH, + GENERIC_HIT_PRONE, + PRONE_HIT_DEATH, + PRONE_LAY_FROMHIT, + PRONE_HIT_DEATHTWITCHNB, + PRONE_HIT_DEATHTWITCHB, + ADULTMONSTER_BREATHING, + ADULTMONSTER_WALKING, + ADULTMONSTER_ATTACKING, + FLYBACK_HITDEATH_STOP, + FALLFORWARD_HITDEATH_STOP, + FALLBACK_HITDEATH_STOP, + PRONE_HITDEATH_STOP, + FLYBACKHIT_STOP, + FALLBACKHIT_STOP, + FALLOFF_STOP, + FALLOFF_FORWARD_STOP, + STAND_FALLFORWARD_STOP, + PRONE_LAYFROMHIT_STOP, + HOPFENCE, + ADULTMONSTER_HIT, + ADULTMONSTER_DYING, + ADULTMONSTER_DYING_STOP, + PUNCH_BREATH, + PUNCH, + NOTHING_STAND, + JFK_HITDEATH, + JFK_HITDEATH_STOP, + JFK_HITDEATH_TWITCHB, + FIRE_STAND_BURST_SPREAD, + FALLOFF_DEATH, + FALLOFF_DEATH_STOP, + FALLOFF_TWITCHB, + FALLOFF_TWITCHNB, + FALLOFF_FORWARD_DEATH, + FALLOFF_FORWARD_DEATH_STOP, + FALLOFF_FORWARD_TWITCHB, + FALLOFF_FORWARD_TWITCHNB, + OPEN_DOOR, + OPEN_STRUCT, + PICKUP_ITEM, + DROP_ITEM, + SLICE, + STAB, + CROUCH_STAB, + START_AID, + GIVING_AID, + END_AID, + DODGE_ONE, + FATCIV_ASS_SCRATCH, + READY_DUAL_STAND, + AIM_DUAL_STAND, + SHOOT_DUAL_STAND, + END_DUAL_STAND, + RAISE_RIFLE, + LOWER_RIFLE, + BODYEXPLODING, + THROW_ITEM, + LOB_ITEM, + QUEEN_MONSTER_BREATHING, + CROUCHED_BURST, + PRONE_BURST, + NOTUSEDANIM1, + BIGBUY_FLEX, + BIGBUY_STRECH, + BIGBUY_SHOEDUST, + BIGBUY_HEADTURN, + MINIGIRL_STOCKING, + GIVE_ITEM, + CLIMB_CLIFF, + COW_EATING, + COW_HIT, + COW_DYING, + COW_DYING_STOP, + WATER_HIT, + WATER_DIE, + WATER_DIE_STOP, + CROW_WALK, + CROW_TAKEOFF, + CROW_LAND, + CROW_FLY, + CROW_EAT, + HELIDROP, + FEM_CLEAN, + FEM_KICKSN, + FEM_LOOK, + FEM_WIPE, + REG_SQUISH, + REG_PULL, + REG_SPIT, + HATKID_YOYO, + KID_ARMPIT, + MONSTER_CLOSE_ATTACK, + MONSTER_SPIT_ATTACK, + MONSTER_BEGIN_EATTING_FLESH, + MONSTER_EATTING_FLESH, + MONSTER_END_EATTING_FLESH, + BLOODCAT_RUN, + BLOODCAT_STARTREADY, + BLOODCAT_READY, + BLOODCAT_ENDREADY, + BLOODCAT_HIT, + BLOODCAT_DYING, + BLOODCAT_DYING_STOP, + BLOODCAT_SWIPE, + NINJA_GOTOBREATH, + NINJA_BREATH, + NINJA_LOWKICK, + NINJA_PUNCH, + NINJA_SPINKICK, + END_OPEN_DOOR, + END_OPEN_LOCKED_DOOR, + KICK_DOOR, + CLOSE_DOOR, + RIFLE_STAND_HIT, + DEEP_WATER_TRED, + DEEP_WATER_SWIM, + DEEP_WATER_HIT, + DEEP_WATER_DIE, + DEEP_WATER_DIE_STOPPING, + DEEP_WATER_DIE_STOP, + LOW_TO_DEEP_WATER, + DEEP_TO_LOW_WATER, + GOTO_SLEEP, + SLEEPING, + WKAEUP_FROM_SLEEP, + FIRE_LOW_STAND, + FIRE_BURST_LOW_STAND, + LARVAE_BREATH, + LARVAE_HIT, + LARVAE_DIE, + LARVAE_DIE_STOP, + LARVAE_WALK, + INFANT_HIT, + INFANT_DIE, + INFANT_DIE_STOP, + INFANT_ATTACK, + INFANT_BEGIN_EATTING_FLESH, + INFANT_EATTING_FLESH, + INFANT_END_EATTING_FLESH, + MONSTER_UP, + MONSTER_JUMP, + STANDING_SHOOT_UNJAM, + CROUCH_SHOOT_UNJAM, + PRONE_SHOOT_UNJAM, + STANDING_SHOOT_DWEL_UNJAM, + STANDING_SHOOT_LOW_UNJAM, + READY_DUAL_CROUCH, + AIM_DUAL_CROUCH, + SHOOT_DUAL_CROUCH, + END_DUAL_CROUCH, + CROUCH_SHOOT_DWEL_UNJAM, + ADJACENT_GET_ITEM, + CUTTING_FENCE, + CRIPPLE_BEG, + CRIPPLE_HIT, + CRIPPLE_DIE, + CRIPPLE_DIE_STOP, + CRIPPLE_DIE_FLYBACK, + CRIPPLE_DIE_FLYBACK_STOP, + CRIPPLE_KICKOUT, + FROM_INJURED_TRANSITION, + THROW_KNIFE, + KNIFE_BREATH, + KNIFE_GOTOBREATH, + KNIFE_ENDBREATH, + ROBOTNW_HIT, + ROBOTNW_DIE, + ROBOTNW_DIE_STOP, + CATCH_STANDING, + CATCH_CROUCHED, + PLANT_BOMB, + USE_REMOTE, + START_COWER, + COWERING, + END_COWER, + STEAL_ITEM, + SHOOT_ROCKET, + CIV_DIE2, + SHOOT_MORTAR, + CROW_DIE, + SIDE_STEP, + WALK_BACKWARDS, + BEGIN_OPENSTRUCT, + END_OPENSTRUCT, + END_OPENSTRUCT_LOCKED, + PUNCH_LOW, + PISTOL_SHOOT_LOW, + DECAPITATE, + BLOODCAT_BITE_ANIM, + BIGMERC_IDLE_NECK, + BIGMERC_CROUCH_TRANS_INTO, + BIGMERC_CROUCH_TRANS_OUTOF, + GOTO_PATIENT, + BEING_PATIENT, + GOTO_DOCTOR, + BEING_DOCTOR, + END_DOCTOR, + GOTO_REPAIRMAN, + BEING_REPAIRMAN, + END_REPAIRMAN, + FALL_INTO_PIT, + ROBOT_WALK, + ROBOT_SHOOT, + QUEEN_HIT, + QUEEN_DIE, + QUEEN_DIE_STOP, + QUEEN_INTO_READY, + QUEEN_READY, + QUEEN_END_READY, + QUEEN_CALL, + QUEEN_SPIT, + QUEEN_SWIPE, + RELOAD_ROBOT, + END_CATCH, + END_CROUCH_CATCH, + AI_RADIO, + AI_CR_RADIO, + TANK_SHOOT, + TANK_BURST, + QUEEN_SLAP, + SLAP_HIT, + TAKE_BLOOD_FROM_CORPSE, + VEHICLE_DIE, + QUEEN_FRUSTRATED_SLAP, + CHARIOTS_OF_FIRE, + AI_PULL_SWITCH, + MONSTER_MELT, + MERC_HURT_IDLE_ANIM, + END_HURT_WALKING, + PASS_OBJECT, + DROP_ADJACENT_OBJECT, + READY_DUAL_PRONE, + AIM_DUAL_PRONE, + SHOOT_DUAL_PRONE, + END_DUAL_PRONE, + PRONE_SHOOT_DWEL_UNJAM, + PICK_LOCK, + OPEN_DOOR_CROUCHED, + BEGIN_OPENSTRUCT_CROUCHED, + CLOSE_DOOR_CROUCHED, + OPEN_STRUCT_CROUCHED, + END_OPEN_DOOR_CROUCHED, + END_OPENSTRUCT_CROUCHED, + END_OPEN_LOCKED_DOOR_CROUCHED, + END_OPENSTRUCT_LOCKED_CROUCHED, + DRUNK_IDLE, + CROWBAR_ATTACK, + CIV_COWER_HIT, + BLOODCAT_WALK_BACKWARDS, + MONSTER_WALK_BACKWARDS, + KID_SKIPPING, + ROBOT_BURST_SHOOT, + ATTACH_CAN_TO_STRING, + SWAT_BACKWARDS, + JUMP_OVER_BLOCKING_PERSON, + REFUEL_VEHICLE, + ROBOT_CAMERA_NOT_MOVING, + CRIPPLE_OPEN_DOOR, + CRIPPLE_CLOSE_DOOR, + CRIPPLE_END_OPEN_DOOR, + CRIPPLE_END_OPEN_LOCKED_DOOR, + LOCKPICK_CROUCHED, + THROW_ITEM_CROUCHED, + BIGGUY_STONE, + SHOOT_ROCKET_CROUCHED, + SWATTING_WK, + SWAT_BACKWARDS_WK, + SWAT_BACKWARDS_NOTHING, + THROW_GRENADE_STANCE, + LOB_GRENADE_STANCE, + ROLL_PRONE_R, + ROLL_PRONE_L, + JUMPUPWALL, + JUMPDOWNWALL, + JUMPWINDOWS, + THROW_KNIFE_SP_BM, + RUNNING_W_PISTOL, + SIDE_STEP_WEAPON_RDY, + SIDE_STEP_DUAL_RDY, + SIDE_STEP_CROUCH_RIFLE, + SIDE_STEP_CROUCH_PISTOL, + SIDE_STEP_CROUCH_DUAL, + WALKING_WEAPON_RDY, + WALKING_DUAL_RDY, + CROUCHEDMOVE_RIFLE_READY, + CROUCHEDMOVE_PISTOL_READY, + CROUCHEDMOVE_DUAL_READY, + START_AID_PRN, + GIVING_AID_PRN, + END_AID_PRN, + ADJACENT_GET_ITEM_CROUCHED, + STEAL_ITEM_CROUCHED, + BURST_DUAL_STAND, + BURST_DUAL_CROUCH, + BURST_DUAL_PRONE, + READY_ALTERNATIVE_STAND, + AIM_ALTERNATIVE_STAND, + SHOOT_ALTERNATIVE_STAND, + BURST_ALTERNATIVE_STAND, + LOW_SHOT_ALTERNATIVE_STAND, + LOW_BURST_ALTERNATIVE_STAND, + UNREADY_ALTERNATIVE_STAND, + UNJAM_ALTERNATIVE_STAND, + LOW_UNJAM_ALTERNATIVE_STAND, + WALKING_ALTERNATIVE_RDY, + SIDE_STEP_ALTERNATIVE_RDY, + START_COWER_CROUCHED, + END_COWER_CROUCHED, + START_COWER_PRONE, + COWERING_PRONE, + END_COWER_PRONE, + BIGMERC_IDLE_NECK2, + FOCUSED_PUNCH, + FOCUSED_STAB, + HTH_KICK, + FOCUSED_HTH_KICK, + LONG_JUMP, + CRYO_DEATH, + CRYO_DEATH_CROUCHED, + BAYONET_STAB_STANDING_VS_STANDING, + BAYONET_STAB_STANDING_VS_PRONE + ); + + /***************************************** + Animation states + ******************************************/ + LOGBT_ENUMDB_ADD("AnimationSurfaces", NUMANIMATIONSURFACETYPES, + RGMBASICWALKING, + RGMSTANDING, + RGMCROUCHING, + RGMSNEAKING, + RGMRUNNING, + RGMPRONE, + RGMSTANDAIM, + RGMHITHARD, + RGMHITSTAND, + RGMHITHARDBLOOD, + RGMCROUCHAIM, + RGMHITFALLBACK, + RGMROLLOVER, + RGMCLIMBROOF, + RGMFALL, + RGMFALLF, + RGMHITCROUCH, + RGMHITPRONE, + RGMHOPFENCE, + RGMPUNCH, + RGMNOTHING_STD, + RGMNOTHING_WALK, + RGMNOTHING_RUN, + RGMNOTHING_SWAT, + RGMNOTHING_CROUCH, + RGMHANDGUN_S_SHOT, + RGMHANDGUN_C_SHOT, + RGMHANDGUN_PRONE, + RGMDIE_JFK, + RGMOPEN, + RGMPICKUP, + RGMSTAB, + RGMSLICE, + RGMCSTAB, + RGMMEDIC, + RGMDODGE, + RGMSTANDDWALAIM, + RGMRAISE, + RGMTHROW, + RGMLOB, + RGMKICKDOOR, + RGMRHIT, + RGM_SQUISH, + RGM_LOOK, + RGM_PULL, + RGM_SPIT, + RGMWATER_R_WALK, + RGMWATER_R_STD, + RGMWATER_N_WALK, + RGMWATER_N_STD, + RGMWATER_DIE, + RGMWATER_N_AIM, + RGMWATER_R_AIM, + RGMWATER_DBLSHT, + RGMWATER_TRANS, + RGMDEEPWATER_TRED, + RGMDEEPWATER_SWIM, + RGMDEEPWATER_DIE, + RGMMCLIMB, + RGMHELIDROP, + RGMLOWKICK, + RGMNPUNCH, + RGMSPINKICK, + RGMSLEEP, + RGMSHOOT_LOW, + RGMCDBLSHOT, + RGMHURTSTANDINGN, + RGMHURTSTANDINGR, + RGMHURTWALKINGN, + RGMHURTWALKINGR, + RGMHURTTRANS, + RGMTHROWKNIFE, + RGMBREATHKNIFE, + RGMPISTOLBREATH, + RGMCOWER, + RGMROCKET, + RGMMORTAR, + RGMSIDESTEP, + RGMDBLBREATH, + RGMPUNCHLOW, + RGMPISTOLSHOOTLOW, + RGMWATERTHROW, + RGMRADIO, + RGMCRRADIO, + RGMBURN, + RGMDWPRONE, + RGMDRUNK, + RGMPISTOLDRUNK, + RGMCROWBAR, + RGMJUMPOVER, + RGMBAYONET_S_S, + RGMBAYONET_S_P, + BGMWALKING, + BGMSTANDING, + BGMCROUCHING, + BGMSNEAKING, + BGMRUNNING, + BGMPRONE, + BGMSTANDAIM, + BGMHITHARD, + BGMHITSTAND, + BGMHITHARDBLOOD, + BGMCROUCHAIM, + BGMHITFALLBACK, + BGMROLLOVER, + BGMCLIMBROOF, + BGMFALL, + BGMFALLF, + BGMHITCROUCH, + BGMHITPRONE, + BGMHOPFENCE, + BGMPUNCH, + BGMNOTHING_STD, + BGMNOTHING_WALK, + BGMNOTHING_RUN, + BGMNOTHING_SWAT, + BGMNOTHING_CROUCH, + BGMHANDGUN_S_SHOT, + BGMHANDGUN_C_SHOT, + BGMHANDGUN_PRONE, + BGMDIE_JFK, + BGMOPEN, + BGMPICKUP, + BGMSTAB, + BGMSLICE, + BGMCSTAB, + BGMMEDIC, + BGMDODGE, + BGMSTANDDWALAIM, + BGMRAISE, + BGMTHROW, + BGMLOB, + BGMKICKDOOR, + BGMRHIT, + BGMSTANDAIM2, + BGMFLEX, + BGMSTRECH, + BGMSHOEDUST, + BGMHEADTURN, + BGMWATER_R_WALK, + BGMWATER_R_STD, + BGMWATER_N_WALK, + BGMWATER_N_STD, + BGMWATER_DIE, + BGMWATER_N_AIM, + BGMWATER_R_AIM, + BGMWATER_DBLSHT, + BGMWATER_TRANS, + BGMDEEPWATER_TRED, + BGMDEEPWATER_SWIM, + BGMDEEPWATER_DIE, + BGMHELIDROP, + BGMSLEEP, + BGMSHOOT_LOW, + BGMTHREATENSTAND, + BGMCDBLSHOT, + BGMHURTSTANDINGN, + BGMHURTSTANDINGR, + BGMHURTWALKINGN, + BGMHURTWALKINGR, + BGMHURTTRANS, + BGMTHROWKNIFE, + BGMBREATHKNIFE, + BGMPISTOLBREATH, + BGMCOWER, + BGMRAISE2, + BGMROCKET, + BGMMORTAR, + BGMSIDESTEP, + BGMDBLBREATH, + BGMPUNCHLOW, + BGMPISTOLSHOOTLOW, + BGMWATERTHROW, + BGMWALK2, + BGMRUN2, + BGMIDLENECK, + BGMCROUCHTRANS, + BGMRADIO, + BGMCRRADIO, + BGMDWPRONE, + BGMDRUNK, + BGMPISTOLDRUNK, + BGMCROWBAR, + BGMJUMPOVER, + BGMBAYONET_S_S, + BGMBAYONET_S_P, + RGFWALKING, + RGFSTANDING, + RGFCROUCHING, + RGFSNEAKING, + RGFRUNNING, + RGFPRONE, + RGFSTANDAIM, + RGFHITHARD, + RGFHITSTAND, + RGFHITHARDBLOOD, + RGFCROUCHAIM, + RGFHITFALLBACK, + RGFROLLOVER, + RGFCLIMBROOF, + RGFFALL, + RGFFALLF, + RGFHITCROUCH, + RGFHITPRONE, + RGFHOPFENCE, + RGFPUNCH, + RGFNOTHING_STD, + RGFNOTHING_WALK, + RGFNOTHING_RUN, + RGFNOTHING_SWAT, + RGFNOTHING_CROUCH, + RGFHANDGUN_S_SHOT, + RGFHANDGUN_C_SHOT, + RGFHANDGUN_PRONE, + RGFDIE_JFK, + RGFOPEN, + RGFPICKUP, + RGFSTAB, + RGFSLICE, + RGFCSTAB, + RGFMEDIC, + RGFDODGE, + RGFSTANDDWALAIM, + RGFRAISE, + RGFTHROW, + RGFLOB, + RGFKICKDOOR, + RGFRHIT, + RGFCLEAN, + RGFKICKSN, + RGFALOOK, + RGFWIPE, + RGFWATER_R_WALK, + RGFWATER_R_STD, + RGFWATER_N_WALK, + RGFWATER_N_STD, + RGFWATER_DIE, + RGFWATER_N_AIM, + RGFWATER_R_AIM, + RGFWATER_DBLSHT, + RGFWATER_TRANS, + RGFDEEPWATER_TRED, + RGFDEEPWATER_SWIM, + RGFDEEPWATER_DIE, + RGFHELIDROP, + RGFSLEEP, + RGFSHOOT_LOW, + RGFCDBLSHOT, + RGFHURTSTANDINGN, + RGFHURTSTANDINGR, + RGFHURTWALKINGN, + RGFHURTWALKINGR, + RGFHURTTRANS, + RGFTHROWKNIFE, + RGFBREATHKNIFE, + RGFPISTOLBREATH, + RGFCOWER, + RGFROCKET, + RGFMORTAR, + RGFSIDESTEP, + RGFDBLBREATH, + RGFPUNCHLOW, + RGFPISTOLSHOOTLOW, + RGFWATERTHROW, + RGFRADIO, + RGFCRRADIO, + RGFSLAP, + RGFDWPRONE, + RGFDRUNK, + RGFPISTOLDRUNK, + RGFCROWBAR, + RGFJUMPOVER, + RGFBAYONET_S_S, + RGFBAYONET_S_P, + CRYO_EXPLODE, + CRYO_EXPLODE_CROUCHED, + AFMONSTERSTANDING, + AFMONSTERWALKING, + AFMONSTERATTACK, + AFMONSTERCLOSEATTACK, + AFMONSTERSPITATTACK, + AFMONSTEREATING, + AFMONSTERDIE, + AFMUP, + AFMJUMP, + AFMMELT, + LVBREATH, + LVDIE, + LVWALK, + IBREATH, + IWALK, + IDIE, + IEAT, + IATTACK, + QUEENMONSTERSTANDING, + QUEENMONSTERREADY, + QUEENMONSTERSPIT_SW, + QUEENMONSTERSPIT_E, + QUEENMONSTERSPIT_NE, + QUEENMONSTERSPIT_S, + QUEENMONSTERSPIT_SE, + QUEENMONSTERDEATH, + QUEENMONSTERSWIPE, + FATMANSTANDING, + FATMANWALKING, + FATMANRUNNING, + FATMANDIE, + FATMANASS, + FATMANACT, + FATMANCOWER, + FATMANDIE2, + FATMANCOWERHIT, + MANCIVSTANDING, + MANCIVWALKING, + MANCIVRUNNING, + MANCIVDIE, + MANCIVACT, + MANCIVCOWER, + MANCIVDIE2, + MANCIVSMACKED, + MANCIVPUNCH, + MANCIVCOWERHIT, + MINICIVSTANDING, + MINICIVWALKING, + MINICIVRUNNING, + MINICIVDIE, + MINISTOCKING, + MINIACT, + MINICOWER, + MINIDIE2, + MINICOWERHIT, + DRESSCIVSTANDING, + DRESSCIVWALKING, + DRESSCIVRUNNING, + DRESSCIVDIE, + DRESSCIVACT, + DRESSCIVCOWER, + DRESSCIVDIE2, + DRESSCIVCOWERHIT, + HATKIDCIVSTANDING, + HATKIDCIVWALKING, + HATKIDCIVRUNNING, + HATKIDCIVDIE, + HATKIDCIVJFK, + HATKIDCIVYOYO, + HATKIDCIVACT, + HATKIDCIVCOWER, + HATKIDCIVDIE2, + HATKIDCIVCOWERHIT, + HATKIDCIVSKIP, + KIDCIVSTANDING, + KIDCIVWALKING, + KIDCIVRUNNING, + KIDCIVDIE, + KIDCIVJFK, + KIDCIVARMPIT, + KIDCIVACT, + KIDCIVCOWER, + KIDCIVDIE2, + KIDCIVCOWERHIT, + KIDCIVSKIP, + CRIPCIVSTANDING, + CRIPCIVWALKING, + CRIPCIVRUNNING, + CRIPCIVBEG, + CRIPCIVDIE, + CRIPCIVDIE2, + CRIPCIVKICK, + COWSTANDING, + COWWALKING, + COWDIE, + COWEAT, + CROWWALKING, + CROWFLYING, + CROWEATING, + CROWDYING, + CATBREATH, + CATWALK, + CATRUN, + CATREADY, + CATHIT, + CATDIE, + CATSWIPE, + CATBITE, + ROBOTNWBREATH, + ROBOTNWWALK, + ROBOTNWHIT, + ROBOTNWDIE, + ROBOTNWSHOOT, + HUMVEE_BASIC, + HUMVEE_DIE, + TANKNW_READY, + TANKNW_SHOOT, + TANKNW_DIE, + TANKNE_READY, + TANKNE_SHOOT, + TANKNE_DIE, + ELDORADO_BASIC, + ELDORADO_DIE, + ICECREAMTRUCK_BASIC, + ICECREAMTRUCK_DIE, + JEEP_BASIC, + JEEP_DIE, + ARMED_CAR_READY, + ARMED_CAR_SHOOT, + ARMED_CAR_DIE, + BODYEXPLODE, + RGMCRTHROW, + BGMCRTHROW, + RGFCRTHROW, + BGMWITHSTONE, + RGMCRROCKET, + BGMCRROCKET, + RGFCRROCKET, + BGMSWKNIFE, + RGFSWKNIFE, + RGMSWKNIFE, + BGMSTHRG, + RGFSTHRG, + RGMSTHRG, + BGMSLOBG, + RGFSLOBG, + RGMSLOBG, + RGMROLL_PR, + BGMROLL_PR, + RGFROLL_PR, + RGMWALLJUMP, + BGMWALLJUMP, + RGFWALLJUMP, + RGMJUMPWINDOWS, + BGMJUMPWINDOWS, + RGFJUMPWINDOWS, + RGMUSEREMOTE, + BGMUSEREMOTE, + RGFUSEREMOTE, + BGMTHROWKNIFE2, + RGMPISTOL_RUN, + BGMPISTOL_RUN, + RGFPISTOL_RUN, + RGMSIDESTEP_P_RDY, + RGMSIDESTEP_R_RDY, + RGMSIDESTEP_D_RDY, + BGMSIDESTEP_P_RDY, + BGMSIDESTEP_R_RDY, + BGMSIDESTEP_R_RDY2, + BGMSIDESTEP_D_RDY, + RGFSIDESTEP_P_RDY, + RGFSIDESTEP_R_RDY, + RGFSIDESTEP_D_RDY, + RGMSIDESTEP_CROUCH_R_RDY, + RGMSIDESTEP_CROUCH_P_RDY, + RGMSIDESTEP_CROUCH_D_RDY, + BGMSIDESTEP_CROUCH_R_RDY, + BGMSIDESTEP_CROUCH_P_RDY, + BGMSIDESTEP_CROUCH_D_RDY, + RGFSIDESTEP_CROUCH_R_RDY, + RGFSIDESTEP_CROUCH_P_RDY, + RGFSIDESTEP_CROUCH_D_RDY, + RGMWALK_P_RDY, + RGMWALK_R_RDY, + RGMWALK_D_RDY, + RGMCROUCH_R_RDY, + RGMCROUCH_P_RDY, + RGMCROUCH_D_RDY, + BGMWALK_P_RDY, + BGMWALK_R_RDY, + BGMWALK_R_RDY2, + BGMWALK_D_RDY, + BGMCROUCH_R_RDY, + BGMCROUCH_P_RDY, + BGMCROUCH_D_RDY, + RGFWALK_P_RDY, + RGFWALK_R_RDY, + RGFWALK_D_RDY, + RGFCROUCH_R_RDY, + RGFCROUCH_P_RDY, + RGFCROUCH_D_RDY, + RGMMEDICPRN, + BGMMEDICPRN, + RGFMEDICPRN, + RGM_HIP_AIM, + RGM_HIP_LOW, + BGM_HIP_AIM, + RGF_HIP_AIM, + RGM_WATER_HIP_AIM, + BGM_WATER_HIP_AIM, + RGF_WATER_HIP_AIM, + RGM_COWER_PRONE, + BGM_COWER_PRONE, + RGF_COWER_PRONE, + BGMIDLENECK2, + BGMHIPAIMALT, + BGMSRAIMALT, + RGM_PFSHOT_AIM, + BGM_PFSHOT_AIM, + RGF_PFSHOT_AIM + ); + + }; + +} diff --git a/Tactical/LogicalBodyTypes/BodyTypeDB.h b/Tactical/LogicalBodyTypes/BodyTypeDB.h new file mode 100644 index 00000000..fa0e7ffd --- /dev/null +++ b/Tactical/LogicalBodyTypes/BodyTypeDB.h @@ -0,0 +1,78 @@ +#pragma once + +#ifndef _LBT_BODYTYPEDB__H_ +#define _LBT_BODYTYPEDB__H_ + +#include +#include "LogicalBodyTypes/Singleton.h" +#include "LogicalBodyTypes/AbstractXMLLoader.h" +#include "LogicalBodyTypes/BodyType.h" +#include "LogicalBodyTypes/FilterDB.h" +#include "LogicalBodyTypes/SurfaceDB.h" + +namespace LogicalBodyTypes { + +class BodyTypeDB : public AbstractXMLLoader, public Singleton { + +public: + using Singleton ::Instance; + typedef std::list BodyTypeList; + //TOTAL_SOLDIERS +private: + enum ParseState { + E_ELEMENT_BODYTYPES = FIRST_SUBCLASS_STATE, + E_ELEMENT_BODYTYPE, + E_ELEMENT_LAYER_CONFIGS, + E_ELEMENT_LAYER_CONFIG, + E_ELEMENT_SURFACES, + E_ELEMENT_LAYER, + E_ELEMENT_PROP, + E_ELEMENT_SURFACE + }; + struct ParseData : public AbstractXMLLoader::ParseData { // shadow ParseData type and also extend the ParseData stuct of the base class + ParseData(XML_Parser* parser) : AbstractXMLLoader::ParseData(parser) { + currentBodyType = NULL; + filter = NULL; + paletteTable = NULL; + layer = -1; + layerPropertiesConfig.clear(); + }; + ~ParseData() { + if (currentBodyType != NULL) delete currentBodyType; + }; + BodyType* currentBodyType; + Filter* filter; + PaletteTable* paletteTable; + Layers::LayerPropertiesVector::size_type layer; + std::map layerPropertiesConfig; + } typedef ParseData; + BodyTypeList bodyTypes; + +public: + BodyTypeDB(void); + ~BodyTypeDB(void); + void Add(BodyType* bodyType); + + inline BodyType* Find(SOLDIERTYPE* pSoldier) { + BodyTypeList::iterator end = bodyTypes.end(); + for (BodyTypeList::iterator i = bodyTypes.begin(); i != end; i++) { + // if we find a bodytype, but it does not have any surfaces, it is meant to exclude objects + // from being matched against bodytypes so we return NULL in that case. + if ((*i)->Match(pSoldier)) return ((*i)->HasSurfaces()) ? *i : NULL; + } + return NULL; + }; + +private: + static void RegisterEnumerators(); + static void XMLCALL StartElementHandle(void* userData, const XML_Char* name, const XML_Char** atts); + static void XMLCALL CharacterDataHandle(void* userData, const XML_Char* str, int len); + static void XMLCALL EndElementHandle(void* userData, const XML_Char* name); + static void XMLCALL ExternalEntityHandler(XML_Parser parser, const XML_Char* context, const XML_Char* base, const XML_Char* systemId, const XML_Char* publicId); + static AbstractXMLLoader::ParseData* MakeParseData(XML_Parser* parser); // shadow factory function for ParseData instances + +}; + +} + +#endif diff --git a/Tactical/LogicalBodyTypes/EnumeratorDB.cpp b/Tactical/LogicalBodyTypes/EnumeratorDB.cpp new file mode 100644 index 00000000..2d44e1c0 --- /dev/null +++ b/Tactical/LogicalBodyTypes/EnumeratorDB.cpp @@ -0,0 +1,64 @@ +#include "EnumeratorDB.h" + +namespace LogicalBodyTypes { + +EnumeratorDB::EnumeratorDB() { +} + +EnumeratorDB::~EnumeratorDB(void) { +} + +void EnumeratorDB::AddEnum(std::string enumName, int num, char* strEnumerators, ...) { + int strLen = strlen(strEnumerators); + char* str = new char[strLen + 1]; + strcpy(str, strEnumerators); + + // for detecting synchronization issue between the actual enum declaration and the DB insertion + // assert that the number of provided enumerators matches the expected number + int numSemiColons = 0; + for (int i = 0; i < strLen; i++) if (strEnumerators[i] == ',') numSemiColons++; + // TODO: remove output to cout Log this event somehow not just do the assertion! + if (numSemiColons + 1 != num) { + std::cout << enumName << " expected " << num << " got " << numSemiColons + 1 << std::endl; + } + assert(numSemiColons + 1 == num); + + // if enumeration already in DB, delete + EnumerationMap::iterator i = enumerations.find(enumName); + if (i != enumerations.end()) enumerations.erase(enumName); + + char* token = strtok(str, ", "); + va_list vl; + va_start(vl, strEnumerators); + for (int i = 0; i < num; i++) { + enumerations[enumName][token] = va_arg(vl, int); + token = strtok(NULL, ", "); + } + + va_end(vl); + delete str; +} + +bool EnumeratorDB::GetEnumeratorStr(const char* enumeration, int enumerator, std::string& str) { + EnumerationMap::iterator i = enumerations.find(enumeration); + if (i != enumerations.end()) { + for (EnumeratorMap::iterator j = i->second.begin(); j != i->second.end(); j++) { + if (j->second == enumerator) { + str = j->first; + return true; + } + } + } + return false; +} + +bool EnumeratorDB::GetEnumeratorByStr(const char* enumeration, const char* enumerationStr, int& enumerator) { + EnumerationMap::iterator i = enumerations.find(enumeration); + if (i == enumerations.end()) return false; + EnumeratorMap::iterator j = i->second.find(enumerationStr); + if (j == i->second.end()) return false; + enumerator = j->second; + return true; +} + +} diff --git a/Tactical/LogicalBodyTypes/EnumeratorDB.h b/Tactical/LogicalBodyTypes/EnumeratorDB.h new file mode 100644 index 00000000..d6eccf4c --- /dev/null +++ b/Tactical/LogicalBodyTypes/EnumeratorDB.h @@ -0,0 +1,38 @@ +#pragma once +#ifndef _LBT_ENUMERATORDB__H_ +#define _LBT_ENUMERATORDB__H_ + +#include "LogicalBodyTypes/Singleton.h" +#include +#include +#include +#include + +#define LOGBT_ENUMDB_ADD(enumName, count, ...) EnumeratorDB::Instance().AddEnum(enumName, count, #__VA_ARGS__, __VA_ARGS__) + +namespace LogicalBodyTypes { + +class EnumeratorDB : public Singleton { + +public: + typedef std::map EnumeratorMap; + typedef std::map EnumerationMap; + EnumerationMap enumerations; + +public: + EnumeratorDB(); + ~EnumeratorDB(); + void AddEnum(std::string enumName, int num, char* strEnumerators, ...); + // Note: this will return the FIRST enumerator of the specified enumeration + // that matches the provided ordinal value! + // Also: it is expected that this will only be called in situations where the efficiency is not relevant + // (like for generating a list of enumerators for testing/documentation) + // otherwise a different mechanism for storing the enumerations should be implemented. + bool GetEnumeratorStr(const char* enumeration, int enumerator, std::string& str); + bool GetEnumeratorByStr(const char* enumeration, const char* enumerationStr, int& enumerator); + +}; + +}; + +#endif diff --git a/Tactical/LogicalBodyTypes/Filter.cpp b/Tactical/LogicalBodyTypes/Filter.cpp new file mode 100644 index 00000000..e264bf68 --- /dev/null +++ b/Tactical/LogicalBodyTypes/Filter.cpp @@ -0,0 +1,303 @@ +#include "Filter.h" + +namespace LogicalBodyTypes { + +Filter::Filter(void) { +} + +Filter::~Filter(void) { + for (CriteriaMap::iterator i = criteria.begin(); i != criteria.end(); i++) { + if (i->first & _TYPE_STRING) { + if (i->first & _TYPE_LIST) delete i->second.stringList; + else delete i->second.string; + } + else if (i->first & _TYPE_INTEGER) { + if (i->first & _TYPE_PAIR) delete i->second.numberPair; + else if (i->first & _TYPE_LIST) delete i->second.numberList; + } + } +} + +void Filter::AddCriterion(UINT32 type, std::wstring& value) { + type &= ~_TYPE_INTEGER; + type |= _TYPE_STRING; + std::wstring* str = new std::wstring(value); + criterionVariant val; + val.string = str; + criteria.insert(CriteriaMap::value_type(type, val)); +} + +void Filter::AddCriterion(UINT32 type, STR16 value) { + type &= ~_TYPE_INTEGER; + type |= _TYPE_STRING; + std::wstring* str = new std::wstring(value); + criterionVariant val; + val.string = str; + criteria.insert(CriteriaMap::value_type(type, val)); +} + +void Filter::AddCriterion(UINT32 type, StringList& list) { + type &= ~_TYPE_INTEGER; + type |= _TYPE_STRING; + criterionVariant val; + val.stringList = new StringList(list); // I don't trust copy constructors, but oh well... + criteria.insert(CriteriaMap::value_type(type, val)); +} + + +void Filter::AddCriterion(UINT32 type, INT32 value) { + type &= ~_TYPE_STRING; + type |= _TYPE_INTEGER; + criterionVariant val; + val.number = value; + criteria.insert(CriteriaMap::value_type(type, val)); +} + +void Filter::AddCriterion(UINT32 type, INT32 value1, INT32 value2) { + type &= ~_TYPE_STRING; + type |= _TYPE_INTEGER; + criterionVariant val; + val.numberPair = new NumberPair(value1, value2); + criteria.insert(CriteriaMap::value_type(type, val)); +} + +void Filter::AddCriterion(UINT32 type, NumberList& list) { + type &= ~_TYPE_STRING; + type |= _TYPE_INTEGER; + criterionVariant val; + val.numberList = new NumberList(list); // I don't trust copy constructors, but oh well... + criteria.insert(CriteriaMap::value_type(type, val)); +} + +void Filter::AddCriterion(UINT32 type, Filter* filter) { + type |= _TYPE_FILTER; + criterionVariant val; + val.filter = filter; + criteria.insert(CriteriaMap::value_type(type, val)); +} + +void Filter::Dump(std::wstringstream& stream) { + stream << L"<-------- Filter" << std::endl; + for (CriteriaMap::iterator ii = criteria.begin(); ii != criteria.end(); ii++) { + UINT32 flags = ii->first & _UNSET_FLAGS; + UINT32 cType = ii->first & ~_UNSET_FLAGS; + std::string op = ""; + if (flags & _REQ_OR) op += "OR"; + if (flags & _REQ_AND) op += "AND"; + std::string cmpop = ""; + if ((flags & _REQ_NOT) && (flags & _REQ_EQ)) cmpop = "!="; + if (((flags & _REQ_NOT) != _REQ_NOT) && (flags & _REQ_EQ)) cmpop = "=="; + if ((flags & _REQ_NOT) && (flags & _REQ_GT)) cmpop = ">"; + if (((flags & _REQ_NOT) != _REQ_NOT) && (flags & _REQ_GT)) cmpop = "<="; + if ((flags & _REQ_NOT) && (flags & _REQ_LT)) cmpop = "<"; + if (((flags & _REQ_NOT) != _REQ_NOT) && (flags & _REQ_LT)) cmpop = ">="; + if (flags & Filter::_TYPE_STRING) { + std::string enumStr; + EnumeratorDB::Instance().GetEnumeratorStr("StringFilterCriterionTypes", cType, enumStr); + stream << L"criterion: " << op << L" str " << enumStr << L" " << cmpop << L" " << *ii->second.string << std::endl; + } + if (flags & Filter::_TYPE_INTEGER) { + std::string enumStr; + // first try to find the enumerator in the integer criterion type list then in the enum list + bool foundEnumerator = EnumeratorDB::Instance().GetEnumeratorStr("IntegerFilterCriterionTypes", cType, enumStr); + if (!foundEnumerator) EnumeratorDB::Instance().GetEnumeratorStr("EnumFilterCriterionTypes", cType, enumStr); + stream << L"criterion: " << op << L" str " << enumStr << L" " << cmpop << L" " << ii->second.number << std::endl; + } + // TODO: drop method or update to match the additional types that have been added. + } + stream << L"-------->" << std::endl; +} + +// quite an ugly implementation. Should be re-done +bool Filter::Match(SOLDIERTYPE* pSoldier) { + bool orReq = false; + bool orRes = false; + UINT32 operation = _REQ_AND; + // TODO: make sure container is a BT, since we need no random access anyways! + for (CriteriaMap::iterator ii = criteria.begin(); ii != criteria.end(); ii++) { + UINT32 r = ii->first; + if ((r & _REQ_AND) == _REQ_AND) { + operation = _REQ_AND; + } + else if ((r & _REQ_OR) == _REQ_OR) { + if (orRes) continue; + orReq = true; + operation = _REQ_OR; + } + char sgn; + if (r & _TYPE_INTEGER) { + INT32 cmp_val; + UINT32 q = r & ~_UNSET_FLAGS; + switch (q) { + case REQ_BODYTYPE: + cmp_val = pSoldier->ubBodyType; + break; + case REQ_TEAM: + cmp_val = pSoldier->bTeam; + break; + case REQ_SOLDIER_CLASS: + cmp_val = pSoldier->ubSoldierClass; + break; + case REQ_CIVILIANGROUP: + cmp_val = pSoldier->ubCivilianGroup; + break; + case REQ_CAMO: + cmp_val = pSoldier->bCamo; + break; + case REQ_URBANCAMO: + cmp_val = pSoldier->urbanCamo; + break; + case REQ_DESERTCAMO: + cmp_val = pSoldier->desertCamo; + break; + case REQ_SNOWCAMO: + cmp_val = pSoldier->snowCamo; + break; + case REQ_EXPLEVEL: + cmp_val = pSoldier->stats.bExpLevel; + break; + case REQ_STRENGTH: + cmp_val = pSoldier->stats.bStrength; + break; + case REQ_LEADERSHIP: + cmp_val = pSoldier->stats.bLeadership; + break; + case REQ_WISDOM: + cmp_val = pSoldier->stats.bWisdom; + break; +/* case REQ_SKILLTRAIT1: + cmp_val = pSoldier->stats.ubSkillTrait1; + break; + case REQ_SKILLTRAIT2: + cmp_val = pSoldier->stats.ubSkillTrait2; + break;*/ + case REQ_FACEINDEX: + if (pSoldier->ubProfile == NO_PROFILE + || pSoldier->ubProfile < 1 + || pSoldier->ubProfile > NUM_PROFILES - 2) return false; + cmp_val = gMercProfiles[pSoldier->ubProfile].ubFaceIndex; + break; + case REQ_WEAPON_IN_HAND: + cmp_val = WeaponInHand(pSoldier); + break; + case REQ_MERC_TYPE: + cmp_val = pSoldier->ubWhatKindOfMercAmI; + break; + case REQ_WEAPON_CLASS: + cmp_val = Weapon[pSoldier->inv[HANDPOS].usItem].ubWeaponClass; + break; + case REQ_WEAPON_TYPE: + cmp_val = Weapon[pSoldier->inv[HANDPOS].usItem].ubWeaponType; + break; + case REQ_CALIBRE: + cmp_val = Weapon[pSoldier->inv[HANDPOS].usItem].ubCalibre; + break; + case REQ_VEST_AMOR_PROTECTION: + cmp_val = Armour[Item[pSoldier->inv[VESTPOS].usItem].ubClassIndex].ubProtection; + break; + case REQ_VEST_AMOR_COVERAGE: + cmp_val = Armour[Item[pSoldier->inv[VESTPOS].usItem].ubClassIndex].ubCoverage; + break; + case REQ_HELMET_AMOR_PROTECTION: + cmp_val = Armour[Item[pSoldier->inv[HELMETPOS].usItem].ubClassIndex].ubProtection; + break; + case REQ_HELMET_AMOR_COVERAGE: + cmp_val = Armour[Item[pSoldier->inv[HELMETPOS].usItem].ubClassIndex].ubCoverage; + break; + default: + if (q < NUM_REQTYPESINV) { + cmp_val = pSoldier->inv[q].usItem; + } else { + // not implemented. We should log this somehow(must be cached). + return false; + } + } + if (r & _TYPE_LIST) { + NumberList* nl = ii->second.numberList; + sgn = -1; // -1 or 1 doesn't matter + for (NumberList::iterator i = nl->begin(); i != nl->end(); i++) { + if (*i == cmp_val) { + sgn = 0; + break; + } + } + } else if (r & _TYPE_PAIR) { + NumberPair* nl = ii->second.numberPair; + // TODO: resolve compiler warning about usigned/signed and the comparison ops?!? + sgn = (nl->second > cmp_val) ? -1 : (nl->first < cmp_val) ? 1 : 0; + } else { + sgn = (ii->second.number > cmp_val) ? -1 : (ii->second.number < cmp_val) ? 1 : 0; + } + } else if (r & _TYPE_STRING) { + // string comparison is quite costly at the moment. should be avoided or reimplemented. + // would probably be much more sensible just to loop and make a wchar for wchar check. + // I wanted to use the signum compare as with the integer values. But since that + // is more like a code gimmick than an actual useful feature, probably better to + // drop the check for > < for strings alltogether. + std::wstring cmp_val; + CHAR16 wStr[31]; + switch (r & ~_UNSET_FLAGS) { + case REQ_NAME: + wcscpy(wStr, pSoldier->name); + cmp_val = wStr; + break; + case REQ_PROFILENAME: + if (pSoldier->ubProfile == NO_PROFILE + || pSoldier->ubProfile < 1 + || pSoldier->ubProfile > NUM_PROFILES - 2) return false; + wcscpy(wStr, gMercProfiles[pSoldier->ubProfile].zName); + cmp_val = wStr; + break; + case REQ_NICKNAME: + if (pSoldier->ubProfile == NO_PROFILE + || pSoldier->ubProfile < 1 + || pSoldier->ubProfile > NUM_PROFILES - 2) return false; + wcscpy(wStr, gMercProfiles[pSoldier->ubProfile].zNickname); + cmp_val = wStr; + break; + default: + // not implemented. We should log this somehow(must be cached). + return false; + } + if (r & _TYPE_LIST) { + StringList* sl = ii->second.stringList; + sgn = -1; // -1 or 1 doesn't matter + for (StringList::iterator i = sl->begin(); i != sl->end(); i++) { + if (*i == cmp_val) { + sgn = 0; + break; + } + } + } + else { + std::wstring* sp = ii->second.string; + sgn = cmp_val.compare(*sp); + } + } else if (r & _TYPE_FILTER) { + if (ii->second.filter == NULL) { + // TODO: log or exception + return false; + } + sgn = (ii->second.filter->Match(pSoldier)) ? 0 : -1; // -1 or 1 doesn't matter + } else { + // TODO: log or exception + return false; + } + bool res = ((r & _REQ_NOT) == _REQ_NOT) ^ ( + (((r & _REQ_EQ) == _REQ_EQ) && sgn == 0) + || (((r & _REQ_IN) == _REQ_IN) && sgn == 0) + || (((r & _REQ_BTWN) == _REQ_BTWN) && sgn == 0) + || (((r & _REQ_GT) == _REQ_GT) && sgn == 1) + || (((r & _REQ_LT) == _REQ_LT) && sgn == -1) + ); + + if (operation == _REQ_AND) { + if (!res) return false; + } else if (operation == _REQ_OR) { + orRes |= res; + } + } + return !orReq || orRes; +}; + +}; diff --git a/Tactical/LogicalBodyTypes/Filter.h b/Tactical/LogicalBodyTypes/Filter.h new file mode 100644 index 00000000..fbe57c0b --- /dev/null +++ b/Tactical/LogicalBodyTypes/Filter.h @@ -0,0 +1,118 @@ +#pragma once +#ifndef _LBT_FILTER__H_ +#define _LBT_FILTER__H_ + +#include +#include +#include "DEBUG.H" +#include "Soldier Control.h" +#include "soldier profile type.h" +#include "Soldier Profile.h" +#include "Weapons.h" +#include "LogicalBodyTypes/EnumeratorDB.h" + +namespace LogicalBodyTypes { + +class Filter { + +public: + enum ConditionTypes + { + // lowest two bytes are reserved for enumerators + REQ_HELMETPOS, + REQ_VESTPOS, + REQ_LEGPOS, + REQ_HEAD1POS, + REQ_HEAD2POS, + REQ_HANDPOS, + REQ_SECONDHANDPOS, + REQ_VESTPOCKPOS, + REQ_LTHIGHPOCKPOS, + REQ_RTHIGHPOCKPOS, + REQ_CPACKPOCKPOS, + REQ_BPACKPOCKPOS, + REQ_GUNSLINGPOCKPOS, + REQ_KNIFEPOCKPOS, + NUM_REQTYPESINV, + REQ_SEX, + REQ_MERC_TYPE, + REQ_NAME, + REQ_SOLDIER_CLASS, + REQ_TEAM, + REQ_CIVILIANGROUP, + REQ_CAMO, + REQ_URBANCAMO, + REQ_DESERTCAMO, + REQ_SNOWCAMO, + REQ_BODYTYPE, + REQ_EXPLEVEL, + REQ_STRENGTH, + REQ_LEADERSHIP, + REQ_WISDOM, + REQ_SKILLTRAIT1, + REQ_SKILLTRAIT2, + REQ_FACEINDEX, + REQ_PROFILENAME, + REQ_NICKNAME, + REQ_WEAPON_IN_HAND, + REQ_WEAPON_CLASS, + REQ_WEAPON_TYPE, + REQ_CALIBRE, + REQ_VEST_AMOR_PROTECTION, + REQ_VEST_AMOR_COVERAGE, + REQ_HELMET_AMOR_PROTECTION, + REQ_HELMET_AMOR_COVERAGE, + NUM_REQTYPES, + // 3rd byte is for operator flags + _REQ_BTWN = 0x20000, + _REQ_NOT = 0x40000, + _REQ_EQ = 0x80000, + _REQ_LT = 0x100000, + _REQ_GT = 0x200000, + _REQ_AND = 0x400000, + _REQ_OR = 0x800000, + _REQ_IN = 0x1000000, + // 4th byte is for type flags + _TYPE_STRING = 0x2000000, + _TYPE_INTEGER = 0x4000000, + _TYPE_ENUM = 0x8000000, + _TYPE_LIST = 0x10000000, + _TYPE_PAIR = 0x20000000, + _TYPE_FILTER = 0x40000000, + // TODO rename enumerator _ALL_FLAGS or somesuch + _UNSET_FLAGS = _TYPE_FILTER | _TYPE_PAIR | _TYPE_LIST | _TYPE_ENUM | _TYPE_STRING | _TYPE_INTEGER | _REQ_IN | _REQ_OR | _REQ_AND | _REQ_BTWN | _REQ_NOT | _REQ_EQ | _REQ_LT | _REQ_GT + }; + typedef std::pair NumberPair; + typedef std::list StringList; + typedef std::list NumberList; + union criterionVariant { + INT32 number; + std::wstring* string; + NumberPair* numberPair; + StringList* stringList; + NumberList* numberList; + Filter* filter; + } typedef criterionVariant; + typedef std::multimap CriteriaMap; + +public: + Filter(void); + ~Filter(void); + void AddCriterion(UINT32 type, std::wstring& value); + void AddCriterion(UINT32 type, STR16 value); + void AddCriterion(UINT32 type, StringList& list); + void AddCriterion(UINT32 type, INT32 value); + void AddCriterion(UINT32 type, INT32 value1, INT32 value2); + void AddCriterion(UINT32 type, NumberList& list); + void AddCriterion(UINT32 type, Filter* filter); + void Dump(std::wstringstream& stream); + bool Match(SOLDIERTYPE* pSoldier); + +private: + CriteriaMap criteria; + +}; + +} + +#endif diff --git a/Tactical/LogicalBodyTypes/FilterDB.cpp b/Tactical/LogicalBodyTypes/FilterDB.cpp new file mode 100644 index 00000000..890c72fa --- /dev/null +++ b/Tactical/LogicalBodyTypes/FilterDB.cpp @@ -0,0 +1,689 @@ +#include "FilterDB.h" + +namespace LogicalBodyTypes { + + FilterDB::FilterDB(void) : AbstractXMLLoader(StartElementHandle, EndElementHandle, CharacterDataHandle, MakeParseData) { + RegisterEnumerators(); + } + + FilterDB::~FilterDB(void) { + for (FilterMap::iterator i = filters.begin(); i != filters.end(); i++) { + delete i->second; + } + } + + bool FilterDB::AddFilter(std::string name, Filter* filter) { + iterator i = filters.find(name); + if (i != filters.end()) { + return false; + } + filters[name] = filter; + return true; + } + + Filter* FilterDB::FindFilter(std::string name) { + iterator i = filters.find(name); + return (i != filters.end()) ? i->second : NULL; + } + + FilterDB::FilterMap::const_iterator FilterDB::begin() { + return filters.begin(); + } + + FilterDB::FilterMap::const_iterator FilterDB::end() { + return filters.end(); + } + + AbstractXMLLoader::ParseData* FilterDB::MakeParseData(XML_Parser* parser) { + return new ParseData(parser); + } + + void XMLCALL FilterDB::StartElementHandle(void* userData, const XML_Char* name, const XML_Char** atts) { + ParseData* data = (ParseData*)userData; + switch (data->state) { + case E_NONE: + if (strcmp(name, "Filters") == 0) { + data->state = E_ELEMENT_FILTERS; + break; + } + case E_ELEMENT_FILTERS: + if (strcmp(name, "Filter") == 0) { + data->state = E_ELEMENT_FILTER; + data->currentFilter = new Filter(); + XML_Char const* attrName = GetAttribute("name", atts); + if (attrName == NULL) throw XMLParseException("Mandatory attribute missing!", name, data->pParser); + data->filterName = attrName; + break; + } + case E_ELEMENT_FILTER: + if (strcmp(name, "AND") == 0) { + data->state = E_OPERATION; + data->operationFlags = Filter::_REQ_AND; + break; + } + if (strcmp(name, "OR") == 0) { + data->state = E_OPERATION; + data->operationFlags = Filter::_REQ_OR; + break; + } + case E_OPERATION: + { + data->state = E_CRITERION; + data->criterionType = 0; + int ord; + data->criterionName = name; + std::string enumeratorString = "Filter::REQ_"; + enumeratorString += name; + if (EnumeratorDB::Instance().GetEnumeratorByStr("IntegerFilterCriterionTypes", enumeratorString.c_str(), ord)) { + data->criterionType = ord; + data->criterionType |= Filter::_TYPE_INTEGER; + } + else if (EnumeratorDB::Instance().GetEnumeratorByStr("StringFilterCriterionTypes", enumeratorString.c_str(), ord)) { + data->criterionType = ord; + data->criterionType |= Filter::_TYPE_STRING; + } + else if (EnumeratorDB::Instance().GetEnumeratorByStr("EnumFilterCriterionTypes", enumeratorString.c_str(), ord)) { + data->criterionType = ord; + data->criterionType |= Filter::_TYPE_ENUM; + } + else if (strcmp(name, "FILTER") == 0) { + data->criterionType = ord; + data->criterionType |= Filter::_TYPE_FILTER; + } + else throw XMLParseException("Unexpected element (unknown criterion)!", name, data->pParser); + + XML_Char const* cmpOp = GetAttribute("op", atts); + if (cmpOp != NULL) { + if (strcmp(cmpOp, "gt") == 0) { + if ((data->criterionType & Filter::_TYPE_FILTER) == Filter::_TYPE_FILTER) { + throw XMLParseException("Greater than operator not supported for filter criterion types!", name, data->pParser); + } + data->criterionType |= Filter::_REQ_GT; + } + else if (strcmp(cmpOp, "lt") == 0) { + if ((data->criterionType & Filter::_TYPE_FILTER) == Filter::_TYPE_FILTER) { + throw XMLParseException("Lesser than operator not supported for filter criterion types!", name, data->pParser); + } + data->criterionType |= Filter::_REQ_LT; + } + else if (strcmp(cmpOp, "eq") == 0) data->criterionType |= Filter::_REQ_EQ; + else if (strcmp(cmpOp, "btwn") == 0) { + if ((data->criterionType & Filter::_TYPE_INTEGER) != Filter::_TYPE_INTEGER) { + // TODO: also allow between for enums + throw XMLParseException("Between operator only handles numerical values!", name, data->pParser); + } + data->criterionType |= Filter::_REQ_BTWN | Filter::_TYPE_PAIR; + } + else if (strcmp(cmpOp, "in") == 0) { + if (data->criterionType & (Filter::_TYPE_INTEGER | Filter::_TYPE_STRING)) { + // TODO: also allow in for enums + data->criterionType |= Filter::_REQ_IN | Filter::_TYPE_LIST; + } + else throw XMLParseException("In operator only handles numerical or string values!", name, data->pParser); + } + else throw XMLParseException("Undefined operator!", name, data->pParser); + } + else { + data->criterionType |= Filter::_REQ_EQ; + } + XML_Char const* not = GetAttribute("not", atts); + if (not != NULL) { + if (strcmp(not, "") != 0) throw XMLParseException("Not attribute must not have a value assigned!", name, data->pParser); + data->criterionType |= Filter::_REQ_NOT; + } + break; + } + default: + throw XMLParseException("Unexpected element!", name, data->pParser); + } + } + + void XMLCALL FilterDB::EndElementHandle(void* userData, const XML_Char* name) { + ParseData* data = (ParseData*)userData; + switch (data->state) { + case E_CRITERION: + if (strcmp(name, data->criterionName.c_str()) == 0) { + data->state = E_OPERATION; + break; + } + case E_OPERATION: + if (((data->operationFlags & Filter::_REQ_AND) && strcmp(name, "AND") == 0) || ((data->operationFlags & Filter::_REQ_OR) && strcmp(name, "OR") == 0)) { + data->state = E_ELEMENT_FILTER; + break; + } + case E_ELEMENT_FILTER: + if (strcmp(name, "Filter") == 0) { + data->state = E_ELEMENT_FILTERS; + if (!Instance().AddFilter(data->filterName, data->currentFilter)) { + throw XMLParseException("Filter could not be added. Filter already defined!", name, data->pParser); + } + data->currentFilter = NULL; // in case an exception is raised between here and the start of the next filter element + break; + } + case E_ELEMENT_FILTERS: + if (strcmp(name, "Filters") == 0) { + data->state = E_NONE; + break; + } + default: + throw XMLParseException("Unexpected element! Closing tag missing?", name, data->pParser); + return; + } + } + + void XMLCALL FilterDB::CharacterDataHandle(void* userData, const XML_Char* str, int len) { + ParseData* data = (ParseData*)userData; + switch (data->state) { + case E_CRITERION: + // TODO: trim character data! + char* text = new char[len + 1]; + strncpy(text, str, len); + text[len] = '\0'; + if (data->criterionType & Filter::_TYPE_STRING) { + STR16 wStr = NULL; + int len = MultiByteToWideChar(CP_UTF8, 0, text, -1, wStr, 0); + wStr = (STR16)MemAlloc(len * sizeof(CHAR16)); + MultiByteToWideChar(CP_UTF8, 0, text, -1, wStr, len); + if (data->criterionType & Filter::_TYPE_LIST) { + Filter::StringList list; + wchar_t* token = wcstok(wStr, L", "); + while (token != NULL) { + list.push_back(token); + token = wcstok(NULL, L", "); + } + data->currentFilter->AddCriterion(data->operationFlags | data->criterionType, list); + } + else { + data->currentFilter->AddCriterion(data->operationFlags | data->criterionType, wStr); + } + MemFree(wStr); + } + else if (data->criterionType & Filter::_TYPE_INTEGER) { + if ((data->criterionType & Filter::_TYPE_LIST) || (data->criterionType & Filter::_TYPE_PAIR)) { + Filter::NumberList list; + char* token = strtok(text, ", "); + while (token != NULL) { + INT32 val; + if (!ConvertStringToINT32(token, &val)) { + delete text; + throw XMLParseException("Invalid value!", data->criterionName.c_str(), data->pParser); + } + list.push_back(val); + token = strtok(NULL, ", "); + } + if (data->criterionType & Filter::_TYPE_PAIR) { + if (list.size() != 2) { + delete text; + throw XMLParseException("Exactly 2 operands must be specified for 'between' operator!", data->criterionName.c_str(), data->pParser); + } + data->currentFilter->AddCriterion(data->operationFlags | data->criterionType, list.front(), list.back()); + } + else if (data->criterionType & Filter::_TYPE_LIST) { + data->currentFilter->AddCriterion(data->operationFlags | data->criterionType, list); + } + } + else { + INT32 val; + if (!ConvertStringToINT32(text, &val)) { + delete text; + throw XMLParseException("Invalid value!", data->criterionName.c_str(), data->pParser); + } + data->currentFilter->AddCriterion(data->operationFlags | data->criterionType, val); + } + } + else if (data->criterionType & Filter::_TYPE_ENUM) { + INT32 ord; + if (EnumeratorDB::Instance().GetEnumeratorByStr(data->criterionName.c_str(), text, ord)) { + // For the filter no enum type exists. + // Since we now know the integer value of the enumerator we treat it like any other integer criterion + data->criterionType &= ~Filter::_TYPE_ENUM; + data->criterionType |= Filter::_TYPE_INTEGER; + data->currentFilter->AddCriterion(data->operationFlags | data->criterionType, ord); + } + else { + delete text; + throw XMLParseException("Can't find specified enumerator!", data->criterionName.c_str(), data->pParser); + } + } + else if (data->criterionType & Filter::_TYPE_FILTER) { + Filter* f = Instance().FindFilter(text); + if (f == NULL) { + throw XMLParseException("Can't find specified filter. Make sure it is defined before the filter that references it!", data->criterionName.c_str(), data->pParser); + } + data->currentFilter->AddCriterion(data->operationFlags | data->criterionType, f); + } + delete text; + break; + } + } + + void FilterDB::RegisterEnumerators() { + + /***************************************** + Filter string criterion types + ******************************************/ + LOGBT_ENUMDB_ADD("StringFilterCriterionTypes", 3, + Filter::REQ_NAME, + Filter::REQ_PROFILENAME, + Filter::REQ_NICKNAME + ); + + /***************************************** + Filter enum criterion types + ******************************************/ + LOGBT_ENUMDB_ADD("IntegerFilterCriterionTypes", 32, + Filter::REQ_HELMETPOS, + Filter::REQ_VESTPOS, + Filter::REQ_LEGPOS, + Filter::REQ_HEAD1POS, + Filter::REQ_HEAD2POS, + Filter::REQ_HANDPOS, + Filter::REQ_SECONDHANDPOS, + Filter::REQ_VESTPOCKPOS, + Filter::REQ_LTHIGHPOCKPOS, + Filter::REQ_RTHIGHPOCKPOS, + Filter::REQ_CPACKPOCKPOS, + Filter::REQ_BPACKPOCKPOS, + Filter::REQ_GUNSLINGPOCKPOS, + Filter::REQ_KNIFEPOCKPOS, + Filter::REQ_TEAM, + Filter::REQ_CAMO, + Filter::REQ_URBANCAMO, + Filter::REQ_DESERTCAMO, + Filter::REQ_SNOWCAMO, + Filter::REQ_EXPLEVEL, + Filter::REQ_STRENGTH, + Filter::REQ_LEADERSHIP, + Filter::REQ_WISDOM, + Filter::REQ_SKILLTRAIT1, + Filter::REQ_SKILLTRAIT2, + Filter::REQ_FACEINDEX, + Filter::REQ_WEAPON_IN_HAND, + Filter::REQ_CALIBRE, + Filter::REQ_VEST_AMOR_PROTECTION, + Filter::REQ_VEST_AMOR_COVERAGE, + Filter::REQ_HELMET_AMOR_PROTECTION, + Filter::REQ_HELMET_AMOR_COVERAGE + ); + + /***************************************** + Filter enum criterion types + ******************************************/ + LOGBT_ENUMDB_ADD("EnumFilterCriterionTypes", 7, + Filter::REQ_SEX, + Filter::REQ_MERC_TYPE, + Filter::REQ_SOLDIER_CLASS, + Filter::REQ_CIVILIANGROUP, + Filter::REQ_BODYTYPE, + Filter::REQ_WEAPON_CLASS, + Filter::REQ_WEAPON_TYPE + ); + + /***************************************** + MERC_TYPE + ******************************************/ + LOGBT_ENUMDB_ADD("MERC_TYPE", 7, + MERC_TYPE__PLAYER_CHARACTER, + MERC_TYPE__AIM_MERC, + MERC_TYPE__MERC, + MERC_TYPE__NPC, + MERC_TYPE__EPC, + MERC_TYPE__NPC_WITH_UNEXTENDABLE_CONTRACT, + MERC_TYPE__VEHICLE + ); + + /***************************************** + SOLDIER_CLASS + ******************************************/ + LOGBT_ENUMDB_ADD("SOLDIER_CLASS", SOLDIER_CLASS_MAX, + SOLDIER_CLASS_NONE, + SOLDIER_CLASS_ADMINISTRATOR, + SOLDIER_CLASS_ELITE, + SOLDIER_CLASS_ARMY, + SOLDIER_CLASS_GREEN_MILITIA, + SOLDIER_CLASS_REG_MILITIA, + SOLDIER_CLASS_ELITE_MILITIA, + SOLDIER_CLASS_CREATURE, + SOLDIER_CLASS_MINER, + SOLDIER_CLASS_ZOMBIE, + SOLDIER_CLASS_TANK, + SOLDIER_CLASS_JEEP, + SOLDIER_CLASS_BANDIT + ); + + /***************************************** + Filter enum criterion types + ******************************************/ + LOGBT_ENUMDB_ADD("SEX", 2, + MALE, + FEMALE + ); + + /***************************************** + SoldierBodyTypes + ******************************************/ + LOGBT_ENUMDB_ADD("BODYTYPE", TOTALBODYTYPES, + REGMALE, + BIGMALE, + STOCKYMALE, + REGFEMALE, + ADULTFEMALEMONSTER, + AM_MONSTER, + YAF_MONSTER, + YAM_MONSTER, + LARVAE_MONSTER, + INFANT_MONSTER, + QUEENMONSTER, + FATCIV, + MANCIV, + MINICIV, + DRESSCIV, + HATKIDCIV, + KIDCIV, + CRIPPLECIV, + COW, + CROW, + BLOODCAT, + ROBOTNOWEAPON, + HUMVEE, + TANK_NW, + TANK_NE, + ELDORADO, + ICECREAMTRUCK, + JEEP, + COMBAT_JEEP + ); + + /***************************************** + Civilian Groups + ******************************************/ + LOGBT_ENUMDB_ADD("CIVILIANGROUP", NUM_CIV_GROUPS, + NON_CIV_GROUP, + REBEL_CIV_GROUP, + KINGPIN_CIV_GROUP, + SANMONA_ARMS_GROUP, + ANGELS_GROUP, + BEGGARS_CIV_GROUP, + TOURISTS_CIV_GROUP, + ALMA_MILITARY_CIV_GROUP, + DOCTORS_CIV_GROUP, + COUPLE1_CIV_GROUP, + HICKS_CIV_GROUP, + WARDEN_CIV_GROUP, + JUNKYARD_CIV_GROUP, + FACTORY_KIDS_GROUP, + QUEENS_CIV_GROUP, + UNNAMED_CIV_GROUP_15, + UNNAMED_CIV_GROUP_16, + UNNAMED_CIV_GROUP_17, + UNNAMED_CIV_GROUP_18, + UNNAMED_CIV_GROUP_19, + ASSASSIN_CIV_GROUP, + POW_PRISON_CIV_GROUP, + UNNAMED_CIV_GROUP_22, + UNNAMED_CIV_GROUP_23, + VOLUNTEER_CIV_GROUP, + BOUNTYHUNTER_CIV_GROUP, + DOWNEDPILOT_CIV_GROUP, + SCIENTIST_GROUP, + RADAR_TECHNICIAN_GROUP, + AIRPORT_STAFF_GROUP, + BARRACK_STAFF_GROUP, + FACTORY_GROUP, + ADMINISTRATIVE_STAFF_GROUP, + LOYAL_CIV_GROUP, + BLACKMARKET_GROUP, + UNNAMED_CIV_GROUP_35, + UNNAMED_CIV_GROUP_36, + UNNAMED_CIV_GROUP_37, + UNNAMED_CIV_GROUP_38, + UNNAMED_CIV_GROUP_39, + UNNAMED_CIV_GROUP_40, + UNNAMED_CIV_GROUP_41, + UNNAMED_CIV_GROUP_42, + UNNAMED_CIV_GROUP_43, + UNNAMED_CIV_GROUP_44, + UNNAMED_CIV_GROUP_45, + UNNAMED_CIV_GROUP_46, + UNNAMED_CIV_GROUP_47, + UNNAMED_CIV_GROUP_48, + UNNAMED_CIV_GROUP_49, + UNNAMED_CIV_GROUP_50, + UNNAMED_CIV_GROUP_51, + UNNAMED_CIV_GROUP_52, + UNNAMED_CIV_GROUP_53, + UNNAMED_CIV_GROUP_54, + UNNAMED_CIV_GROUP_55, + UNNAMED_CIV_GROUP_56, + UNNAMED_CIV_GROUP_57, + UNNAMED_CIV_GROUP_58, + UNNAMED_CIV_GROUP_59, + UNNAMED_CIV_GROUP_60, + UNNAMED_CIV_GROUP_61, + UNNAMED_CIV_GROUP_62, + UNNAMED_CIV_GROUP_63, + UNNAMED_CIV_GROUP_64, + UNNAMED_CIV_GROUP_65, + UNNAMED_CIV_GROUP_66, + UNNAMED_CIV_GROUP_67, + UNNAMED_CIV_GROUP_68, + UNNAMED_CIV_GROUP_69, + UNNAMED_CIV_GROUP_70, + UNNAMED_CIV_GROUP_71, + UNNAMED_CIV_GROUP_72, + UNNAMED_CIV_GROUP_73, + UNNAMED_CIV_GROUP_74, + UNNAMED_CIV_GROUP_75, + UNNAMED_CIV_GROUP_76, + UNNAMED_CIV_GROUP_77, + UNNAMED_CIV_GROUP_78, + UNNAMED_CIV_GROUP_79, + UNNAMED_CIV_GROUP_80, + UNNAMED_CIV_GROUP_81, + UNNAMED_CIV_GROUP_82, + UNNAMED_CIV_GROUP_83, + UNNAMED_CIV_GROUP_84, + UNNAMED_CIV_GROUP_85, + UNNAMED_CIV_GROUP_86, + UNNAMED_CIV_GROUP_87, + UNNAMED_CIV_GROUP_88, + UNNAMED_CIV_GROUP_89, + UNNAMED_CIV_GROUP_90, + UNNAMED_CIV_GROUP_91, + UNNAMED_CIV_GROUP_92, + UNNAMED_CIV_GROUP_93, + UNNAMED_CIV_GROUP_94, + UNNAMED_CIV_GROUP_95, + UNNAMED_CIV_GROUP_96, + UNNAMED_CIV_GROUP_97, + UNNAMED_CIV_GROUP_98, + UNNAMED_CIV_GROUP_99, + UNNAMED_CIV_GROUP_100, + UNNAMED_CIV_GROUP_101, + UNNAMED_CIV_GROUP_102, + UNNAMED_CIV_GROUP_103, + UNNAMED_CIV_GROUP_104, + UNNAMED_CIV_GROUP_105, + UNNAMED_CIV_GROUP_106, + UNNAMED_CIV_GROUP_107, + UNNAMED_CIV_GROUP_108, + UNNAMED_CIV_GROUP_109, + UNNAMED_CIV_GROUP_110, + UNNAMED_CIV_GROUP_111, + UNNAMED_CIV_GROUP_112, + UNNAMED_CIV_GROUP_113, + UNNAMED_CIV_GROUP_114, + UNNAMED_CIV_GROUP_115, + UNNAMED_CIV_GROUP_116, + UNNAMED_CIV_GROUP_117, + UNNAMED_CIV_GROUP_118, + UNNAMED_CIV_GROUP_119, + UNNAMED_CIV_GROUP_120, + UNNAMED_CIV_GROUP_121, + UNNAMED_CIV_GROUP_122, + UNNAMED_CIV_GROUP_123, + UNNAMED_CIV_GROUP_124, + UNNAMED_CIV_GROUP_125, + UNNAMED_CIV_GROUP_126, + UNNAMED_CIV_GROUP_127, + UNNAMED_CIV_GROUP_128, + UNNAMED_CIV_GROUP_129, + UNNAMED_CIV_GROUP_130, + UNNAMED_CIV_GROUP_131, + UNNAMED_CIV_GROUP_132, + UNNAMED_CIV_GROUP_133, + UNNAMED_CIV_GROUP_134, + UNNAMED_CIV_GROUP_135, + UNNAMED_CIV_GROUP_136, + UNNAMED_CIV_GROUP_137, + UNNAMED_CIV_GROUP_138, + UNNAMED_CIV_GROUP_139, + UNNAMED_CIV_GROUP_140, + UNNAMED_CIV_GROUP_141, + UNNAMED_CIV_GROUP_142, + UNNAMED_CIV_GROUP_143, + UNNAMED_CIV_GROUP_144, + UNNAMED_CIV_GROUP_145, + UNNAMED_CIV_GROUP_146, + UNNAMED_CIV_GROUP_147, + UNNAMED_CIV_GROUP_148, + UNNAMED_CIV_GROUP_149, + UNNAMED_CIV_GROUP_150, + UNNAMED_CIV_GROUP_151, + UNNAMED_CIV_GROUP_152, + UNNAMED_CIV_GROUP_153, + UNNAMED_CIV_GROUP_154, + UNNAMED_CIV_GROUP_155, + UNNAMED_CIV_GROUP_156, + UNNAMED_CIV_GROUP_157, + UNNAMED_CIV_GROUP_158, + UNNAMED_CIV_GROUP_159, + UNNAMED_CIV_GROUP_160, + UNNAMED_CIV_GROUP_161, + UNNAMED_CIV_GROUP_162, + UNNAMED_CIV_GROUP_163, + UNNAMED_CIV_GROUP_164, + UNNAMED_CIV_GROUP_165, + UNNAMED_CIV_GROUP_166, + UNNAMED_CIV_GROUP_167, + UNNAMED_CIV_GROUP_168, + UNNAMED_CIV_GROUP_169, + UNNAMED_CIV_GROUP_170, + UNNAMED_CIV_GROUP_171, + UNNAMED_CIV_GROUP_172, + UNNAMED_CIV_GROUP_173, + UNNAMED_CIV_GROUP_174, + UNNAMED_CIV_GROUP_175, + UNNAMED_CIV_GROUP_176, + UNNAMED_CIV_GROUP_177, + UNNAMED_CIV_GROUP_178, + UNNAMED_CIV_GROUP_179, + UNNAMED_CIV_GROUP_180, + UNNAMED_CIV_GROUP_181, + UNNAMED_CIV_GROUP_182, + UNNAMED_CIV_GROUP_183, + UNNAMED_CIV_GROUP_184, + UNNAMED_CIV_GROUP_185, + UNNAMED_CIV_GROUP_186, + UNNAMED_CIV_GROUP_187, + UNNAMED_CIV_GROUP_188, + UNNAMED_CIV_GROUP_189, + UNNAMED_CIV_GROUP_190, + UNNAMED_CIV_GROUP_191, + UNNAMED_CIV_GROUP_192, + UNNAMED_CIV_GROUP_193, + UNNAMED_CIV_GROUP_194, + UNNAMED_CIV_GROUP_195, + UNNAMED_CIV_GROUP_196, + UNNAMED_CIV_GROUP_197, + UNNAMED_CIV_GROUP_198, + UNNAMED_CIV_GROUP_199, + UNNAMED_CIV_GROUP_200, + UNNAMED_CIV_GROUP_201, + UNNAMED_CIV_GROUP_202, + UNNAMED_CIV_GROUP_203, + UNNAMED_CIV_GROUP_204, + UNNAMED_CIV_GROUP_205, + UNNAMED_CIV_GROUP_206, + UNNAMED_CIV_GROUP_207, + UNNAMED_CIV_GROUP_208, + UNNAMED_CIV_GROUP_209, + UNNAMED_CIV_GROUP_210, + UNNAMED_CIV_GROUP_211, + UNNAMED_CIV_GROUP_212, + UNNAMED_CIV_GROUP_213, + UNNAMED_CIV_GROUP_214, + UNNAMED_CIV_GROUP_215, + UNNAMED_CIV_GROUP_216, + UNNAMED_CIV_GROUP_217, + UNNAMED_CIV_GROUP_218, + UNNAMED_CIV_GROUP_219, + UNNAMED_CIV_GROUP_220, + UNNAMED_CIV_GROUP_221, + UNNAMED_CIV_GROUP_222, + UNNAMED_CIV_GROUP_223, + UNNAMED_CIV_GROUP_224, + UNNAMED_CIV_GROUP_225, + UNNAMED_CIV_GROUP_226, + UNNAMED_CIV_GROUP_227, + UNNAMED_CIV_GROUP_228, + UNNAMED_CIV_GROUP_229, + UNNAMED_CIV_GROUP_230, + UNNAMED_CIV_GROUP_231, + UNNAMED_CIV_GROUP_232, + UNNAMED_CIV_GROUP_233, + UNNAMED_CIV_GROUP_234, + UNNAMED_CIV_GROUP_235, + UNNAMED_CIV_GROUP_236, + UNNAMED_CIV_GROUP_237, + UNNAMED_CIV_GROUP_238, + UNNAMED_CIV_GROUP_239, + UNNAMED_CIV_GROUP_240, + UNNAMED_CIV_GROUP_241, + UNNAMED_CIV_GROUP_242, + UNNAMED_CIV_GROUP_243, + UNNAMED_CIV_GROUP_244, + UNNAMED_CIV_GROUP_245, + UNNAMED_CIV_GROUP_246, + UNNAMED_CIV_GROUP_247, + UNNAMED_CIV_GROUP_248, + UNNAMED_CIV_GROUP_249, + UNNAMED_CIV_GROUP_250, + UNNAMED_CIV_GROUP_251, + UNNAMED_CIV_GROUP_252, + UNNAMED_CIV_GROUP_253, + UNNAMED_CIV_GROUP_254 + ); + + /***************************************** + Weapon Class + ******************************************/ + LOGBT_ENUMDB_ADD("WEAPON_CLASS", NUM_WEAPON_CLASSES, + NOGUNCLASS, + HANDGUNCLASS, + SMGCLASS, + RIFLECLASS, + MGCLASS, + SHOTGUNCLASS, + KNIFECLASS, + MONSTERCLASS + ); + + /***************************************** + Weapon Type + ******************************************/ + LOGBT_ENUMDB_ADD("WEAPON_TYPE", GUN_TYPES_MAX, + NOT_GUN, + GUN_PISTOL, + GUN_M_PISTOL, + GUN_SMG, + GUN_RIFLE, + GUN_SN_RIFLE, + GUN_AS_RIFLE, + GUN_LMG, + GUN_SHOTGUN + ); + + }; + +} diff --git a/Tactical/LogicalBodyTypes/FilterDB.h b/Tactical/LogicalBodyTypes/FilterDB.h new file mode 100644 index 00000000..1d5dc2b9 --- /dev/null +++ b/Tactical/LogicalBodyTypes/FilterDB.h @@ -0,0 +1,68 @@ +#pragma once +#ifndef _LBT_FILTERDB__H_ +#define _LBT_FILTERDB__H_ + +#include "LogicalBodyTypes/AbstractXMLLoader.h" +#include "Animation Data.h" +#include "Weapons.h" +#include "LogicalBodyTypes/EnumeratorDB.h" +#include "LogicalBodyTypes/Filter.h" +#include + +namespace LogicalBodyTypes { + +class FilterDB : public AbstractXMLLoader, public Singleton { + +public: + using Singleton ::Instance; + typedef std::map FilterMap; + typedef FilterMap::const_iterator iterator; + +private: + enum ParseState { + E_ELEMENT_FILTERS = FIRST_SUBCLASS_STATE, + E_ELEMENT_FILTER, + E_OPERATION, + E_CRITERION + }; + struct ParseData : public AbstractXMLLoader::ParseData { // shadow ParseData type and also extend the ParseData stuct of the base class + ParseData(XML_Parser* parser) : AbstractXMLLoader::ParseData(parser) { + currentFilter = NULL; + operationFlags = 0; + criterionName = ""; + criterionType = 0; + }; + ~ParseData() { + // don't like this one bit, but we have to handle this here in case an exception is thrown + // remember to set the pointer to NULL after the filter object has been added to the DB! + if (currentFilter != NULL) delete currentFilter; + }; + Filter* currentFilter; + std::string filterName; + UINT32 operationFlags; + std::string criterionName; + UINT32 criterionType; + } typedef ParseData; + FilterMap filters; + +public: + FilterDB(void); + ~FilterDB(void); + FilterMap::const_iterator begin(); + FilterMap::const_iterator end(); + Filter* FindFilter(std::string name); + +private: + bool AddFilter(std::string name, Filter* filter); + static void RegisterEnumerators(); + static void XMLCALL StartElementHandle(void* userData, const XML_Char* name, const XML_Char** atts); + static void XMLCALL EndElementHandle(void* userData, const XML_Char* name); + static void XMLCALL CharacterDataHandle(void* userData, const XML_Char* str, int len); + static void XMLCALL ExternalEntityHandler(XML_Parser parser, const XML_Char* context, const XML_Char* base, const XML_Char* systemId, const XML_Char* publicId); + static AbstractXMLLoader::ParseData* MakeParseData(XML_Parser* parser); // shadow factory function for ParseData instances + +}; + +} + +#endif diff --git a/Tactical/LogicalBodyTypes/Layers.cpp b/Tactical/LogicalBodyTypes/Layers.cpp new file mode 100644 index 00000000..419f218f --- /dev/null +++ b/Tactical/LogicalBodyTypes/Layers.cpp @@ -0,0 +1,202 @@ +#include "Layers.h" +#include +#include + +namespace LogicalBodyTypes { + +Layers::Layers() : AbstractXMLLoader(StartElementHandle, EndElementHandle, CharacterDataHandle, MakeParseData) { + directionLayerGraphs.resize(NUM_WORLD_DIRECTIONS); +} + +Layers::~Layers(void) { + for (LayerPropertiesVector::size_type i = 0; i < layers.size(); i++) { + delete[] layers[i].identifier; + } +} + +Layers::LayerGraphIterator Layers::GetIterator(WorldDirections direction) { + return directionLayerGraphs[direction].begin(); +} + +Layers::LayerGraphIterator Layers::GetIterationEnd(WorldDirections direction) { + return directionLayerGraphs[direction].end(); +} + +Layers::LayerGraphIterator Layers::GetIterator(INT8 direction) { + return directionLayerGraphs[direction].begin(); +} + +Layers::LayerGraphIterator Layers::GetIterationEnd(INT8 direction) { + + return directionLayerGraphs[direction].end(); +} + +AbstractXMLLoader::ParseData* Layers::MakeParseData(XML_Parser* parser) { + return new ParseData(parser); +} + +void Layers::AddLayerGraphNode(WorldDirections dir, std::string identifier, bool render, bool renderShadows, INT32 zIndex) { + // create layer property object and push it into the layers properties container - if layer not already there + Layers::LayerPropertiesVector::size_type index = GetIndex(identifier); + if (index == -1) { + LayerProperties props; + props.identifier = new char[identifier.size() + 1]; + strcpy(props.identifier, identifier.c_str()); + props.render = render; + props.renderShadows = renderShadows; + layers.push_back(props); + index = GetIndex(identifier); + } + + // create node with zindex and a pointer to the layer properties object + LayerGraphNode node; + node.zIndex = zIndex; + node.index = index; + node.pLayerProperties = NULL; // since the pointers would be invalided once the vector has to be reallocated, + // we set the pointers after the layer configuration is finalized (see UpdateConfiguration) + + // add node to direction specific layer graph + LayerGraph::iterator i = directionLayerGraphs[dir].begin(); + for (; i != directionLayerGraphs[dir].end(); i++) { + if (i->zIndex > zIndex) break; + } + directionLayerGraphs[dir].insert(i, node); +} + +void Layers::UpdateConfiguration() { + for (int d = NORTH; d < NUM_WORLD_DIRECTIONS; ++d) { + WorldDirections dir = static_cast(d); + LayerGraph::iterator i = directionLayerGraphs[dir].begin(); + for (; i != directionLayerGraphs[dir].end(); i++) { + i->pLayerProperties = &layers[i->index]; + } + } +} + +Layers::LayerPropertiesVector::size_type Layers::GetCount() { + return layers.size(); +} + +Layers::LayerPropertiesVector::size_type Layers::GetIndex(std::string& identifier) { + for (LayerPropertiesVector::size_type i = 0; i < layers.size(); i++) { + if (strcmp(layers[i].identifier, identifier.c_str()) == 0) return i; + } + return -1; +} + +const Layers::LayerProperties& Layers::GetLayerProperties(LayerPropertiesVector::size_type index) { + return layers[index]; +} + +void Layers::StartElementHandle(void* userData, const XML_Char* name, const XML_Char** atts) { + ParseData* data = (ParseData*)userData; + switch (data->state) { + case E_NONE: + if (strcmp(name, "Layers") == 0) { + data->level = 0; + data->state = E_ELEMENT_LAYERS; + break; + } + case E_ELEMENT_LAYERS: + case E_ELEMENT_LAYER: + if (strcmp(name, "Layer") == 0) { + data->level++; + data->state = E_ELEMENT_LAYER; + XML_Char const* attrName = GetAttribute("name", atts); + XML_Char const* attrRender = GetAttribute("render", atts); + XML_Char const* attrShadow = GetAttribute("shadow", atts); + XML_Char const* attrDirNorth = GetAttribute("zindex_north", atts); + XML_Char const* attrDirNorthEast = GetAttribute("zindex_northeast", atts); + XML_Char const* attrDirEast = GetAttribute("zindex_east", atts); + XML_Char const* attrDirSouthEast = GetAttribute("zindex_southeast", atts); + XML_Char const* attrDirSouth = GetAttribute("zindex_south", atts); + XML_Char const* attrDirSouthWest = GetAttribute("zindex_southwest", atts); + XML_Char const* attrDirWest = GetAttribute("zindex_west", atts); + XML_Char const* attrDirNorthWest = GetAttribute("zindex_northwest", atts); + if (attrName == NULL || attrRender == NULL || attrShadow == NULL) { + throw XMLParseException("Mandatory attribute missing!", name, data->pParser); + } + BOOLEAN fRender; + if (!ConvertStringToBOOLEAN(attrRender, &fRender)) throw XMLParseException("Attribute 'value' doesn't have a valid value!", name, data->pParser); + BOOLEAN fShadow; + if (!ConvertStringToBOOLEAN(attrShadow, &fShadow)) throw XMLParseException("Attribute 'shadow' doesn't have a valid value!", name, data->pParser); + INT32 value; + if (attrDirNorth != NULL) { + if (!ConvertStringToINT32(attrDirNorth, &value)) throw XMLParseException("Attribute 'zindex_north' doesn't have a valid value!", name, data->pParser); + data->directionZStacks[NORTH].push(ZLevelPair(data->level, value)); + } + if (attrDirNorthEast != NULL) { + if (!ConvertStringToINT32(attrDirNorthEast, &value)) throw XMLParseException("Attribute 'zindex_northeast' doesn't have a valid value!", name, data->pParser); + data->directionZStacks[NORTHEAST].push(ZLevelPair(data->level, value)); + } + if (attrDirEast != NULL) { + if (!ConvertStringToINT32(attrDirEast, &value)) throw XMLParseException("Attribute 'zindex_east' doesn't have a valid value!", name, data->pParser); + data->directionZStacks[EAST].push(ZLevelPair(data->level, value)); + } + if (attrDirSouthEast != NULL) { + if (!ConvertStringToINT32(attrDirSouthEast, &value)) throw XMLParseException("Attribute 'zindex_southeast' doesn't have a valid value!", name, data->pParser); + data->directionZStacks[SOUTHEAST].push(ZLevelPair(data->level, value)); + } + if (attrDirSouth != NULL) { + if (!ConvertStringToINT32(attrDirSouth, &value)) throw XMLParseException("Attribute 'zindex_south' doesn't have a valid value!", name, data->pParser); + data->directionZStacks[SOUTH].push(ZLevelPair(data->level, value)); + } + if (attrDirSouthWest != NULL) { + if (!ConvertStringToINT32(attrDirSouthWest, &value)) throw XMLParseException("Attribute 'zindex_southwest' doesn't have a valid value!", name, data->pParser); + data->directionZStacks[SOUTHWEST].push(ZLevelPair(data->level, value)); + } + if (attrDirWest != NULL) { + if (!ConvertStringToINT32(attrDirWest, &value)) throw XMLParseException("Attribute 'zindex_west' doesn't have a valid value!", name, data->pParser); + data->directionZStacks[WEST].push(ZLevelPair(data->level, value)); + } + if (attrDirNorthWest != NULL) { + if (!ConvertStringToINT32(attrDirNorthWest, &value)) throw XMLParseException("Attribute 'zindex_northwest' doesn't have a valid value!", name, data->pParser); + data->directionZStacks[NORTHWEST].push(ZLevelPair(data->level, value)); + } + + for (int d = NORTH; d < NUM_WORLD_DIRECTIONS; ++d) { + WorldDirections dir = static_cast(d); + INT32 value = 0; + if (!data->directionZStacks[dir].empty()) { + value = data->directionZStacks[dir].top().second; + } + Instance().AddLayerGraphNode(dir, attrName, fRender == TRUE, fShadow == TRUE, value); + } + break; + } + default: + throw XMLParseException("Unexpected element!", name, data->pParser); + } +} + +void Layers::EndElementHandle(void* userData, const XML_Char* name) { + ParseData* data = (ParseData*)userData; + switch (data->state) { + case E_ELEMENT_LAYER: + if (strcmp(name, "Layer") == 0) { + for (int d = NORTH; d < NUM_WORLD_DIRECTIONS; ++d) { + if (!data->directionZStacks[static_cast(d)].empty()) { + if (data->directionZStacks[static_cast(d)].top().first == data->level) { + data->directionZStacks[d].pop(); + } + } + } + if (--data->level == 0) data->state = E_ELEMENT_LAYERS; + break; + } + case E_ELEMENT_LAYERS: + if (strcmp(name, "Layers") == 0) { + data->state = E_NONE; + Instance().UpdateConfiguration(); + break; + } + default: + throw XMLParseException("Unexpected element! Closing tag missing?", name, data->pParser); + return; + } +} + +void Layers::CharacterDataHandle(void* userData, const XML_Char* str, int len) { +} + +} diff --git a/Tactical/LogicalBodyTypes/Layers.h b/Tactical/LogicalBodyTypes/Layers.h new file mode 100644 index 00000000..990c5000 --- /dev/null +++ b/Tactical/LogicalBodyTypes/Layers.h @@ -0,0 +1,74 @@ +#pragma once +#ifndef _LBT_LAYERS__H_ +#define _LBT_LAYERS__H_ + +#include "LogicalBodyTypes/AbstractXMLLoader.h" +#include + +namespace LogicalBodyTypes { + +// Layers configuration implemented as singleton and loadable from XML. +class Layers : public AbstractXMLLoader, public Singleton { + +public: + using Singleton ::Instance; + struct LayerProperties { + char* identifier; + bool render; + bool renderShadows; + } typedef LayerProperties; + typedef std::vector LayerPropertiesVector; + +private: + enum ParseState { + E_ELEMENT_LAYERS = FIRST_SUBCLASS_STATE, + E_ELEMENT_LAYER + }; + typedef std::pair ZLevelPair; + typedef std::stack ZStack; + typedef std::vector ZStackVector; + struct ParseData : public AbstractXMLLoader::ParseData { // shadow ParseData type and also extend the ParseData stuct of the base class + ParseData(XML_Parser* parser) : AbstractXMLLoader::ParseData(parser) + { + directionZStacks.resize(NUM_WORLD_DIRECTIONS); + }; + ZStackVector directionZStacks; + } typedef ParseData; + struct LayerGraphNode { + INT32 zIndex; + LayerPropertiesVector::size_type index; + LayerProperties* pLayerProperties; + } typedef LayerGraphNode; + typedef std::list LayerGraph; + typedef std::vector LayerGraphsVector; + LayerPropertiesVector layers; + LayerGraphsVector directionLayerGraphs; + +public: + typedef LayerGraph::iterator LayerGraphIterator; + +public: + Layers(void); + ~Layers(void); + LayerPropertiesVector::size_type GetCount(); + // returns -1 if layer doesn't exist + LayerPropertiesVector::size_type GetIndex(std::string& identifier); + const Layers::LayerProperties& GetLayerProperties(LayerPropertiesVector::size_type index); + LayerGraphIterator GetIterator(WorldDirections direction); + LayerGraphIterator GetIterationEnd(WorldDirections direction); + LayerGraphIterator GetIterator(INT8 direction); + LayerGraphIterator GetIterationEnd(INT8 direction); + +private: + static void XMLCALL StartElementHandle(void* userData, const XML_Char* name, const XML_Char** atts); + static void XMLCALL CharacterDataHandle(void* userData, const XML_Char* str, int len); + static void XMLCALL EndElementHandle(void* userData, const XML_Char* name); + void AddLayerGraphNode(WorldDirections dir, std::string identifier, bool render, bool renderShadows, INT32 zIndex); + static AbstractXMLLoader::ParseData* MakeParseData(XML_Parser* parser); // shadow factory function for ParseData instances + void UpdateConfiguration(); + +}; + +} + +#endif diff --git a/Tactical/LogicalBodyTypes/PaletteDB.cpp b/Tactical/LogicalBodyTypes/PaletteDB.cpp new file mode 100644 index 00000000..2ef669bc --- /dev/null +++ b/Tactical/LogicalBodyTypes/PaletteDB.cpp @@ -0,0 +1,167 @@ +#include "PaletteDB.h" + +namespace LogicalBodyTypes { + +PaletteDB::PaletteDB(void) : AbstractXMLLoader(StartElementHandle, EndElementHandle, CharacterDataHandle) { +} + +PaletteDB::~PaletteDB(void) { + PaletteTableMap::iterator i = paletteTables.begin(); + for (; i != paletteTables.end(); i++) delete i->second; +} + +bool PaletteDB::AddPaletteTable(std::string name, PaletteTable* paletteTable) { + PaletteTableMap::iterator i = paletteTables.find(name); + if (i != paletteTables.end()) return false; + paletteTables[name] = paletteTable; + return true; +} + +PaletteTable* PaletteDB::FindPaletteTable(std::string name) { + PaletteTableMap::iterator i = paletteTables.find(name); + if (i == paletteTables.end()) return NULL; + return i->second; +} + +void XMLCALL PaletteDB::StartElementHandle(void* userData, const XML_Char* name, const XML_Char** atts) { + ParseData* data = (ParseData*)userData; + switch (data->state) { + case E_NONE: + if (strcmp(name, "Palettes") == 0) { + data->state = E_ELEMENT_PALETTES; + break; + } + case E_ELEMENT_PALETTES: + if (strcmp(name, "Palette") == 0) { + data->state = E_ELEMENT_PALETTE; + XML_Char const* aName = GetAttribute("name", atts); + XML_Char const* aFileName = GetAttribute("filename", atts); + if (aFileName == NULL || aName == NULL) throw XMLParseException("Mandatory attribute missing!", name, data->pParser); + PaletteTable* paletteTable = new PaletteTable(); + if (!paletteTable->Load(aFileName)) throw XMLParseException("Palette table could not be loaded from the specified file!", name, data->pParser); + Instance().AddPaletteTable(aName, paletteTable); + break; + } + default: + throw XMLParseException("Unexpected element!", name, data->pParser); + } +} + +void XMLCALL PaletteDB::EndElementHandle(void* userData, const XML_Char* name) { + ParseData* data = (ParseData*)userData; + switch (data->state) { + case E_ELEMENT_PALETTE: + if (strcmp(name, "Palette") == 0) { + data->state = E_ELEMENT_PALETTES; + break; + } + case E_ELEMENT_PALETTES: + if (strcmp(name, "Palettes") == 0) { + data->state = E_NONE; + break; + } + default: + throw XMLParseException("Unexpected element! Closing tag missing?", name, data->pParser); + return; + } +} + +void XMLCALL PaletteDB::CharacterDataHandle(void* userData, const XML_Char* str, int len) { +} + + +/* +BOOLEAN SOLDIERTYPE::CreateSoldierPalettes( void ) +{ + CHAR8 zColFilename[100]; + INT32 iWhich; + INT32 cnt; + SGPPaletteEntry Temp8BPPPalette[ 256 ]; + + if (this->p8BPPPalette != NULL) { + MemFree(this->p8BPPPalette); + this->p8BPPPalette = NULL; + } + + // Allocate mem for new palette + this->p8BPPPalette = (SGPPaletteEntry *) MemAlloc( sizeof( SGPPaletteEntry ) * 256 ); + memset(this->p8BPPPalette, 0, sizeof(SGPPaletteEntry) * 256); + CHECKF(this->p8BPPPalette != NULL); + + // Use col file + if (CreateSGPPaletteFromCOLFile(Temp8BPPPalette, zColFilename)) { + // Copy into palette + memcpy(this->p8BPPPalette, Temp8BPPPalette, sizeof( this->p8BPPPalette ) * 256); + } else { + } + + if (this->p16BPPPalette != NULL) { + MemFree(this->p16BPPPalette); + this->p16BPPPalette = NULL; + } + + // -- BUILD 16BPP Palette from this + this->p16BPPPalette = Create16BPPPalette(this->p8BPPPalette); + + for (iWhich = 0; iWhich < NUM_SOLDIER_SHADES; iWhich++) { + if (this->pShades[iWhich] != NULL) { + MemFree(this->pShades[iWhich]); + this->pShades[iWhich] = NULL; + } + } + + for (iWhich = 0; iWhich < NUM_SOLDIER_EFFECTSHADES; iWhich++) { + if (this->pEffectShades[iWhich] != NULL) { + MemFree( this->pEffectShades[ iWhich ] ); + this->pEffectShades[iWhich] = NULL; + } + } + + for (iWhich = 0; iWhich < 20; iWhich++) { + if (this->pGlowShades[iWhich] != NULL) { + MemFree( this->pGlowShades[ iWhich ]); + this->pGlowShades[iWhich] = NULL; + } + } + + CreateSoldierPaletteTables( this, HVOBJECT_GLOW_GREEN ); + + this->pEffectShades[0] = Create16BPPPaletteShaded(this->p8BPPPalette, 100, 100, 100, TRUE); + this->pEffectShades[1] = Create16BPPPaletteShaded(this->p8BPPPalette, 100, 150, 100, TRUE); + + // Build shades for glowing visible bad guy + + // First do visible guy + this->pGlowShades[0] = Create16BPPPaletteShaded(this->p8BPPPalette, 255, 255, 255, FALSE); + for (cnt = 1; cnt < 10; cnt++) { + this->pGlowShades[cnt] = CreateEnemyGlow16BPPPalette(this->p8BPPPalette, gRedGlowR[cnt], 255, FALSE); + } + + // Now for gray guy... + this->pGlowShades[10] = Create16BPPPaletteShaded(this->p8BPPPalette, 100, 100, 100, TRUE); + for (cnt = 11; cnt < 19; cnt++) { + this->pGlowShades[cnt] = CreateEnemyGreyGlow16BPPPalette(this->p8BPPPalette, gRedGlowR[cnt], 0, FALSE); + } + this->pGlowShades[19] = CreateEnemyGreyGlow16BPPPalette(this->p8BPPPalette, gRedGlowR[18], 0, FALSE); + + + // ATE: OK, piggyback on the shades we are not using for 2 colored lighting.... + // ORANGE, VISIBLE GUY + this->pShades[20] = Create16BPPPaletteShaded(this->p8BPPPalette, 255, 255, 255, FALSE); + for (cnt = 21; cnt < 30; cnt++) { + this->pShades[cnt] = CreateEnemyGlow16BPPPalette(this->p8BPPPalette, gOrangeGlowR[( cnt - 20 )], gOrangeGlowG[( cnt - 20 )], TRUE); + } + + // ORANGE, GREY GUY + this->pShades[30] = Create16BPPPaletteShaded(this->p8BPPPalette, 100, 100, 100, TRUE); + for (cnt = 31; cnt < 39; cnt++) { + this->pShades[cnt] = CreateEnemyGreyGlow16BPPPalette(this->p8BPPPalette, gOrangeGlowR[(cnt - 20)], gOrangeGlowG[(cnt - 20 )], TRUE); + } + this->pShades[39] = CreateEnemyGreyGlow16BPPPalette(this->p8BPPPalette, gOrangeGlowR[18], gOrangeGlowG[18], TRUE); + + return(TRUE); +} +*/ + + +} diff --git a/Tactical/LogicalBodyTypes/PaletteDB.h b/Tactical/LogicalBodyTypes/PaletteDB.h new file mode 100644 index 00000000..36f2fb8a --- /dev/null +++ b/Tactical/LogicalBodyTypes/PaletteDB.h @@ -0,0 +1,41 @@ +#pragma once +#ifndef _LBT_PALETTEDB__H_ +#define _LBT_PALETTEDB__H_ + +#include +#include "LogicalBodyTypes/Singleton.h" +#include "LogicalBodyTypes/AbstractXMLLoader.h" +#include "LogicalBodyTypes/PaletteTable.h" + +namespace LogicalBodyTypes { + +class PaletteDB : public AbstractXMLLoader, public Singleton { + +public: + using Singleton ::Instance; + typedef std::map PaletteTableMap; + +private: + enum ParseState { + E_ELEMENT_PALETTES = FIRST_SUBCLASS_STATE, + E_ELEMENT_PALETTE + }; + PaletteTableMap paletteTables; + +public: + PaletteDB(void); + ~PaletteDB(void); + bool AddPaletteTable(std::string name, PaletteTable* paletteTable); + PaletteTable* FindPaletteTable(std::string name); + +private: + static void XMLCALL StartElementHandle(void* userData, const XML_Char* name, const XML_Char** atts); + static void XMLCALL EndElementHandle(void* userData, const XML_Char* name); + static void XMLCALL CharacterDataHandle(void* userData, const XML_Char* str, int len); + static void XMLCALL ExternalEntityHandler(XML_Parser parser, const XML_Char* context, const XML_Char* base, const XML_Char* systemId, const XML_Char* publicId); + +}; + +} + +#endif diff --git a/Tactical/LogicalBodyTypes/PaletteTable.cpp b/Tactical/LogicalBodyTypes/PaletteTable.cpp new file mode 100644 index 00000000..d4608013 --- /dev/null +++ b/Tactical/LogicalBodyTypes/PaletteTable.cpp @@ -0,0 +1,102 @@ +#include "PaletteTable.h" + +namespace LogicalBodyTypes { + +PaletteTable::PaletteTable() { +} + +PaletteTable::~PaletteTable() { +} + +bool PaletteTable::CreateSGPPaletteFromActFile(SGPPaletteEntry *pPalette, std::string fileName) { + HWFILE hFileHandle; + UINT32 cnt; + char* colFileName = new char[fileName.size() + 1]; + strcpy(colFileName, fileName.c_str()); + if (!FileExists(colFileName)) { + DebugMsg( TOPIC_JA2, DBG_LEVEL_3, "Cannot find COL file"); + return false; + } + if ((hFileHandle = FileOpen(colFileName, FILE_ACCESS_READ, FALSE)) == 0) { + DebugMsg(TOPIC_JA2, DBG_LEVEL_3, "Cannot open COL file"); + return false; + } + for (cnt = 0; cnt < 256; cnt++) { + FileRead(hFileHandle, &pPalette[cnt].peRed, sizeof(UINT8), NULL); + FileRead(hFileHandle, &pPalette[cnt].peGreen, sizeof(UINT8), NULL); + FileRead(hFileHandle, &pPalette[cnt].peBlue, sizeof(UINT8), NULL); + } + FileClose(hFileHandle); + delete[] colFileName; + return true; +} + +bool PaletteTable::Load(std::string fileName) { + INT32 iWhich; + INT32 cnt; + SGPPaletteEntry Temp8BPPPalette[256]; + + if (this->p8BPPPalette != NULL) { + MemFree(this->p8BPPPalette); + this->p8BPPPalette = NULL; + } + this->p8BPPPalette = (SGPPaletteEntry*)MemAlloc(sizeof(SGPPaletteEntry) * 256); + memset(this->p8BPPPalette, 0, sizeof(SGPPaletteEntry) * 256); + if (CreateSGPPaletteFromActFile(Temp8BPPPalette, (CHAR8*)fileName.c_str())) { + memcpy(this->p8BPPPalette, Temp8BPPPalette, sizeof(this->p8BPPPalette) * 256); + } else { + return false; + } + + if (this->p16BPPPalette != NULL ) { + MemFree(this->p16BPPPalette); + this->p16BPPPalette = NULL; + } + this->p16BPPPalette = Create16BPPPalette(this->p8BPPPalette); + + for (iWhich = 0; iWhich < NUM_SOLDIER_SHADES; iWhich++) { + if (this->pShades[ iWhich ] != NULL) { + MemFree(this->pShades[iWhich]); + this->pShades[ iWhich ] = NULL; + } + } + for (iWhich = 0; iWhich < NUM_SOLDIER_EFFECTSHADES; iWhich++) { + if (this->pEffectShades[iWhich] != NULL) { + MemFree(this->pEffectShades[iWhich]); + this->pEffectShades[iWhich] = NULL; + } + } + for (iWhich = 0; iWhich < 20; iWhich++) { + if (this->pGlowShades[iWhich] != NULL) { + MemFree(this->pGlowShades[iWhich]); + this->pGlowShades[iWhich] = NULL; + } + } + + CreateSoldierPaletteTables(this, HVOBJECT_GLOW_GREEN); + + this->pEffectShades[0] = Create16BPPPaletteShaded(this->p8BPPPalette, 100, 100, 100, TRUE); + this->pEffectShades[1] = Create16BPPPaletteShaded(this->p8BPPPalette, 100, 150, 100, TRUE); + this->pGlowShades[0] = Create16BPPPaletteShaded(this->p8BPPPalette, 255, 255, 255, FALSE); + for (cnt = 1; cnt < 10; cnt++) { + this->pGlowShades[cnt] = CreateEnemyGlow16BPPPalette(this->p8BPPPalette, gRedGlowR[cnt], 255, FALSE); + } + this->pGlowShades[10] = Create16BPPPaletteShaded(this->p8BPPPalette, 100, 100, 100, TRUE); + for (cnt = 11; cnt < 19; cnt++) { + this->pGlowShades[cnt] = CreateEnemyGreyGlow16BPPPalette(this->p8BPPPalette, gRedGlowR[cnt], 0, FALSE); + } + this->pGlowShades[19] = CreateEnemyGreyGlow16BPPPalette(this->p8BPPPalette, gRedGlowR[18], 0, FALSE); + this->pShades[20] = Create16BPPPaletteShaded(this->p8BPPPalette, 255, 255, 255, FALSE); + for (cnt = 21; cnt < 30; cnt++) { + this->pShades[cnt] = CreateEnemyGlow16BPPPalette(this->p8BPPPalette, gOrangeGlowR[(cnt - 20)], gOrangeGlowG[(cnt - 20)], TRUE); + } + this->pShades[30] = Create16BPPPaletteShaded(this->p8BPPPalette, 100, 100, 100, TRUE); + for (cnt = 31; cnt < 39; cnt++) { + this->pShades[cnt] = CreateEnemyGreyGlow16BPPPalette(this->p8BPPPalette, gOrangeGlowR[( cnt - 20)], gOrangeGlowG[(cnt - 20)], TRUE); + } + this->pShades[39] = CreateEnemyGreyGlow16BPPPalette(this->p8BPPPalette, gOrangeGlowR[18], gOrangeGlowG[18], TRUE); + + return true; +} + +} diff --git a/Tactical/LogicalBodyTypes/PaletteTable.h b/Tactical/LogicalBodyTypes/PaletteTable.h new file mode 100644 index 00000000..0c2141e8 --- /dev/null +++ b/Tactical/LogicalBodyTypes/PaletteTable.h @@ -0,0 +1,32 @@ +#pragma once + +#ifndef _LBT_PALETTETABLE__H_ +#define _LBT_PALETTETABLE__H_ + +#include "soldier control.h" +#include "Utilities.h" +#include "lighting.h" + +extern UINT8 gRedGlowR[]; +extern UINT8 gOrangeGlowR[]; +extern UINT8 gOrangeGlowG[]; +extern UINT16* CreateEnemyGlow16BPPPalette(SGPPaletteEntry* pPalette, UINT32 rscale, UINT32 gscale, BOOLEAN fAdjustGreen); +extern UINT16* CreateEnemyGreyGlow16BPPPalette(SGPPaletteEntry* pPalette, UINT32 rscale, UINT32 gscale, BOOLEAN fAdjustGreen); + +namespace LogicalBodyTypes { + +class PaletteTable : public SOLDIERTYPE { + +public: + PaletteTable(); + ~PaletteTable(void); + bool Load(std::string fileName); + +private: + bool CreateSGPPaletteFromActFile(SGPPaletteEntry *pPalette, std::string fileName); + +}; + +} + +#endif diff --git a/Tactical/LogicalBodyTypes/Singleton.h b/Tactical/LogicalBodyTypes/Singleton.h new file mode 100644 index 00000000..948ccc6d --- /dev/null +++ b/Tactical/LogicalBodyTypes/Singleton.h @@ -0,0 +1,79 @@ +#pragma once +#ifndef _LBT_SINGLETON__H_ +#define _LBT_SINGLETON__H_ + +#include + +/* +Not thread safe. Copied from the codeproject (Author: Lai Shiaw San Kent) +*/ + +template class ISingleton { +public : + static T& Instance(); +}; + +template class Singleton : public ISingleton { + +public : + static T& Instance(); + static void Destroy(); + +protected : + inline explicit Singleton() { + assert(Singleton::instance_ == 0); + Singleton::instance_ = static_cast(this); + } + inline ~Singleton() { + Singleton::instance_ = 0; + } + +private : + static T* CreateInstance(); + static void ScheduleForDestruction(void (*)()); + static void DestroyInstance(T*); + +private : + static T* instance_; + +private : + inline explicit Singleton(Singleton const&) {} + inline Singleton& operator=(Singleton const&) { return *this; } +}; + + +template typename T& Singleton::Instance() { + if (Singleton::instance_ == 0) { + Singleton::instance_ = CreateInstance(); + ScheduleForDestruction(Singleton::Destroy); + } + return *(Singleton::instance_); +} + +template +void Singleton::Destroy() { + if (Singleton::instance_ != 0) { + DestroyInstance(Singleton::instance_); + Singleton::instance_ = 0; + } +} + +template +inline typename T* Singleton::CreateInstance() { + return new T(); +} + +template +inline void Singleton::ScheduleForDestruction(void (*pFun)()) { + std::atexit(pFun); +} + +template +inline void Singleton::DestroyInstance(T* p) { + delete p; +} + +template +typename T* Singleton::instance_ = 0; + +#endif diff --git a/Tactical/LogicalBodyTypes/SurfaceCache.cpp b/Tactical/LogicalBodyTypes/SurfaceCache.cpp new file mode 100644 index 00000000..86974fe7 --- /dev/null +++ b/Tactical/LogicalBodyTypes/SurfaceCache.cpp @@ -0,0 +1,145 @@ +#include "SurfaceCache.h" + +namespace LogicalBodyTypes { + +SurfaceCache::SurfaceCache(UINT32 size) { + loadedElementsMax = size; + loadedElements = 0; + oldest = newest = NULL; +}; + +SurfaceCache::~SurfaceCache() { + for (UINT32 i = 0; i < surfaceVector.size(); i++) { + delete surfaceVector[i]; + } +} + +AnimationSurfaceType* SurfaceCache::GetLoadedSurface(UINT32 idx) { + if (idx >= surfaceVector.size()) { + // TODO more sensible handling of errors + SET_ERROR("Error: surface index out of range!"); + return NULL; + } + CacheEntry* node = surfaceVector[idx]; + if (node == newest) { + return node->surface; // nothing to be done here... + } + if (loadedElements < loadedElementsMax) { + if (!oldest) oldest = node; + if (!node->loaded) { + node->loaded = LoadSurface(node->surface, node->structFile); + // TODO more sensible handling of errors + if (!node->loaded) { + SET_ERROR("Error: a surface could not be laoded!"); + return NULL; + } + loadedElements++; + } else { + if (node->next) node->next->prev = node->prev; + if (node->prev) node->prev->next = node->next; + } + if (newest) { + newest->next = node; + node->prev = newest; + } + newest = node; + } else { + if (node->loaded) { + if (node == oldest) { + oldest = oldest->next; + } + if (node->next) node->next->prev = node->prev; + if (node->prev) node->prev->next = node->next; + } else { + CacheEntry* oldNext = oldest->next; + while (node == oldNext) { + oldNext = oldNext->next; + } + oldest->prev = NULL; + oldest->next = NULL; + oldest->loaded = !UnloadSurface(oldest->surface); + oldest = oldNext; + node->loaded = LoadSurface(node->surface, node->structFile); + // TODO more sensible handling of errors + if (!node->loaded) { + SET_ERROR("Error: a surface could not be laoded!"); + return NULL; + } + } + newest->next = node; + node->prev = newest; + newest = node; + } + return node->surface; +} + +UINT32 SurfaceCache::AddSurface(AnimationSurfaceType* surface, STRUCTURE_FILE_REF* pStructFile) { + surface->hVideoObject = NULL; + CacheEntry* node = new CacheEntry(surface, pStructFile); + surfaceVector.push_back(node); + return surfaceVector.size() - 1; +} + +bool SurfaceCache::UnloadSurface(AnimationSurfaceType* animSurfaceType) { + if (animSurfaceType->hVideoObject != NULL) { + DeleteVideoObject(animSurfaceType->hVideoObject); + animSurfaceType->hVideoObject = NULL; + } + return true; +} + +bool SurfaceCache::LoadSurface(AnimationSurfaceType* animSurfaceType, STRUCTURE_FILE_REF* pStructureFileRef) { + AuxObjectData *pAuxData; + AnimDebugMsg("SurfaceCache::LoadSurface"); + // Load into memory + VOBJECT_DESC VObjectDesc; + HVOBJECT hVObject; + HIMAGE hImage; + CHAR8 sFilename[48]; + // Create video object + FilenameForBPP(animSurfaceType->Filename, sFilename); + hImage = CreateImage(sFilename, IMAGE_ALLDATA); + if (hImage == NULL) return TRUE == SET_ERROR("Error: Could not load animation file %s", sFilename); + + VObjectDesc.fCreateFlags = VOBJECT_CREATE_FROMHIMAGE; + VObjectDesc.hImage = hImage; + hVObject = CreateVideoObject( &VObjectDesc ); + if ( hVObject == NULL ) { + SET_ERROR("Error: Could not load animation file: %s", sFilename); + // Video Object will set error conition. + DestroyImage( hImage ); + return false; + } + // Get aux data + if (hImage->uiAppDataSize == hVObject->usNumberOfObjects * sizeof(AuxObjectData)) { + // Valid auxiliary data, so get # od frames from data + pAuxData = (AuxObjectData*) hImage->pAppData; + animSurfaceType->uiNumFramesPerDir = pAuxData->ubNumberOfFrames; + } + else { + SET_ERROR("Invalid # of animations given"); + DestroyImage(hImage); + return false; + } + if (pStructureFileRef != NULL) { + INT16 sStartFrame = 0; + // removed exception coding. Do we even need the next block without that? See original global function + if (AddZStripInfoToVObject(hVObject, pStructureFileRef, TRUE, sStartFrame) == FALSE) { + DestroyImage(hImage); + DeleteVideoObject(hVObject); + SET_ERROR("Animation structure ZStrip creation error: %s", sFilename); + return false; + } + } + // the hImage is no longer needed + DestroyImage(hImage); + // Set video object index + animSurfaceType->hVideoObject = hVObject; + // Determine if we have a problem with #frames + directions ( ie mismatch ) + if ((animSurfaceType->uiNumDirections * animSurfaceType->uiNumFramesPerDir ) != animSurfaceType->hVideoObject->usNumberOfObjects) { + AnimDebugMsg(String("Surface Database: WARNING!!! Surface %d has #frames mismatch.", usSurfaceIndex)); + } + return true; +} + +} diff --git a/Tactical/LogicalBodyTypes/SurfaceCache.h b/Tactical/LogicalBodyTypes/SurfaceCache.h new file mode 100644 index 00000000..f3780bd3 --- /dev/null +++ b/Tactical/LogicalBodyTypes/SurfaceCache.h @@ -0,0 +1,49 @@ +#pragma once +#ifndef _LBT_SURFACECACHE__H_ +#define _LBT_SURFACECACHE__H_ + +#include "Animation Data.h" +#include "Utilities.h" +#include "Sys Globals.h" +#include "Debug Control.h" + +namespace LogicalBodyTypes { + +class SurfaceCache { + +private: + struct CacheEntry { + CacheEntry(AnimationSurfaceType* animSurface, STRUCTURE_FILE_REF* pStructFile) { + surface = animSurface; + structFile = pStructFile; + loaded = false; + prev = next = NULL; + } + bool loaded; + AnimationSurfaceType* surface; + STRUCTURE_FILE_REF* structFile; + CacheEntry* prev; + CacheEntry* next; + } typedef CacheEntry; + typedef std::vector SurfaceVector; + +public: + SurfaceCache(UINT32 size); + ~SurfaceCache(); + AnimationSurfaceType* GetLoadedSurface(UINT32 idx); + UINT32 AddSurface(AnimationSurfaceType* surface, STRUCTURE_FILE_REF* pStructFile); + +private: + UINT32 loadedElementsMax; + UINT32 loadedElements; + CacheEntry* newest; + CacheEntry* oldest; + SurfaceVector surfaceVector; + static bool LoadSurface(AnimationSurfaceType* animSurfaceType, STRUCTURE_FILE_REF* pStructureFileRef); + static bool SurfaceCache::UnloadSurface(AnimationSurfaceType* animSurfaceType); + +}; + +} + +#endif diff --git a/Tactical/LogicalBodyTypes/SurfaceDB.cpp b/Tactical/LogicalBodyTypes/SurfaceDB.cpp new file mode 100644 index 00000000..1cef23ee Binary files /dev/null and b/Tactical/LogicalBodyTypes/SurfaceDB.cpp differ diff --git a/Tactical/LogicalBodyTypes/SurfaceDB.h b/Tactical/LogicalBodyTypes/SurfaceDB.h new file mode 100644 index 00000000..b07b2d4f --- /dev/null +++ b/Tactical/LogicalBodyTypes/SurfaceDB.h @@ -0,0 +1,55 @@ +#ifndef _LBT_SURFACE__H_ +#define _LBT_SURFACE__H_ +#pragma once + +#include "LogicalBodyTypes/AbstractXMLLoader.h" +#include "Animation Data.h" +#include "Utilities.h" +#include "Sys Globals.h" +#include "structure.h" + +extern void FreeStructureFileRef(STRUCTURE_FILE_REF* pFileRef); + +namespace LogicalBodyTypes { + +// Singleton serving as container for AnimationSurfaceType instances. +// Implements loading said instances from an XML files. +class SurfaceDB : public AbstractXMLLoader, public Singleton { + +public: + using Singleton ::Instance; + typedef std::map AnimSurfaceTypeMap; + typedef std::map StructTypeFileMap; + typedef std::map Surface2StructMap; + typedef AnimSurfaceTypeMap::const_iterator iterator; + +private: + enum ParseState { + E_ELEMENT_ANIMSURFACES = FIRST_SUBCLASS_STATE, + E_ELEMENT_ANIMSURFACE + }; + AnimSurfaceTypeMap animSurfaceTypes; + StructTypeFileMap structTypeFiles; + Surface2StructMap surfaceStructs; + +public: + SurfaceDB(void); + ~SurfaceDB(void); + AnimSurfaceTypeMap::const_iterator begin(); + AnimSurfaceTypeMap::const_iterator end(); + AnimationSurfaceType* GetAnimSurfaceType(std::string name); + STRUCTURE_FILE_REF* GetStructFile(AnimationSurfaceType* animSurfaceType); + +private: + static void XMLCALL StartElementHandle(void* userData, const XML_Char* name, const XML_Char** atts); + static void XMLCALL EndElementHandle(void* userData, const XML_Char* name); + static void XMLCALL CharacterDataHandle(void* userData, const XML_Char* str, int len); + static void XMLCALL ExternalEntityHandler(XML_Parser parser, const XML_Char* context, const XML_Char* base, const XML_Char* systemId, const XML_Char* publicId); + bool AddAnimSurfaceType(std::string name, AnimationSurfaceType* animSurfaceType, STRUCTURE_FILE_REF* pStructFile); + STRUCTURE_FILE_REF* LoadStructFile(STR fileName); + +}; + +} + +#endif diff --git a/Tactical/LogicalBodyTypes/XMLParseException.cpp b/Tactical/LogicalBodyTypes/XMLParseException.cpp new file mode 100644 index 00000000..e9357b83 --- /dev/null +++ b/Tactical/LogicalBodyTypes/XMLParseException.cpp @@ -0,0 +1,18 @@ +#include "XMLParseException.h" + +XMLParseException::XMLParseException(const char* text, const char* function, int line, const char* file) : std::exception(), message(text), _LINE(line) { +} + +XMLParseException::XMLParseException(const char* text, const XML_Char* name, XML_Parser* parser) : std::exception(), message(text), _LINE(0) { + message = text; + if (parser != NULL) { + _LINE = XML_GetCurrentLineNumber(*parser); + } +} + +XMLParseException::~XMLParseException(void) { +} + +const char* XMLParseException::what() const throw() { + return message.c_str(); +} diff --git a/Tactical/LogicalBodyTypes/XMLParseException.h b/Tactical/LogicalBodyTypes/XMLParseException.h new file mode 100644 index 00000000..dbc03afc --- /dev/null +++ b/Tactical/LogicalBodyTypes/XMLParseException.h @@ -0,0 +1,26 @@ +#pragma once +#ifndef _LBT_XMLPARSEEXCEPTION__H_ +#define _LBT_XMLPARSEEXCEPTION__H_ + +#include "LogicalBodyTypes/XMLParseException.h" +#include "expat.h" +#include +#include + +class XMLParseException : public std::exception { +public: + XMLParseException(const char* text, const char* function, int line, const char* file); + XMLParseException(const char* text, const XML_Char* name, XML_Parser* parser = NULL); + const char* what() const throw(); + ~XMLParseException(void); + +public: + int _LINE; + std::string message; + std::string _FILE; + std::string _FUNCTION; + std::string _time; + +}; + +#endif diff --git a/Tactical/ShopKeeper Interface.cpp b/Tactical/ShopKeeper Interface.cpp index 1525c6ee..a5228a2c 100644 --- a/Tactical/ShopKeeper Interface.cpp +++ b/Tactical/ShopKeeper Interface.cpp @@ -1526,7 +1526,9 @@ BOOLEAN RenderShopKeeperInterface() sCenX, sCenY, pSoldier->usAniFrame, &rect, - pSoldier->pShades[pSoldier->ubFadeLevel] ); + pSoldier->pShades[pSoldier->ubFadeLevel], + TRUE + ); UnLockVideoSurface( FRAME_BUFFER ); } diff --git a/Tactical/Tactical_VS2010.vcxproj b/Tactical/Tactical_VS2010.vcxproj index f4502dcc..3c1d2629 100644 --- a/Tactical/Tactical_VS2010.vcxproj +++ b/Tactical/Tactical_VS2010.vcxproj @@ -66,6 +66,19 @@ + + + + + + + + + + + + + @@ -155,13 +168,25 @@ + + + + + + + + + + + + - + diff --git a/Tactical/Tactical_VS2010.vcxproj.filters b/Tactical/Tactical_VS2010.vcxproj.filters index b7c82e98..bdee8df2 100644 --- a/Tactical/Tactical_VS2010.vcxproj.filters +++ b/Tactical/Tactical_VS2010.vcxproj.filters @@ -7,6 +7,9 @@ {c1880088-a976-405e-919e-9f1e97ad6701} + + {7ccf82e9-8713-4351-af1f-218106a69555} + @@ -147,7 +150,7 @@ Header Files - + Header Files @@ -276,6 +279,45 @@ Header Files + + Logical Bodytypes + + + Logical Bodytypes + + + Logical Bodytypes + + + Logical Bodytypes + + + Logical Bodytypes + + + Logical Bodytypes + + + Logical Bodytypes + + + Logical Bodytypes + + + Logical Bodytypes + + + Logical Bodytypes + + + Logical Bodytypes + + + Logical Bodytypes + + + Logical Bodytypes + @@ -704,5 +746,41 @@ Source Files + + Logical Bodytypes + + + Logical Bodytypes + + + Logical Bodytypes + + + Logical Bodytypes + + + Logical Bodytypes + + + Logical Bodytypes + + + Logical Bodytypes + + + Logical Bodytypes + + + Logical Bodytypes + + + Logical Bodytypes + + + Logical Bodytypes + + + Logical Bodytypes + \ No newline at end of file diff --git a/Tactical/Tactical_VS2013.vcxproj b/Tactical/Tactical_VS2013.vcxproj index 770f41a7..656ccdf0 100644 --- a/Tactical/Tactical_VS2013.vcxproj +++ b/Tactical/Tactical_VS2013.vcxproj @@ -66,6 +66,19 @@ + + + + + + + + + + + + + @@ -156,6 +169,18 @@ + + + + + + + + + + + + diff --git a/Tactical/Tactical_VS2013.vcxproj.filters b/Tactical/Tactical_VS2013.vcxproj.filters index 15c9b3a3..8db6d9d0 100644 --- a/Tactical/Tactical_VS2013.vcxproj.filters +++ b/Tactical/Tactical_VS2013.vcxproj.filters @@ -7,6 +7,9 @@ {c1880088-a976-405e-919e-9f1e97ad6701} + + {7ccf82e9-8713-4351-af1f-218106a69555} + @@ -279,6 +282,45 @@ Header Files + + Logical Bodytypes + + + Logical Bodytypes + + + Logical Bodytypes + + + Logical Bodytypes + + + Logical Bodytypes + + + Logical Bodytypes + + + Logical Bodytypes + + + Logical Bodytypes + + + Logical Bodytypes + + + Logical Bodytypes + + + Logical Bodytypes + + + Logical Bodytypes + + + Logical Bodytypes + @@ -707,5 +749,41 @@ Source Files + + Logical Bodytypes + + + Logical Bodytypes + + + Logical Bodytypes + + + Logical Bodytypes + + + Logical Bodytypes + + + Logical Bodytypes + + + Logical Bodytypes + + + Logical Bodytypes + + + Logical Bodytypes + + + Logical Bodytypes + + + Logical Bodytypes + + + Logical Bodytypes + \ No newline at end of file diff --git a/Tactical/Tactical_VS2017.vcxproj b/Tactical/Tactical_VS2017.vcxproj index b1e56e8a..85fde975 100644 --- a/Tactical/Tactical_VS2017.vcxproj +++ b/Tactical/Tactical_VS2017.vcxproj @@ -66,6 +66,19 @@ + + + + + + + + + + + + + @@ -156,6 +169,18 @@ + + + + + + + + + + + + diff --git a/Tactical/Tactical_VS2017.vcxproj.filters b/Tactical/Tactical_VS2017.vcxproj.filters index 15c9b3a3..8db6d9d0 100644 --- a/Tactical/Tactical_VS2017.vcxproj.filters +++ b/Tactical/Tactical_VS2017.vcxproj.filters @@ -7,6 +7,9 @@ {c1880088-a976-405e-919e-9f1e97ad6701} + + {7ccf82e9-8713-4351-af1f-218106a69555} + @@ -279,6 +282,45 @@ Header Files + + Logical Bodytypes + + + Logical Bodytypes + + + Logical Bodytypes + + + Logical Bodytypes + + + Logical Bodytypes + + + Logical Bodytypes + + + Logical Bodytypes + + + Logical Bodytypes + + + Logical Bodytypes + + + Logical Bodytypes + + + Logical Bodytypes + + + Logical Bodytypes + + + Logical Bodytypes + @@ -707,5 +749,41 @@ Source Files + + Logical Bodytypes + + + Logical Bodytypes + + + Logical Bodytypes + + + Logical Bodytypes + + + Logical Bodytypes + + + Logical Bodytypes + + + Logical Bodytypes + + + Logical Bodytypes + + + Logical Bodytypes + + + Logical Bodytypes + + + Logical Bodytypes + + + Logical Bodytypes + \ No newline at end of file diff --git a/Tactical/XML.h b/Tactical/XML.h index 4a0c89ae..f2521e1d 100644 --- a/Tactical/XML.h +++ b/Tactical/XML.h @@ -256,6 +256,12 @@ typedef PARSE_STAGE; #define DIFFICULTYFILENAME "DifficultySettings.xml" +#define LBT_LAYERSFILENAME "LogicalBodyTypes/Layers.xml" +#define LBT_PALETTESFILENAME "LogicalBodyTypes/Palettes.xml" +#define LBT_ANIMSURFACESFILENAME "LogicalBodyTypes/AnimationSurfaces.xml" +#define LBT_FILTERSFILENAME "LogicalBodyTypes/Filters.xml" +#define LBT_BODYTYPESFILENAME "LogicalBodyTypes/LogicalBodyTypes.xml" + extern BOOLEAN ReadInItemStats(STR fileName, BOOLEAN localizedVersion); extern BOOLEAN WriteItemStats(); diff --git a/TileEngine/renderworld.cpp b/TileEngine/renderworld.cpp index 383da355..3842bcb3 100644 --- a/TileEngine/renderworld.cpp +++ b/TileEngine/renderworld.cpp @@ -834,20 +834,156 @@ void RenderSetShadows(BOOLEAN fShadows) } } +inline UINT16 * GetShadeTable(LEVELNODE * pNode, SOLDIERTYPE * pSoldier, SOLDIERTYPE * pPaletteTable, UINT32 uiFlags, INT16 * gsForceSoldierZLevel) +{ + UINT16 * pShadeTable; + // Shade guy always lighter than sceane default! + { + UINT8 ubShadeLevel; + ubShadeLevel = (pNode->ubShadeLevel & 0x0f); + ubShadeLevel = __max(ubShadeLevel - 2, DEFAULT_SHADE_LEVEL); + ubShadeLevel |= (pNode->ubShadeLevel & 0x30); + if (pSoldier->flags.fBeginFade) + { + pShadeTable = pPaletteTable->pCurrentShade = pPaletteTable->pShades[pSoldier->ubFadeLevel]; + } + else + { + pShadeTable = pPaletteTable->pCurrentShade = pPaletteTable->pShades[ubShadeLevel]; + } + } + if (!pSoldier->flags.fBeginFade) + { + // Special effect - draw ghost if is seen by a guy in player's team but not current guy + // ATE: Todo: setup flag for 'bad-guy' - can releive some checks in renderer + if (!pSoldier->aiData.bNeutral && (pSoldier->bSide != gbPlayerNum)) + { + SOLDIERTYPE * pSelSoldier; + if (gusSelectedSoldier != NOBODY) + { + pSelSoldier = MercPtrs[gusSelectedSoldier]; + } + else + { + pSelSoldier = NULL; + } + INT8 bGlowShadeOffset; + bGlowShadeOffset = 0; + if (gTacticalStatus.ubCurrentTeam == gbPlayerNum) + { + // Shade differently depending on visiblity + if (pSoldier->bLastRenderVisibleValue == 0) + { + bGlowShadeOffset = 10; + } + if (pSelSoldier != NULL) + { + if (pSelSoldier->aiData.bOppList[pSoldier->ubID] != SEEN_CURRENTLY) + { + if (pSoldier->usAnimState != CHARIOTS_OF_FIRE && pSoldier->usAnimState != BODYEXPLODING) + { + bGlowShadeOffset = 10; + } + } + } + } + INT16 ** pShadeStart; + if (pSoldier->pathing.bLevel == 0) + { + pShadeStart = (INT16 **) & (pPaletteTable->pGlowShades[0]); + } + else + { + pShadeStart = (INT16 **) & (pPaletteTable->pShades[20]); + } + // Set shade + // If a bad guy is highlighted + if (gfUIHandleSelectionAboveGuy == TRUE && MercPtrs[gsSelectedGuy]->bSide != gbPlayerNum) + { + if (gsSelectedGuy == pSoldier->ubID) + { + pShadeTable = (UINT16 *)pShadeStart[gsGlowFrames[gsCurrentGlowFrame] + bGlowShadeOffset]; + *gsForceSoldierZLevel = TOPMOST_Z_LEVEL; + } + else + { + // Are we dealing with a not-so visible merc? + if (bGlowShadeOffset == 10) + { + pShadeTable = pPaletteTable->pEffectShades[0]; + } + } + } + else + { + // OK,not highlighted, but maybe we are in enemy's turn and they have the baton + // AI's turn? + if (gTacticalStatus.ubCurrentTeam != OUR_TEAM) + { + // Do he have baton? + if ((pSoldier->flags.uiStatusFlags & SOLDIER_UNDERAICONTROL)) + { + pShadeTable = (UINT16 *)pShadeStart[gpGlowFramePointer[gsCurrentGlowFrame] + bGlowShadeOffset]; + if (gpGlowFramePointer[gsCurrentGlowFrame] >= 7) + { + *gsForceSoldierZLevel = TOPMOST_Z_LEVEL; + } + } + } + else + { + pShadeTable = (UINT16 *)pShadeStart[gpGlowFramePointer[gsCurrentGlowFrame] + bGlowShadeOffset]; + if (gpGlowFramePointer[gsCurrentGlowFrame] >= 7) + { + *gsForceSoldierZLevel = TOPMOST_Z_LEVEL; + } + } + } + //if ( gusSelectedSoldier != NOBODY ) + //{ + // pSelSoldier = MercPtrs[ gusSelectedSoldier ]; + // Shade differently depending on visiblity + // if ( pSoldier->bVisible == 0 || ( pSelSoldier->aiData.bOppList[ pSoldier->ubID ] == 0 ) ) + // { + // Shade gray + // pShadeTable = pSoldier->pGlowShades[ gpGlowFramePointer[ gsCurrentGlowFrame ] + 10 ]; + // } + //} + } + } + if (!(uiFlags & TILES_DIRTY)) + { + if (pSoldier->flags.fForceShade) + { + pShadeTable = pPaletteTable->pForcedShade; + } + } + // check if we are a merc duplicate, if so, only do minimal stuff! + if (pSoldier->ubID >= MAX_NUM_SOLDIERS) + { + // Shade gray + pShadeTable = pPaletteTable->pEffectShades[1]; + } + return pShadeTable; +} -void RenderTiles(UINT32 uiFlags, INT32 iStartPointX_M, INT32 iStartPointY_M, INT32 iStartPointX_S, INT32 iStartPointY_S, INT32 iEndXS, INT32 iEndYS, UINT8 ubNumLevels, UINT32 *puiLevels, UINT16 *psLevelIDs ) + +/* +MONSTERS BE HERE! +*/ +void RenderTiles(UINT32 uiFlags, INT32 iStartPointX_M, INT32 iStartPointY_M, INT32 iStartPointX_S, INT32 iStartPointY_S, INT32 iEndXS, INT32 iEndYS, UINT8 ubNumLevels, UINT32 *puiLevels, UINT16 *psLevelIDs) { -//#if 0 + //#if 0 LEVELNODE *pNode; //, *pLand, *pStruct; //*pObject, *pTopmost, *pMerc; SOLDIERTYPE *pSoldier, *pSelSoldier; HVOBJECT hVObject = NULL; ETRLEObject *pTrav; - TILE_ELEMENT *TileElem=NULL; + TILE_ELEMENT *TileElem = NULL; UINT32 uiDestPitchBYTES = 0; - UINT8 *pDestBuf=NULL; + UINT8 *pDestBuf = NULL; UINT16 usAnimSurface; INT8 bXOddFlag = 0; INT32 iAnchorPosX_M, iAnchorPosY_M; @@ -861,61 +997,59 @@ void RenderTiles(UINT32 uiFlags, INT32 iStartPointX_M, INT32 iStartPointY_M, INT UINT32 uiBrushWidth, uiBrushHeight, uiDirtyFlags; INT16 sTileHeight, sXPos, sYPos, sZLevel; INT16 sMouseX_M, sMouseY_M; - BOOLEAN fShadowBlitter=FALSE; - BOOLEAN fZBlitter=FALSE; - BOOLEAN fZWrite=FALSE; - BOOLEAN fLinkedListDirection=TRUE; - BOOLEAN fRenderTile=TRUE; - BOOLEAN fMerc=FALSE; - BOOLEAN fCheckForRedundency=FALSE; + BOOLEAN fShadowBlitter = FALSE; + BOOLEAN fZBlitter = FALSE; + BOOLEAN fZWrite = FALSE; + BOOLEAN fLinkedListDirection = TRUE; + BOOLEAN fRenderTile = TRUE; + BOOLEAN fMerc = FALSE; + BOOLEAN fCheckForRedundency = FALSE; UINT32 uiRowFlags; - BOOLEAN fDynamic=TRUE; + BOOLEAN fDynamic = TRUE; BOOLEAN fEndRenderRow = FALSE; BOOLEAN fEndRenderCol = FALSE; - BOOLEAN fPixelate=FALSE; + BOOLEAN fPixelate = FALSE; BOOLEAN fMultiZBlitter = FALSE; BOOLEAN fWallTile = FALSE; BOOLEAN fMultiTransShadowZBlitter = FALSE; - INT16 sMultiTransShadowZBlitterIndex=-1; - BOOLEAN fTranslucencyType=FALSE; + INT16 sMultiTransShadowZBlitterIndex = -1; + BOOLEAN fTranslucencyType = FALSE; INT16 sX, sY; BOOLEAN fTileInvisible = FALSE; - BOOLEAN fConvertTo16=FALSE; + BOOLEAN fConvertTo16 = FALSE; UINT32 cnt; - static UINT8 ubLevelNodeStartIndex[ NUM_RENDER_FX_TYPES ]; + static UINT8 ubLevelNodeStartIndex[NUM_RENDER_FX_TYPES]; BOOLEAN bItemOutline; - UINT16 usOutlineColor=0; + UINT16 usOutlineColor = 0; - static INT32 iTileMapPos[ 500 ]; + static INT32 iTileMapPos[500]; INT32 uiMapPosIndex; UINT8 bBlitClipVal; INT8 bItemCount, bVisibleItemCount; //UINT16 us16BPPIndex; RenderFXType RenderingFX; BOOLEAN fCheckForMouseDetections = FALSE; - static RenderFXType RenderFXList[ NUM_RENDER_FX_TYPES ]; + static RenderFXType RenderFXList[NUM_RENDER_FX_TYPES]; BOOLEAN fSaveZ; INT16 sWorldY; - INT16 sZOffsetX=-1; - INT16 sZOffsetY=-1; + INT16 sZOffsetX = -1; + INT16 sZOffsetY = -1; BOOLEAN fIntensityBlitter; INT16 gsForceSoldierZLevel; - ROTTING_CORPSE *pCorpse=NULL; + ROTTING_CORPSE *pCorpse = NULL; BOOLEAN fUseTileElem; UINT32 uiLevelNodeFlags; - UINT32 uiTileElemFlags=0; - INT8 bGlowShadeOffset; + UINT32 uiTileElemFlags = 0; BOOLEAN fObscured; BOOLEAN fObscuredBlitter; INT16 sModifiedTileHeight; BOOLEAN fDoRow; - INT16 **pShadeStart; UINT32 uiSaveBufferPitchBYTES; UINT8 *pSaveBuf; ITEM_POOL *pItemPool = NULL; BOOLEAN fHiddenTile = FALSE; - UINT32 uiAniTileFlags = 0; + UINT32 uiAniTileFlags = 0; INT16 sZStripIndex; //Init some variables @@ -930,19 +1064,19 @@ void RenderTiles(UINT32 uiFlags, INT32 iStartPointX_M, INT32 iStartPointY_M, INT iAnchorPosX_S = iStartPointX_S; iAnchorPosY_S = iStartPointY_S; - if(!(uiFlags&TILES_DIRTY)) - pDestBuf = LockVideoSurface( FRAME_BUFFER, &uiDestPitchBYTES ); + if (!(uiFlags&TILES_DIRTY)) + pDestBuf = LockVideoSurface(FRAME_BUFFER, &uiDestPitchBYTES); - if ( uiFlags & TILES_DYNAMIC_CHECKFOR_INT_TILE ) + if (uiFlags & TILES_DYNAMIC_CHECKFOR_INT_TILE) { - if ( ShouldCheckForMouseDetections( ) ) + if (ShouldCheckForMouseDetections()) { - BeginCurInteractiveTileCheck( gubIntTileCheckFlags ); + BeginCurInteractiveTileCheck(gubIntTileCheckFlags); fCheckForMouseDetections = TRUE; // If we are in edit mode, don't do this... - if ( gfEditMode ) + if (gfEditMode) { fCheckForMouseDetections = FALSE; } @@ -950,17 +1084,17 @@ void RenderTiles(UINT32 uiFlags, INT32 iStartPointX_M, INT32 iStartPointY_M, INT } //if((uiFlags&TILES_TYPE_MASK)==TILES_STATIC_LAND) - GetMouseXY( &sMouseX_M, &sMouseY_M ); + GetMouseXY(&sMouseX_M, &sMouseY_M); - pDirtyBackPtr=NULL; + pDirtyBackPtr = NULL; - if(gTacticalStatus.uiFlags&TRANSLUCENCY_TYPE) - fTranslucencyType=TRUE; + if (gTacticalStatus.uiFlags&TRANSLUCENCY_TYPE) + fTranslucencyType = TRUE; - for ( cnt = 0; cnt < ubNumLevels; cnt++ ) + for (cnt = 0; cnt < ubNumLevels; cnt++) { - ubLevelNodeStartIndex[ cnt ] = RenderFXStartIndex[ psLevelIDs[ cnt ] ]; - RenderFXList[ cnt ] = RenderFX[ psLevelIDs[ cnt ] ]; + ubLevelNodeStartIndex[cnt] = RenderFXStartIndex[psLevelIDs[cnt]]; + RenderFXList[cnt] = RenderFX[psLevelIDs[cnt]]; } do @@ -976,47 +1110,47 @@ void RenderTiles(UINT32 uiFlags, INT32 iStartPointX_M, INT32 iStartPointY_M, INT // Build tile index list do { - iTileMapPos[ uiMapPosIndex ] = FASTMAPROWCOLTOPOS( iTempPosY_M, iTempPosX_M ); + iTileMapPos[uiMapPosIndex] = FASTMAPROWCOLTOPOS(iTempPosY_M, iTempPosX_M); - iTempPosX_S += 40; - iTempPosX_M ++; - iTempPosY_M --; + iTempPosX_S += 40; + iTempPosX_M++; + iTempPosY_M--; - uiMapPosIndex++; + uiMapPosIndex++; - } while( iTempPosX_S < iEndXS ); + } while (iTempPosX_S < iEndXS); - for ( cnt = 0; cnt < ubNumLevels; cnt++ ) + for (cnt = 0; cnt < ubNumLevels; cnt++) { - uiRowFlags = puiLevels[ cnt ]; - fDoRow = TRUE; + uiRowFlags = puiLevels[cnt]; + fDoRow = TRUE; - if ( ( uiRowFlags & TILES_ALL_DYNAMICS ) && !( uiLayerUsedFlags & uiRowFlags ) && !( uiFlags & TILES_DYNAMIC_CHECKFOR_INT_TILE ) ) + if ((uiRowFlags & TILES_ALL_DYNAMICS) && !(uiLayerUsedFlags & uiRowFlags) && !(uiFlags & TILES_DYNAMIC_CHECKFOR_INT_TILE)) { fDoRow = FALSE; } - if ( fDoRow ) + if (fDoRow) { iTempPosX_M = iAnchorPosX_M; iTempPosY_M = iAnchorPosY_M; iTempPosX_S = iAnchorPosX_S; iTempPosY_S = iAnchorPosY_S; - fEndRenderRow = FALSE; + fEndRenderRow = FALSE; uiMapPosIndex = 0; - if(bXOddFlag > 0) + if (bXOddFlag > 0) iTempPosX_S += 20; do { - uiTileIndex = iTileMapPos[ uiMapPosIndex ]; + uiTileIndex = iTileMapPos[uiMapPosIndex]; uiMapPosIndex++; //if ( 0 ) @@ -1025,66 +1159,66 @@ void RenderTiles(UINT32 uiFlags, INT32 iStartPointX_M, INT32 iStartPointY_M, INT // OK, we're searching through this loop anyway, might as well check for mouse position // over objects... // Experimental! - if ( uiFlags & TILES_DYNAMIC_CHECKFOR_INT_TILE ) + if (uiFlags & TILES_DYNAMIC_CHECKFOR_INT_TILE) { - if ( fCheckForMouseDetections && gpWorldLevelData[uiTileIndex].pStructHead != NULL ) + if (fCheckForMouseDetections && gpWorldLevelData[uiTileIndex].pStructHead != NULL) { - LogMouseOverInteractiveTile( uiTileIndex ); + LogMouseOverInteractiveTile(uiTileIndex); } } - if((uiFlags&TILES_MARKED) && !(gpWorldLevelData[uiTileIndex].uiFlags&MAPELEMENT_REDRAW)) + if ((uiFlags&TILES_MARKED) && !(gpWorldLevelData[uiTileIndex].uiFlags&MAPELEMENT_REDRAW)) { - pNode=NULL; + pNode = NULL; } else { //pNode = gpWorldLevelData[ uiTileIndex ].pLevelNodes[ RenderFXStartIndex[ psLevelIDs[ cnt ] ] ]; //pNode = gpWorldLevelData[ uiTileIndex ].pLevelNodes[ 0 ]; //pNode=NULL; - pNode = gpWorldLevelData[ uiTileIndex ].pLevelNodes[ ubLevelNodeStartIndex[ cnt ] ]; + pNode = gpWorldLevelData[uiTileIndex].pLevelNodes[ubLevelNodeStartIndex[cnt]]; } bItemCount = 0; bVisibleItemCount = 0; - pItemPool = NULL; + pItemPool = NULL; - while(pNode!= NULL) + while (pNode != NULL) { - RenderingFX = RenderFXList[ cnt ]; + RenderingFX = RenderFXList[cnt]; - fObscured = RenderingFX.fObscured; - fDynamic = RenderingFX.fDynamic; + fObscured = RenderingFX.fObscured; + fDynamic = RenderingFX.fDynamic; - fMerc = RenderingFX.fMerc; - fZWrite = RenderingFX.fZWrite; - fZBlitter = RenderingFX.fZBlitter; - fShadowBlitter = RenderingFX.fShadowBlitter; - fLinkedListDirection = RenderingFX.fLinkedListDirection; - fCheckForRedundency = RenderingFX.fCheckForRedundency; - fMultiZBlitter = RenderingFX.fMultiZBlitter; - fConvertTo16 = RenderingFX.fConvertTo16; - fIntensityBlitter = FALSE; - fSaveZ = FALSE; - fWallTile = FALSE; - gsForceSoldierZLevel = FALSE; - pSoldier = NULL; - fUseTileElem = FALSE; - fMultiTransShadowZBlitter = FALSE; - fObscuredBlitter = FALSE; - fTranslucencyType = TRUE; - uiAniTileFlags = 0; - sZStripIndex = -1; + fMerc = RenderingFX.fMerc; + fZWrite = RenderingFX.fZWrite; + fZBlitter = RenderingFX.fZBlitter; + fShadowBlitter = RenderingFX.fShadowBlitter; + fLinkedListDirection = RenderingFX.fLinkedListDirection; + fCheckForRedundency = RenderingFX.fCheckForRedundency; + fMultiZBlitter = RenderingFX.fMultiZBlitter; + fConvertTo16 = RenderingFX.fConvertTo16; + fIntensityBlitter = FALSE; + fSaveZ = FALSE; + fWallTile = FALSE; + gsForceSoldierZLevel = FALSE; + pSoldier = NULL; + fUseTileElem = FALSE; + fMultiTransShadowZBlitter = FALSE; + fObscuredBlitter = FALSE; + fTranslucencyType = TRUE; + uiAniTileFlags = 0; + sZStripIndex = -1; - uiLevelNodeFlags = pNode->uiFlags; + uiLevelNodeFlags = pNode->uiFlags; - if ( fCheckForRedundency ) + if (fCheckForRedundency) { - if ( ( gpWorldLevelData[ uiTileIndex ].uiFlags & MAPELEMENT_REDUNDENT) ) + if ((gpWorldLevelData[uiTileIndex].uiFlags & MAPELEMENT_REDUNDENT)) { // IF WE DONOT WANT TO RE-EVALUATE FIRST - if ( !( gpWorldLevelData[uiTileIndex].uiFlags & MAPELEMENT_REEVALUATE_REDUNDENCY ) && !(gTacticalStatus.uiFlags & NOHIDE_REDUNDENCY ) ) + if (!(gpWorldLevelData[uiTileIndex].uiFlags & MAPELEMENT_REEVALUATE_REDUNDENCY) && !(gTacticalStatus.uiFlags & NOHIDE_REDUNDENCY)) { pNode = NULL; break; @@ -1093,34 +1227,34 @@ void RenderTiles(UINT32 uiFlags, INT32 iStartPointX_M, INT32 iStartPointY_M, INT } // Force z-buffer blitting for marked tiles ( even ground!) - if ( (uiFlags&TILES_MARKED) ) + if ((uiFlags&TILES_MARKED)) { - fZBlitter = TRUE; + fZBlitter = TRUE; } //Looking up height every time here is alot better than doing it above! - sTileHeight=gpWorldLevelData[uiTileIndex].sHeight; + sTileHeight = gpWorldLevelData[uiTileIndex].sHeight; - sModifiedTileHeight = ( ( ( sTileHeight / 80 ) - 1 ) * 80 ); + sModifiedTileHeight = (((sTileHeight / 80) - 1) * 80); - if ( sModifiedTileHeight < 0 ) + if (sModifiedTileHeight < 0) { sModifiedTileHeight = 0; } - fRenderTile=TRUE; - pDirtyBackPtr=NULL; - if(uiLevelNodeFlags&LEVELNODE_REVEAL) + fRenderTile = TRUE; + pDirtyBackPtr = NULL; + if (uiLevelNodeFlags&LEVELNODE_REVEAL) { - if(!fDynamic) - fRenderTile=FALSE; + if (!fDynamic) + fRenderTile = FALSE; else - fPixelate=TRUE; + fPixelate = TRUE; } else - fPixelate=FALSE; + fPixelate = FALSE; // non-type specific setup sXPos = (INT16)iTempPosX_S; @@ -1128,194 +1262,145 @@ void RenderTiles(UINT32 uiFlags, INT32 iStartPointX_M, INT32 iStartPointY_M, INT // setup for any tile type except mercs - if(!fMerc ) + if (!fMerc) { - if ( !( uiLevelNodeFlags & ( LEVELNODE_ROTTINGCORPSE | LEVELNODE_CACHEDANITILE ) ) ) + if (!(uiLevelNodeFlags & (LEVELNODE_ROTTINGCORPSE | LEVELNODE_CACHEDANITILE))) + { + if ((uiLevelNodeFlags & LEVELNODE_REVEALTREES)) { - if( ( uiLevelNodeFlags & LEVELNODE_REVEALTREES ) ) - { - TileElem = &(gTileDatabase[pNode->usIndex + 2]); - } - else - { - TileElem = &(gTileDatabase[pNode->usIndex]); - } - - // HANDLE INDEPENDANT-PER-TILE ANIMATIONS ( IE: DOORS, EXPLODING THINGS, ETC ) - if ( fDynamic ) - { - if( ( uiLevelNodeFlags & LEVELNODE_ANIMATION ) ) - { - if ( pNode->sCurrentFrame != -1 ) - { - Assert( TileElem->pAnimData != NULL ); - TileElem = &gTileDatabase[TileElem->pAnimData->pusFrames[pNode->sCurrentFrame]]; - } - } - } - } - - // Check for best translucency - if ( uiLevelNodeFlags & LEVELNODE_USEBESTTRANSTYPE ) - { - fTranslucencyType = FALSE; - } - - if ( ( uiLevelNodeFlags & ( LEVELNODE_ROTTINGCORPSE | LEVELNODE_CACHEDANITILE ) ) ) - { - if ( fDynamic ) - { - if( !(uiLevelNodeFlags & ( LEVELNODE_DYNAMIC ) ) && !(uiLevelNodeFlags & LEVELNODE_LASTDYNAMIC) ) - fRenderTile=FALSE; - } - else if( (uiLevelNodeFlags & ( LEVELNODE_DYNAMIC ) ) ) - fRenderTile=FALSE; + TileElem = &(gTileDatabase[pNode->usIndex + 2]); } else { - // Set Tile elem flags here! - uiTileElemFlags = TileElem->uiFlags; - // Set valid tile elem! - fUseTileElem = TRUE; + TileElem = &(gTileDatabase[pNode->usIndex]); + } - if(fDynamic || fPixelate) + // HANDLE INDEPENDANT-PER-TILE ANIMATIONS ( IE: DOORS, EXPLODING THINGS, ETC ) + if (fDynamic) + { + if ((uiLevelNodeFlags & LEVELNODE_ANIMATION)) { - if(!fPixelate) + if (pNode->sCurrentFrame != -1) { - if(!( uiTileElemFlags & ANIMATED_TILE) && !(uiTileElemFlags & DYNAMIC_TILE) && !(uiLevelNodeFlags & LEVELNODE_DYNAMIC) && !(uiLevelNodeFlags & LEVELNODE_LASTDYNAMIC) ) - fRenderTile=FALSE; - else if(!(uiTileElemFlags&DYNAMIC_TILE) && !(uiLevelNodeFlags&LEVELNODE_DYNAMIC) && !(uiLevelNodeFlags&LEVELNODE_LASTDYNAMIC) ) - // else if((TileElem->uiFlags&ANIMATED_TILE) ) - { - Assert( TileElem->pAnimData != NULL ); - TileElem = &gTileDatabase[TileElem->pAnimData->pusFrames[TileElem->pAnimData->bCurrentFrame]]; - uiTileElemFlags = TileElem->uiFlags; - } - } - - } - else if((uiTileElemFlags & ANIMATED_TILE) || (uiTileElemFlags & DYNAMIC_TILE) || (uiLevelNodeFlags & LEVELNODE_DYNAMIC) ) - { - if ( !( uiFlags & TILES_OBSCURED ) || ( uiTileElemFlags & ANIMATED_TILE ) ) - { - fRenderTile=FALSE; + Assert(TileElem->pAnimData != NULL); + TileElem = &gTileDatabase[TileElem->pAnimData->pusFrames[pNode->sCurrentFrame]]; } } } + } - // OK, ATE, CHECK FOR AN OBSCURED TILE AND MAKE SURE IF LEVELNODE IS SET - // WE DON'T RENDER UNLESS WE HAVE THE RENDER FLAG SET! - if ( fObscured ) + // Check for best translucency + if (uiLevelNodeFlags & LEVELNODE_USEBESTTRANSTYPE) + { + fTranslucencyType = FALSE; + } + + if ((uiLevelNodeFlags & (LEVELNODE_ROTTINGCORPSE | LEVELNODE_CACHEDANITILE))) + { + if (fDynamic) { - if ( ( uiFlags & TILES_OBSCURED ) ) - { - if ( uiLevelNodeFlags & LEVELNODE_SHOW_THROUGH ) - { - fObscuredBlitter = TRUE; + if (!(uiLevelNodeFlags & (LEVELNODE_DYNAMIC)) && !(uiLevelNodeFlags & LEVELNODE_LASTDYNAMIC)) + fRenderTile = FALSE; + } + else if ((uiLevelNodeFlags & (LEVELNODE_DYNAMIC))) + fRenderTile = FALSE; + } + else + { + // Set Tile elem flags here! + uiTileElemFlags = TileElem->uiFlags; + // Set valid tile elem! + fUseTileElem = TRUE; - // ATE: Check if this is a levelnode, and what frame we are on - // turn off...... - //if ( ( uiLevelNodeFlags & LEVELNODE_ITEM ) && gsCurrentItemGlowFrame < 25 ) - //{ - // fRenderTile = FALSE; - //} - } - else - { - // Don;t render if we are not on this render loop! - fRenderTile = FALSE; - } + if (fDynamic || fPixelate) + { + if (!fPixelate) + { + if (!(uiTileElemFlags & ANIMATED_TILE) && !(uiTileElemFlags & DYNAMIC_TILE) && !(uiLevelNodeFlags & LEVELNODE_DYNAMIC) && !(uiLevelNodeFlags & LEVELNODE_LASTDYNAMIC)) + fRenderTile = FALSE; + else if (!(uiTileElemFlags&DYNAMIC_TILE) && !(uiLevelNodeFlags&LEVELNODE_DYNAMIC) && !(uiLevelNodeFlags&LEVELNODE_LASTDYNAMIC)) + // else if((TileElem->uiFlags&ANIMATED_TILE) ) + { + Assert(TileElem->pAnimData != NULL); + TileElem = &gTileDatabase[TileElem->pAnimData->pusFrames[TileElem->pAnimData->bCurrentFrame]]; + uiTileElemFlags = TileElem->uiFlags; + } + } + + } + else if ((uiTileElemFlags & ANIMATED_TILE) || (uiTileElemFlags & DYNAMIC_TILE) || (uiLevelNodeFlags & LEVELNODE_DYNAMIC)) + { + if (!(uiFlags & TILES_OBSCURED) || (uiTileElemFlags & ANIMATED_TILE)) + { + fRenderTile = FALSE; + } + } + } + + // OK, ATE, CHECK FOR AN OBSCURED TILE AND MAKE SURE IF LEVELNODE IS SET + // WE DON'T RENDER UNLESS WE HAVE THE RENDER FLAG SET! + if (fObscured) + { + if ((uiFlags & TILES_OBSCURED)) + { + if (uiLevelNodeFlags & LEVELNODE_SHOW_THROUGH) + { + fObscuredBlitter = TRUE; + + // ATE: Check if this is a levelnode, and what frame we are on + // turn off...... + //if ( ( uiLevelNodeFlags & LEVELNODE_ITEM ) && gsCurrentItemGlowFrame < 25 ) + //{ + // fRenderTile = FALSE; + //} } else { - if ( uiLevelNodeFlags & LEVELNODE_SHOW_THROUGH ) - { - fRenderTile = FALSE; - - // ATE: Check if this is a levelnode, and what frame we are on - // turn off...... - //if ( ( uiLevelNodeFlags & LEVELNODE_ITEM ) && gsCurrentItemGlowFrame < 25 ) - //{ - // fRenderTile = TRUE; - //} - } + // Don;t render if we are not on this render loop! + fRenderTile = FALSE; } } - - - // If flag says to do dynamic as well, render! - if ( ( uiFlags & TILES_DOALL ) ) + else { - fRenderTile = TRUE; - } - - // If we are on the struct layer, check for if it's hidden! - if ( uiRowFlags & ( TILES_STATIC_STRUCTURES | TILES_DYNAMIC_STRUCTURES | TILES_STATIC_SHADOWS | TILES_DYNAMIC_SHADOWS ) ) - { - if ( fUseTileElem ) + if (uiLevelNodeFlags & LEVELNODE_SHOW_THROUGH) { + fRenderTile = FALSE; + + // ATE: Check if this is a levelnode, and what frame we are on + // turn off...... + //if ( ( uiLevelNodeFlags & LEVELNODE_ITEM ) && gsCurrentItemGlowFrame < 25 ) + //{ + // fRenderTile = TRUE; + //} + } + } + } + + + // If flag says to do dynamic as well, render! + if ((uiFlags & TILES_DOALL)) + { + fRenderTile = TRUE; + } + + // If we are on the struct layer, check for if it's hidden! + if (uiRowFlags & (TILES_STATIC_STRUCTURES | TILES_DYNAMIC_STRUCTURES | TILES_STATIC_SHADOWS | TILES_DYNAMIC_SHADOWS)) + { + if (fUseTileElem) + { #if 0 - // DONOT RENDER IF IT'S A HIDDEN STRUCT AND TILE IS NOT REVEALED - if ( uiTileElemFlags & HIDDEN_TILE ) - { - // IF WORLD IS NOT REVEALED, QUIT - #ifdef JA2EDITOR - if ( !gfEditMode ) - #endif - { - if ( !(gpWorldLevelData[ uiTileIndex ].uiFlags & MAPELEMENT_REVEALED ) && !(gTacticalStatus.uiFlags&SHOW_ALL_MERCS) ) - { - //CONTINUE, DONOT RENDER - if(!fLinkedListDirection) - pNode = pNode->pPrevNode; - else - pNode = pNode->pNext; - - continue; - } - } - } + // DONOT RENDER IF IT'S A HIDDEN STRUCT AND TILE IS NOT REVEALED + if (uiTileElemFlags & HIDDEN_TILE) + { + // IF WORLD IS NOT REVEALED, QUIT +#ifdef JA2EDITOR + if (!gfEditMode) #endif - } - } - - if(fRenderTile) - { - // Set flag to set layer as used - if( fDynamic || fPixelate ) - { - uiAdditiveLayerUsedFlags |= uiRowFlags; - } - - if ( uiLevelNodeFlags & LEVELNODE_DYNAMICZ ) - { - fSaveZ = TRUE; - fZWrite = TRUE; - } - - if ( ( uiLevelNodeFlags & LEVELNODE_CACHEDANITILE ) ) - { - hVObject = gpTileCache[ pNode->pAniTile->sCachedTileID ].pImagery->vo; - usImageIndex = pNode->pAniTile->sCurrentFrame; - uiAniTileFlags = pNode->pAniTile->uiFlags; - - // Position corpse based on its float position - if ( ( uiLevelNodeFlags & LEVELNODE_ROTTINGCORPSE ) ) { - pCorpse = &( gRottingCorpse[ pNode->pAniTile->uiUserData ] ); - - pShadeTable = pCorpse->pShades[ pNode->ubShadeLevel ]; - - //pShadeTable = pCorpse->p16BPPPalette; - - dOffsetX = pCorpse->def.dXPos - gsRenderCenterX; - dOffsetY = pCorpse->def.dYPos - gsRenderCenterY; - - // OK, if this is a corpse.... stop if not visible - if ( pCorpse->def.bVisible != 1 && !(gTacticalStatus.uiFlags&SHOW_ALL_MERCS) ) + if (!(gpWorldLevelData[uiTileIndex].uiFlags & MAPELEMENT_REVEALED) && !(gTacticalStatus.uiFlags&SHOW_ALL_MERCS)) { //CONTINUE, DONOT RENDER - if(!fLinkedListDirection) + if (!fLinkedListDirection) pNode = pNode->pPrevNode; else pNode = pNode->pNext; @@ -1323,597 +1408,502 @@ void RenderTiles(UINT32 uiFlags, INT32 iStartPointX_M, INT32 iStartPointY_M, INT continue; } } - else - { - dOffsetX = (FLOAT)( pNode->pAniTile->sRelativeX - gsRenderCenterX ); - dOffsetY = (FLOAT)( pNode->pAniTile->sRelativeY - gsRenderCenterY ); - } - - // Calculate guy's position - FloatFromCellToScreenCoordinates( dOffsetX, dOffsetY, &dTempX_S, &dTempY_S ); - - sXPos = ( ( gsVIEWPORT_END_X - gsVIEWPORT_START_X ) /2 ) + (INT16)dTempX_S; - sYPos = ( ( gsVIEWPORT_END_Y - gsVIEWPORT_START_Y ) /2 ) + (INT16)dTempY_S - sTileHeight; - - // Adjust for offset position on screen - sXPos -= gsRenderWorldOffsetX; - sYPos -= gsRenderWorldOffsetY; - } - else - { - hVObject = TileElem->hTileSurface; - usImageIndex=TileElem->usRegionIndex; - - // ADJUST FOR WORLD MAPELEM HIEGHT - sYPos-=TileElem->sOffsetHeight; - - if((TileElem->uiFlags&IGNORE_WORLD_HEIGHT) ) - { - sYPos = sYPos - sModifiedTileHeight; - //sYPos -= sTileHeight; - } - - if( !(uiLevelNodeFlags&LEVELNODE_IGNOREHEIGHT) && !(TileElem->uiFlags&IGNORE_WORLD_HEIGHT )) - sYPos-=sTileHeight; - - if(!(uiFlags&TILES_DIRTY)) - { - hVObject->pShadeCurrent=hVObject->pShades[pNode->ubShadeLevel]; - hVObject->pShade8=ubColorTables[pNode->ubShadeLevel]; - } - - } - - - //ADJUST FOR RELATIVE OFFSETS - if ( uiLevelNodeFlags & LEVELNODE_USERELPOS ) - { - sXPos += pNode->sRelativeX; - sYPos += pNode->sRelativeY; - } - - if ( uiLevelNodeFlags& LEVELNODE_USEZ ) - { - sYPos -= pNode->sRelativeZ; - } - - //ADJUST FOR ABSOLUTE POSITIONING - if ( uiLevelNodeFlags& LEVELNODE_USEABSOLUTEPOS ) - { - dOffsetX = (FLOAT)(pNode->sRelativeX - gsRenderCenterX); - dOffsetY = (FLOAT)(pNode->sRelativeY - gsRenderCenterY); - - // OK, DONT'T ASK... CONVERSION TO PROPER Y NEEDS THIS... - dOffsetX -= CELL_Y_SIZE; - - FloatFromCellToScreenCoordinates( dOffsetX, dOffsetY, &dTempX_S, &dTempY_S ); - - sXPos = ( ( gsVIEWPORT_END_X - gsVIEWPORT_START_X ) /2 ) + (INT16)SHORT_ROUND( dTempX_S ); - sYPos = ( ( gsVIEWPORT_END_Y - gsVIEWPORT_START_Y ) /2 ) + (INT16)SHORT_ROUND( dTempY_S ); - - // Adjust for offset position on screen - sXPos -= gsRenderWorldOffsetX; - sYPos -= gsRenderWorldOffsetY; - - - sYPos -= pNode->sRelativeZ; - - } - +#endif } + } - // COUNT # OF ITEMS AT THIS LOCATION - if ( uiLevelNodeFlags & LEVELNODE_ITEM ) - { - // OK set item pool for this location.... - if ( bItemCount == 0 ) - { - pItemPool = pNode->pItemPool; - } - else - { - pItemPool = pItemPool->pNext; - } - - if ( bItemCount < MAX_RENDERED_ITEMS ) - { - bItemCount++; - - if ( gWorldItems[ pItemPool->iItemIndex ].bVisible == VISIBLE ) - { - bVisibleItemCount++; - } - } - - // LIMIT RENDERING OF ITEMS TO ABOUT 7, DO NOT RENDER HIDDEN ITEMS TOO! - if ( bVisibleItemCount == MAX_RENDERED_ITEMS || ( gWorldItems[ pItemPool->iItemIndex ].bVisible != VISIBLE ) || ( pItemPool->usFlags & WORLD_ITEM_DONTRENDER ) ) - { - if ( !(gTacticalStatus.uiFlags&SHOW_ALL_ITEMS) ) - { - //CONTINUE, DONOT RENDER - if(!fLinkedListDirection) - pNode = pNode->pPrevNode; - else - pNode = pNode->pNext; - continue; - } - } - - if ( guiCurrentScreen == EDIT_SCREEN ) - { - // ATE: If in the editor, change this to a little higher value - if ( bItemCount == MAX_RENDERED_ITEMS ) - { - //CONTINUE, DONOT RENDER - if(!fLinkedListDirection) - pNode = pNode->pPrevNode; - else - pNode = pNode->pNext; - continue; - } - } - if ( pItemPool->bRenderZHeightAboveLevel > 0 ) - { - sYPos -= pItemPool->bRenderZHeightAboveLevel; - } - - } - - // If render tile is false... - if ( !fRenderTile ) - { - if(!fLinkedListDirection) - pNode = pNode->pPrevNode; - else - pNode = pNode->pNext; - - continue; - } - } - - // specific code for node types on a per-tile basis - switch( uiRowFlags ) - { - case TILES_STATIC_LAND: - - sZLevel = LandZLevel( iTempPosX_M, iTempPosY_M ); - break; - - case TILES_STATIC_OBJECTS: - - // ATE: Modified to use constant z level, as these are same level as land items - sZLevel = ObjectZLevel( TileElem, pNode, uiTileElemFlags, iTempPosX_M, iTempPosY_M, sWorldY ); - break; - - case TILES_STATIC_STRUCTURES: - - StructZLevel( iTempPosX_M, iTempPosY_M ); - - if ( fUseTileElem && ( TileElem->uiFlags & MULTI_Z_TILE ) ) - { - fMultiZBlitter = TRUE; - } - - // ATE: if we are a wall, set flag - if ( fUseTileElem && ( TileElem->uiFlags & WALL_TILE ) ) - { - fWallTile = TRUE; - } - - break; - - case TILES_STATIC_ROOF: - - sZLevel = RoofZLevel( iTempPosX_M, iTempPosY_M, sWorldY ); - - // Automatically adjust height! - sYPos -= WALL_HEIGHT; - - // ATE: Added for shadows on roofs - if ( fUseTileElem && ( TileElem->uiFlags & ROOFSHADOW_TILE ) ) - { - fShadowBlitter=TRUE; - } - break; - case TILES_STATIC_ONROOF: - - sZLevel = OnRoofZLevel( iTempPosX_M, iTempPosY_M, sWorldY, uiLevelNodeFlags ); - // Automatically adjust height! - sYPos -= WALL_HEIGHT; - break; - - case TILES_STATIC_TOPMOST: - - sZLevel = TopmostZLevel( iTempPosX_M, iTempPosY_M, sWorldY ); - break; - - case TILES_STATIC_SHADOWS: - - sZLevel = ShadowZLevel( iTempPosX_M, iTempPosY_M, sWorldY ); - - if ( uiLevelNodeFlags & LEVELNODE_EXITGRID ) - { - fIntensityBlitter = TRUE; - fShadowBlitter = FALSE; - } - break; - - case TILES_DYNAMIC_LAND: - - sZLevel = LandZLevel( iTempPosX_M, iTempPosY_M ); - uiDirtyFlags=BGND_FLAG_SINGLE|BGND_FLAG_ANIMATED; - break; - case TILES_DYNAMIC_SHADOWS: - - sZLevel = ShadowZLevel( iTempPosX_M, iTempPosY_M, sWorldY ); - //sZLevel=SHADOW_Z_LEVEL; - uiDirtyFlags=BGND_FLAG_SINGLE|BGND_FLAG_ANIMATED; - break; - case TILES_DYNAMIC_OBJECTS: - - sZLevel = ObjectZLevel( TileElem, pNode, uiTileElemFlags, iTempPosX_M, iTempPosY_M, sWorldY ); - uiDirtyFlags=BGND_FLAG_SINGLE|BGND_FLAG_ANIMATED; - break; - - case TILES_DYNAMIC_STRUCTURES: - - StructZLevel( iTempPosX_M, iTempPosY_M ); - uiDirtyFlags=BGND_FLAG_SINGLE|BGND_FLAG_ANIMATED; - - if ( uiTileElemFlags & Z_AWARE_DYNAMIC_TILE ) - { - fMultiZBlitter = TRUE; - fZBlitter = TRUE; - fWallTile = TRUE; - sZStripIndex = 0; - } - break; - case TILES_DYNAMIC_ROOF: - - sYPos -= WALL_HEIGHT; - - sZLevel = RoofZLevel( iTempPosX_M, iTempPosY_M, sWorldY ); - uiDirtyFlags=BGND_FLAG_SINGLE|BGND_FLAG_ANIMATED; - // For now, adjust to hieght of a wall ( 50 temp, make define ) - //if ( TileElem->fType > FOOTPRINTS ) - //{ - // sYPos -= 58; - //} - break; - - case TILES_DYNAMIC_ONROOF: - - sZLevel = OnRoofZLevel( iTempPosX_M, iTempPosY_M, sWorldY, uiLevelNodeFlags ); - uiDirtyFlags=BGND_FLAG_SINGLE|BGND_FLAG_ANIMATED; - // Automatically adjust height! - sYPos -= WALL_HEIGHT; - break; - - case TILES_DYNAMIC_TOPMOST: - sZLevel = TopmostZLevel( iTempPosX_M, iTempPosY_M, sWorldY ); - uiDirtyFlags=BGND_FLAG_SINGLE|BGND_FLAG_ANIMATED; - break; - - case TILES_DYNAMIC_MERCS: - case TILES_DYNAMIC_HIGHMERCS: - case TILES_DYNAMIC_STRUCT_MERCS: - + if (fRenderTile) + { // Set flag to set layer as used - uiAdditiveLayerUsedFlags |= uiRowFlags; - - pSoldier=pNode->pSoldier; - - if ( uiRowFlags == TILES_DYNAMIC_MERCS ) + if (fDynamic || fPixelate) { - // If we are multi-tiled, ignore here - if ( pSoldier->flags.uiStatusFlags & ( SOLDIER_MULTITILE_Z | SOLDIER_Z ) ) - { - pNode = pNode->pNext; - continue; - } - - // If we are at a higher level, no not do anything unless we are at the highmerc stage - if ( pSoldier->pathing.bLevel > 0 ) - { - pNode = pNode->pNext; - continue; - } + uiAdditiveLayerUsedFlags |= uiRowFlags; } - if ( uiRowFlags == TILES_DYNAMIC_HIGHMERCS ) + if (uiLevelNodeFlags & LEVELNODE_DYNAMICZ) { - // If we are multi-tiled, ignore here - if ( pSoldier->flags.uiStatusFlags & SOLDIER_MULTITILE_Z ) - { - pNode = pNode->pNext; - continue; - } - - // If we are at a lower level, no not do anything unless we are at the highmerc stage - if ( pSoldier->pathing.bLevel == 0 ) - { - pNode = pNode->pNext; - continue; - } + fSaveZ = TRUE; + fZWrite = TRUE; } - - if ( uiRowFlags == TILES_DYNAMIC_STRUCT_MERCS ) + if ((uiLevelNodeFlags & LEVELNODE_CACHEDANITILE)) { - // If we are not multi-tiled, ignore here - if ( !( pSoldier->flags.uiStatusFlags & ( SOLDIER_MULTITILE_Z | SOLDIER_Z ) ) ) + hVObject = gpTileCache[pNode->pAniTile->sCachedTileID].pImagery->vo; + usImageIndex = pNode->pAniTile->sCurrentFrame; + uiAniTileFlags = pNode->pAniTile->uiFlags; + + // Position corpse based on its float position + if ((uiLevelNodeFlags & LEVELNODE_ROTTINGCORPSE)) { - // If we are at a low level, no not do anything unless we are at the merc stage - if ( pSoldier->pathing.bLevel == 0 ) + pCorpse = &(gRottingCorpse[pNode->pAniTile->uiUserData]); + + pShadeTable = pCorpse->pShades[pNode->ubShadeLevel]; + + //pShadeTable = pCorpse->p16BPPPalette; + + dOffsetX = pCorpse->def.dXPos - gsRenderCenterX; + dOffsetY = pCorpse->def.dYPos - gsRenderCenterY; + + // OK, if this is a corpse.... stop if not visible + if (pCorpse->def.bVisible != 1 && !(gTacticalStatus.uiFlags&SHOW_ALL_MERCS)) { - pNode = pNode->pNext; + //CONTINUE, DONOT RENDER + if (!fLinkedListDirection) + pNode = pNode->pPrevNode; + else + pNode = pNode->pNext; + continue; } } - - if ( pSoldier->flags.uiStatusFlags & ( SOLDIER_MULTITILE_Z | SOLDIER_Z ) ) - { - fSaveZ = TRUE; - fZBlitter = TRUE; - - if ( pSoldier->flags.uiStatusFlags & SOLDIER_MULTITILE_Z ) - { - fMultiTransShadowZBlitter = TRUE; - // ATE: Use one direction for queen! - if ( pSoldier->ubBodyType == QUEENMONSTER ) - { - sMultiTransShadowZBlitterIndex = 0; - } - else - { - sMultiTransShadowZBlitterIndex = gOneCDirection[ pSoldier->ubDirection ]; - } - } - else - { - fZWrite = TRUE; - } - } - - } - - // IF we are not active, or are a placeholder for multi-tile animations do nothing - //if ( !pSoldier->bActive ) - if ( !pSoldier->bActive || (uiLevelNodeFlags & LEVELNODE_MERCPLACEHOLDER) ) - { - pNode = pNode->pNext; - continue; - } - - // Skip if we cannot see the guy! - if ( pSoldier->bLastRenderVisibleValue == -1 && !(gTacticalStatus.uiFlags&SHOW_ALL_MERCS) ) - { - pNode = pNode->pNext; - continue; - } - - - // Get animation surface.... - usAnimSurface = GetSoldierAnimationSurface( pSoldier, pSoldier->usAnimState ); - - if ( usAnimSurface == INVALID_ANIMATION_SURFACE ) - { - pNode = pNode->pNext; - continue; - } - - - // Shade guy always lighter than sceane default! - { - UINT8 ubShadeLevel; - - ubShadeLevel = (pNode->ubShadeLevel&0x0f); - ubShadeLevel=__max(ubShadeLevel-2, DEFAULT_SHADE_LEVEL); - ubShadeLevel|=(pNode->ubShadeLevel&0x30); - - if ( pSoldier->flags.fBeginFade ) - { - pShadeTable = pSoldier->pCurrentShade = pSoldier->pShades[ pSoldier->ubFadeLevel ]; - } else { - pShadeTable = pSoldier->pCurrentShade = pSoldier->pShades[ ubShadeLevel]; + dOffsetX = (FLOAT)(pNode->pAniTile->sRelativeX - gsRenderCenterX); + dOffsetY = (FLOAT)(pNode->pAniTile->sRelativeY - gsRenderCenterY); } - } + // Calculate guy's position + FloatFromCellToScreenCoordinates(dOffsetX, dOffsetY, &dTempX_S, &dTempY_S); + sXPos = ((gsVIEWPORT_END_X - gsVIEWPORT_START_X) / 2) + (INT16)dTempX_S; + sYPos = ((gsVIEWPORT_END_Y - gsVIEWPORT_START_Y) / 2) + (INT16)dTempY_S - sTileHeight; - // Position guy based on guy's position - dOffsetX = pSoldier->dXPos - gsRenderCenterX; - dOffsetY = pSoldier->dYPos - gsRenderCenterY; + // Adjust for offset position on screen + sXPos -= gsRenderWorldOffsetX; + sYPos -= gsRenderWorldOffsetY; - - // Calculate guy's position - FloatFromCellToScreenCoordinates( dOffsetX, dOffsetY, &dTempX_S, &dTempY_S ); - - sXPos = ( ( gsVIEWPORT_END_X - gsVIEWPORT_START_X ) /2 ) + (INT16)dTempX_S; - sYPos = ( ( gsVIEWPORT_END_Y - gsVIEWPORT_START_Y ) /2 ) + (INT16)dTempY_S - sTileHeight; - - // Adjust for offset position on screen - sXPos -= gsRenderWorldOffsetX; - sYPos -= gsRenderWorldOffsetY; - - // Adjust for soldier height - sYPos -= pSoldier->sHeightAdjustment; - - // Handle shade stuff.... - if ( !pSoldier->flags.fBeginFade ) - { - // Special effect - draw ghost if is seen by a guy in player's team but not current guy - // ATE: Todo: setup flag for 'bad-guy' - can releive some checks in renderer - if ( !pSoldier->aiData.bNeutral && (pSoldier->bSide != gbPlayerNum ) ) - { - if ( gusSelectedSoldier != NOBODY ) - { - pSelSoldier = MercPtrs[ gusSelectedSoldier ]; - } - else - { - pSelSoldier = NULL; - } - - bGlowShadeOffset = 0; - - if ( gTacticalStatus.ubCurrentTeam == gbPlayerNum ) - { - // Shade differently depending on visiblity - if ( pSoldier->bLastRenderVisibleValue == 0 ) - { - bGlowShadeOffset = 10; - } - - if ( pSelSoldier != NULL ) - { - if ( pSelSoldier->aiData.bOppList[ pSoldier->ubID ] != SEEN_CURRENTLY ) - { - if ( pSoldier->usAnimState != CHARIOTS_OF_FIRE && pSoldier->usAnimState != BODYEXPLODING ) - { - bGlowShadeOffset = 10; - } - } - } - } - - if ( pSoldier->pathing.bLevel == 0 ) - { - pShadeStart = (INT16 **)&(pSoldier->pGlowShades[0]); - } - else - { - pShadeStart = (INT16 **) &( pSoldier->pShades[ 20 ] ); - } - - // Set shade - // If a bad guy is highlighted - if ( gfUIHandleSelectionAboveGuy == TRUE && MercPtrs[ gsSelectedGuy ]->bSide != gbPlayerNum ) - { - if ( gsSelectedGuy == pSoldier->ubID ) - { - pShadeTable = (UINT16 *) pShadeStart[ gsGlowFrames[ gsCurrentGlowFrame ] + bGlowShadeOffset ]; - gsForceSoldierZLevel = TOPMOST_Z_LEVEL; - } - else - { - // Are we dealing with a not-so visible merc? - if ( bGlowShadeOffset == 10 ) - { - pShadeTable = pSoldier->pEffectShades[ 0 ]; - } - } - } - else - { - // OK,not highlighted, but maybe we are in enemy's turn and they have the baton - - // AI's turn? - if ( gTacticalStatus.ubCurrentTeam != OUR_TEAM ) - { - // Does he have baton? - if ( (pSoldier->flags.uiStatusFlags & SOLDIER_UNDERAICONTROL) ) - { - pShadeTable = (UINT16 *) pShadeStart[ gpGlowFramePointer[ gsCurrentGlowFrame ] + bGlowShadeOffset ]; - - if ( gpGlowFramePointer[ gsCurrentGlowFrame ] >= 7 ) - { - gsForceSoldierZLevel = TOPMOST_Z_LEVEL; - } - } - } - else - { - pShadeTable = (UINT16 *) pShadeStart[ gpGlowFramePointer[ gsCurrentGlowFrame ] + bGlowShadeOffset ]; - - if ( gpGlowFramePointer[ gsCurrentGlowFrame ] >= 7 ) - { - gsForceSoldierZLevel = TOPMOST_Z_LEVEL; - } - } - } - - //if ( gusSelectedSoldier != NOBODY ) - //{ - // pSelSoldier = MercPtrs[ gusSelectedSoldier ]; - - // Shade differently depending on visiblity - // if ( pSoldier->bVisible == 0 || ( pSelSoldier->aiData.bOppList[ pSoldier->ubID ] == 0 ) ) - // { - // Shade gray - // pShadeTable = pSoldier->pGlowShades[ gpGlowFramePointer[ gsCurrentGlowFrame ] + 10 ]; - // } - //} - } - } - - // Calculate Z level - SoldierZLevel( pSoldier, iTempPosX_M, iTempPosY_M ); - - if(!(uiFlags&TILES_DIRTY)) - { - if ( pSoldier->flags.fForceShade ) - { - pShadeTable = pSoldier->pForcedShade; - } - } - - // check if we are a merc duplicate, if so, only do minimal stuff! - if ( pSoldier->ubID >= MAX_NUM_SOLDIERS ) - { - // Shade gray - pShadeTable = pSoldier->pEffectShades[ 1 ]; - } - - // Flugente: frozen soldiers appear to be in ice, which we simulate by having the soldier be fully white - if ( pSoldier->usSkillCooldown[SOLDIER_COOLDOWN_CRYO] ) - { - pShadeTable = White16BPPPalette; - } - - hVObject=gAnimSurfaceDatabase[ usAnimSurface ].hVideoObject; - - if ( hVObject == NULL ) - { - pNode = pNode->pNext; - continue; - } - - // ATE: If we are in a gridno that we should not use obscure blitter, set! - if ( !( gpWorldLevelData[ uiTileIndex ].ubExtFlags[0] & MAPELEMENT_EXT_NOBURN_STRUCT ) ) - { - fObscuredBlitter = TRUE; } else { - // ATE: Artificially increase z=level... - sZLevel += 2; - } - - usImageIndex = pSoldier->usAniFrame; + hVObject = TileElem->hTileSurface; + usImageIndex = TileElem->usRegionIndex; - // Flugente: frozen soldiers don't move - if ( pSoldier->usSkillCooldown[SOLDIER_COOLDOWN_CRYO] && pSoldier->stats.bLife > 0 ) + // ADJUST FOR WORLD MAPELEM HIEGHT + sYPos -= TileElem->sOffsetHeight; + + if ((TileElem->uiFlags&IGNORE_WORLD_HEIGHT)) + { + sYPos = sYPos - sModifiedTileHeight; + //sYPos -= sTileHeight; + } + + if (!(uiLevelNodeFlags&LEVELNODE_IGNOREHEIGHT) && !(TileElem->uiFlags&IGNORE_WORLD_HEIGHT)) + sYPos -= sTileHeight; + + if (!(uiFlags&TILES_DIRTY)) + { + hVObject->pShadeCurrent = hVObject->pShades[pNode->ubShadeLevel]; + hVObject->pShade8 = ubColorTables[pNode->ubShadeLevel]; + } + + } + + + //ADJUST FOR RELATIVE OFFSETS + if (uiLevelNodeFlags & LEVELNODE_USERELPOS) { - usImageIndex = pSoldier->CryoAniFrame( ); + sXPos += pNode->sRelativeX; + sYPos += pNode->sRelativeY; } - // Flugente: riot shields - if ( pSoldier && - pSoldier->bVisible != -1 && - (pSoldier->ubDirection == NORTH || - pSoldier->ubDirection == NORTHWEST || - pSoldier->ubDirection == WEST) - && pSoldier->IsRiotShieldEquipped( ) ) + if (uiLevelNodeFlags& LEVELNODE_USEZ) { - ShowRiotShield( pSoldier ); + sYPos -= pNode->sRelativeZ; } - uiDirtyFlags=BGND_FLAG_SINGLE|BGND_FLAG_ANIMATED| BGND_FLAG_MERC; - break; + //ADJUST FOR ABSOLUTE POSITIONING + if (uiLevelNodeFlags& LEVELNODE_USEABSOLUTEPOS) + { + dOffsetX = (FLOAT)(pNode->sRelativeX - gsRenderCenterX); + dOffsetY = (FLOAT)(pNode->sRelativeY - gsRenderCenterY); + + // OK, DONT'T ASK... CONVERSION TO PROPER Y NEEDS THIS... + dOffsetX -= CELL_Y_SIZE; + + FloatFromCellToScreenCoordinates(dOffsetX, dOffsetY, &dTempX_S, &dTempY_S); + + sXPos = ((gsVIEWPORT_END_X - gsVIEWPORT_START_X) / 2) + (INT16)SHORT_ROUND(dTempX_S); + sYPos = ((gsVIEWPORT_END_Y - gsVIEWPORT_START_Y) / 2) + (INT16)SHORT_ROUND(dTempY_S); + + // Adjust for offset position on screen + sXPos -= gsRenderWorldOffsetX; + sYPos -= gsRenderWorldOffsetY; + + + sYPos -= pNode->sRelativeZ; + + } + + } + + // COUNT # OF ITEMS AT THIS LOCATION + if (uiLevelNodeFlags & LEVELNODE_ITEM) + { + // OK set item pool for this location.... + if (bItemCount == 0) + { + pItemPool = pNode->pItemPool; + } + else + { + pItemPool = pItemPool->pNext; + } + + if (bItemCount < MAX_RENDERED_ITEMS) + { + bItemCount++; + + if (gWorldItems[pItemPool->iItemIndex].bVisible == VISIBLE) + { + bVisibleItemCount++; + } + } + + // LIMIT RENDERING OF ITEMS TO ABOUT 7, DO NOT RENDER HIDDEN ITEMS TOO! + if (bVisibleItemCount == MAX_RENDERED_ITEMS || (gWorldItems[pItemPool->iItemIndex].bVisible != VISIBLE) || (pItemPool->usFlags & WORLD_ITEM_DONTRENDER)) + { + if (!(gTacticalStatus.uiFlags&SHOW_ALL_ITEMS)) + { + //CONTINUE, DONOT RENDER + if (!fLinkedListDirection) + pNode = pNode->pPrevNode; + else + pNode = pNode->pNext; + continue; + } + } + + if (guiCurrentScreen == EDIT_SCREEN) + { + // ATE: If in the editor, change this to a little higher value + if (bItemCount == MAX_RENDERED_ITEMS) + { + //CONTINUE, DONOT RENDER + if (!fLinkedListDirection) + pNode = pNode->pPrevNode; + else + pNode = pNode->pNext; + continue; + } + } + if (pItemPool->bRenderZHeightAboveLevel > 0) + { + sYPos -= pItemPool->bRenderZHeightAboveLevel; + } + + } + + // If render tile is false... + if (!fRenderTile) + { + if (!fLinkedListDirection) + pNode = pNode->pPrevNode; + else + pNode = pNode->pNext; + + continue; + } + } + + // specific code for node types on a per-tile basis + switch (uiRowFlags) + { + case TILES_STATIC_LAND: + + sZLevel = LandZLevel(iTempPosX_M, iTempPosY_M); + break; + + case TILES_STATIC_OBJECTS: + + // ATE: Modified to use constant z level, as these are same level as land items + sZLevel = ObjectZLevel(TileElem, pNode, uiTileElemFlags, iTempPosX_M, iTempPosY_M, sWorldY); + break; + + case TILES_STATIC_STRUCTURES: + + StructZLevel(iTempPosX_M, iTempPosY_M); + + if (fUseTileElem && (TileElem->uiFlags & MULTI_Z_TILE)) + { + fMultiZBlitter = TRUE; + } + + // ATE: if we are a wall, set flag + if (fUseTileElem && (TileElem->uiFlags & WALL_TILE)) + { + fWallTile = TRUE; + } + + break; + + case TILES_STATIC_ROOF: + + sZLevel = RoofZLevel(iTempPosX_M, iTempPosY_M, sWorldY); + + // Automatically adjust height! + sYPos -= WALL_HEIGHT; + + // ATE: Added for shadows on roofs + if (fUseTileElem && (TileElem->uiFlags & ROOFSHADOW_TILE)) + { + fShadowBlitter = TRUE; + } + break; + case TILES_STATIC_ONROOF: + + sZLevel = OnRoofZLevel(iTempPosX_M, iTempPosY_M, sWorldY, uiLevelNodeFlags); + // Automatically adjust height! + sYPos -= WALL_HEIGHT; + break; + + case TILES_STATIC_TOPMOST: + + sZLevel = TopmostZLevel(iTempPosX_M, iTempPosY_M, sWorldY); + break; + + case TILES_STATIC_SHADOWS: + + sZLevel = ShadowZLevel(iTempPosX_M, iTempPosY_M, sWorldY); + + if (uiLevelNodeFlags & LEVELNODE_EXITGRID) + { + fIntensityBlitter = TRUE; + fShadowBlitter = FALSE; + } + break; + + case TILES_DYNAMIC_LAND: + + sZLevel = LandZLevel(iTempPosX_M, iTempPosY_M); + uiDirtyFlags = BGND_FLAG_SINGLE | BGND_FLAG_ANIMATED; + break; + case TILES_DYNAMIC_SHADOWS: + + sZLevel = ShadowZLevel(iTempPosX_M, iTempPosY_M, sWorldY); + //sZLevel=SHADOW_Z_LEVEL; + uiDirtyFlags = BGND_FLAG_SINGLE | BGND_FLAG_ANIMATED; + break; + case TILES_DYNAMIC_OBJECTS: + + sZLevel = ObjectZLevel(TileElem, pNode, uiTileElemFlags, iTempPosX_M, iTempPosY_M, sWorldY); + uiDirtyFlags = BGND_FLAG_SINGLE | BGND_FLAG_ANIMATED; + break; + + case TILES_DYNAMIC_STRUCTURES: + + StructZLevel(iTempPosX_M, iTempPosY_M); + uiDirtyFlags = BGND_FLAG_SINGLE | BGND_FLAG_ANIMATED; + + if (uiTileElemFlags & Z_AWARE_DYNAMIC_TILE) + { + fMultiZBlitter = TRUE; + fZBlitter = TRUE; + fWallTile = TRUE; + sZStripIndex = 0; + } + break; + case TILES_DYNAMIC_ROOF: + + sYPos -= WALL_HEIGHT; + + sZLevel = RoofZLevel(iTempPosX_M, iTempPosY_M, sWorldY); + uiDirtyFlags = BGND_FLAG_SINGLE | BGND_FLAG_ANIMATED; + // For now, adjust to hieght of a wall ( 50 temp, make define ) + //if ( TileElem->fType > FOOTPRINTS ) + //{ + // sYPos -= 58; + //} + break; + + case TILES_DYNAMIC_ONROOF: + + sZLevel = OnRoofZLevel(iTempPosX_M, iTempPosY_M, sWorldY, uiLevelNodeFlags); + uiDirtyFlags = BGND_FLAG_SINGLE | BGND_FLAG_ANIMATED; + // Automatically adjust height! + sYPos -= WALL_HEIGHT; + break; + + case TILES_DYNAMIC_TOPMOST: + sZLevel = TopmostZLevel(iTempPosX_M, iTempPosY_M, sWorldY); + uiDirtyFlags = BGND_FLAG_SINGLE | BGND_FLAG_ANIMATED; + break; + + case TILES_DYNAMIC_MERCS: + case TILES_DYNAMIC_HIGHMERCS: + case TILES_DYNAMIC_STRUCT_MERCS: + + // Set flag to set layer as used + uiAdditiveLayerUsedFlags |= uiRowFlags; + + pSoldier = pNode->pSoldier; + + if (uiRowFlags == TILES_DYNAMIC_MERCS) + { + // If we are multi-tiled, ignore here + if (pSoldier->flags.uiStatusFlags & (SOLDIER_MULTITILE_Z | SOLDIER_Z)) + { + pNode = pNode->pNext; + continue; + } + + // If we are at a higher level, no not do anything unless we are at the highmerc stage + if (pSoldier->pathing.bLevel > 0) + { + pNode = pNode->pNext; + continue; + } + } + + if (uiRowFlags == TILES_DYNAMIC_HIGHMERCS) + { + // If we are multi-tiled, ignore here + if (pSoldier->flags.uiStatusFlags & SOLDIER_MULTITILE_Z) + { + pNode = pNode->pNext; + continue; + } + + // If we are at a lower level, no not do anything unless we are at the highmerc stage + if (pSoldier->pathing.bLevel == 0) + { + pNode = pNode->pNext; + continue; + } + } + + + if (uiRowFlags == TILES_DYNAMIC_STRUCT_MERCS) + { + // If we are not multi-tiled, ignore here + if (!(pSoldier->flags.uiStatusFlags & (SOLDIER_MULTITILE_Z | SOLDIER_Z))) + { + // If we are at a low level, no not do anything unless we are at the merc stage + if (pSoldier->pathing.bLevel == 0) + { + pNode = pNode->pNext; + continue; + } + } + + if (pSoldier->flags.uiStatusFlags & (SOLDIER_MULTITILE_Z | SOLDIER_Z)) + { + fSaveZ = TRUE; + fZBlitter = TRUE; + + if (pSoldier->flags.uiStatusFlags & SOLDIER_MULTITILE_Z) + { + fMultiTransShadowZBlitter = TRUE; + // ATE: Use one direction for queen! + if (pSoldier->ubBodyType == QUEENMONSTER) + { + sMultiTransShadowZBlitterIndex = 0; + } + else + { + sMultiTransShadowZBlitterIndex = gOneCDirection[pSoldier->ubDirection]; + } + } + else + { + fZWrite = TRUE; + } + } + + } + + // IF we are not active, or are a placeholder for multi-tile animations do nothing + //if ( !pSoldier->bActive ) + if (!pSoldier->bActive || (uiLevelNodeFlags & LEVELNODE_MERCPLACEHOLDER)) + { + pNode = pNode->pNext; + continue; + } + + // Skip if we cannot see the guy! + if (pSoldier->bLastRenderVisibleValue == -1 && !(gTacticalStatus.uiFlags&SHOW_ALL_MERCS)) + { + pNode = pNode->pNext; + continue; + } + + + // Get animation surface.... + usAnimSurface = GetSoldierAnimationSurface(pSoldier, pSoldier->usAnimState); + + if (usAnimSurface == INVALID_ANIMATION_SURFACE) + { + pNode = pNode->pNext; + continue; + } + + + // Position guy based on guy's position + dOffsetX = pSoldier->dXPos - gsRenderCenterX; + dOffsetY = pSoldier->dYPos - gsRenderCenterY; + + + // Calculate guy's position + FloatFromCellToScreenCoordinates(dOffsetX, dOffsetY, &dTempX_S, &dTempY_S); + + sXPos = ((gsVIEWPORT_END_X - gsVIEWPORT_START_X) / 2) + (INT16)dTempX_S; + sYPos = ((gsVIEWPORT_END_Y - gsVIEWPORT_START_Y) / 2) + (INT16)dTempY_S - sTileHeight; + + // Adjust for offset position on screen + sXPos -= gsRenderWorldOffsetX; + sYPos -= gsRenderWorldOffsetY; + + // Adjust for soldier height + sYPos -= pSoldier->sHeightAdjustment; + + // Handle shade stuff.... + // bio: put the logic for determining the right shade table into inline fuction (called again for logical bodytype implementation) + // TODO: in case of a logical bodytype being used, the function does not have to be called here (if determining of log. bodytype is moved to the render entry fun. + pShadeTable = GetShadeTable(pNode, pSoldier, pSoldier, uiFlags, &gsForceSoldierZLevel); + + // Calculate Z level + SoldierZLevel(pSoldier, iTempPosX_M, iTempPosY_M); + + hVObject = gAnimSurfaceDatabase[usAnimSurface].hVideoObject; + + if (hVObject == NULL) + { + pNode = pNode->pNext; + continue; + } + + // ATE: If we are in a gridno that we should not use obscure blitter, set! + if (!(gpWorldLevelData[uiTileIndex].ubExtFlags[0] & MAPELEMENT_EXT_NOBURN_STRUCT)) + { + fObscuredBlitter = TRUE; + } + else + { + // ATE: Artificially increase z=level... + sZLevel += 2; + } + + usImageIndex = pSoldier->usAniFrame; + + // Flugente: frozen soldiers don't move + if (pSoldier->usSkillCooldown[SOLDIER_COOLDOWN_CRYO] && pSoldier->stats.bLife > 0) + { + usImageIndex = pSoldier->CryoAniFrame(); + } + + // Flugente: riot shields + if (pSoldier && + pSoldier->bVisible != -1 && + (pSoldier->ubDirection == NORTH || + pSoldier->ubDirection == NORTHWEST || + pSoldier->ubDirection == WEST) + && pSoldier->IsRiotShieldEquipped()) + { + ShowRiotShield(pSoldier); + } + + uiDirtyFlags = BGND_FLAG_SINGLE | BGND_FLAG_ANIMATED | BGND_FLAG_MERC; + break; } // Adjust for interface level @@ -1922,18 +1912,18 @@ void RenderTiles(UINT32 uiFlags, INT32 iStartPointX_M, INT32 iStartPointY_M, INT // OK, check for LEVELNODE HIDDEN... fHiddenTile = FALSE; - if ( uiLevelNodeFlags & LEVELNODE_HIDDEN ) + if (uiLevelNodeFlags & LEVELNODE_HIDDEN) { fHiddenTile = TRUE; - if ( TileElem != NULL ) + if (TileElem != NULL) { // If we are a roof and have SHOW_ALL_ROOFS on, turn off hidden tile check! //if ( ( TileElem->uiFlags & ROOF_TILE ) && ( gTacticalStatus.uiFlags&SHOW_ALL_ROOFS ) ) // anv: commented out TileElem->uiFlags & ROOF_TILE because: // 1. only roof tiles get hidden in this manner anyway // 2. we might want to his and reveal again other stuff (most importantly - on roof structures) - if ( ( gTacticalStatus.uiFlags&SHOW_ALL_ROOFS ) ) + if ((gTacticalStatus.uiFlags&SHOW_ALL_ROOFS)) { // Turn off fHiddenTile = FALSE; @@ -1942,11 +1932,11 @@ void RenderTiles(UINT32 uiFlags, INT32 iStartPointX_M, INT32 iStartPointY_M, INT } - if( fRenderTile && !fHiddenTile ) + if (fRenderTile && !fHiddenTile) { fTileInvisible = FALSE; - if ( ( uiLevelNodeFlags & LEVELNODE_ROTTINGCORPSE ) ) + if ((uiLevelNodeFlags & LEVELNODE_ROTTINGCORPSE)) { // Set fmerc flag! fMerc = TRUE; @@ -1954,119 +1944,184 @@ void RenderTiles(UINT32 uiFlags, INT32 iStartPointX_M, INT32 iStartPointY_M, INT //if ( hVObject->ppZStripInfo != NULL ) { - sMultiTransShadowZBlitterIndex = GetCorpseStructIndex( &( pCorpse->def ), TRUE ); + sMultiTransShadowZBlitterIndex = GetCorpseStructIndex(&(pCorpse->def), TRUE); fMultiTransShadowZBlitter = TRUE; } } - if ( (uiLevelNodeFlags & LEVELNODE_LASTDYNAMIC ) && !(uiFlags&TILES_DIRTY) ) + if ((uiLevelNodeFlags & LEVELNODE_LASTDYNAMIC) && !(uiFlags&TILES_DIRTY)) { // Remove flags! - pNode->uiFlags &= (~LEVELNODE_LASTDYNAMIC ); + pNode->uiFlags &= (~LEVELNODE_LASTDYNAMIC); fZWrite = TRUE; } - if ( uiLevelNodeFlags & LEVELNODE_NOWRITEZ ) + if (uiLevelNodeFlags & LEVELNODE_NOWRITEZ) { fZWrite = FALSE; } - if(uiFlags&TILES_NOZWRITE) - fZWrite=FALSE; + if (uiFlags&TILES_NOZWRITE) + fZWrite = FALSE; - if ( uiFlags & TILES_NOZ ) + if (uiFlags & TILES_NOZ) { - fZBlitter = FALSE; + fZBlitter = FALSE; } - if ( ( uiLevelNodeFlags & LEVELNODE_WIREFRAME ) ) + if ((uiLevelNodeFlags & LEVELNODE_WIREFRAME)) { - if ( !gGameSettings.fOptions[ TOPTION_TOGGLE_WIREFRAME ] ) + if (!gGameSettings.fOptions[TOPTION_TOGGLE_WIREFRAME]) { - fTileInvisible = TRUE; + fTileInvisible = TRUE; } } + using namespace LogicalBodyTypes; + static BodyTypeDB * bodyTypeDB = &BodyTypeDB::Instance(); + static Layers::LayerPropertiesVector::size_type numLayers = max(1, Layers::Instance().GetCount()); //defaults to 1 in case the layers.xml file could not be read + // TODO: should find a better place to determine the logical body type. This function gets called like a gazillion times + // every render cycle and the find provedure will get quite expensive at later stages (lots of logical body types, animations and filters!) + // Should only be done once every cycle, or better yet, only and directly after a SOLDIERTYPE object has been altered (if at all possible)! + BodyType * bt = NULL; + if ((gGameSettings.fOptions[TOPTION_USE_LOGICAL_BODYTYPES] == TRUE) + && (uiRowFlags == TILES_DYNAMIC_MERCS || uiRowFlags == TILES_DYNAMIC_HIGHMERCS || uiRowFlags == TILES_DYNAMIC_STRUCT_MERCS)) + { + bt = bodyTypeDB->Find(pSoldier); + } + UINT16 * pDefaultShadeTable = pShadeTable; + RECT backRect; + memset(&backRect, 0, sizeof(backRect)); // var actually only needed if uiFlags & TILES_DIRTY, but leaving stuff uninitialized... + + Layers::LayerGraphIterator layerIter; + Layers::LayerGraphIterator layerEnd; + if (bt != NULL) + { + layerIter = Layers::Instance().GetIterator(pSoldier->bMovementDirection); + layerEnd = Layers::Instance().GetIterationEnd(pSoldier->bMovementDirection); + } + + HVOBJECT hVObjectAlpha = NULL; + while ((bt == NULL) || (layerIter != layerEnd)) + { + bool fIgnoreShadows = false; + if (bt != NULL) + { + BodyType::LogicalSurfaceType * logSurfaceType = bt->GetLogicalSurfaceType(layerIter->index, pSoldier); + if (logSurfaceType != NULL) + { + const Layers::LayerProperties * layerProperties = bt->GetLayerProperties(layerIter->index); + fIgnoreShadows = !layerProperties->renderShadows; + if (!layerProperties->render) + { + layerIter++; + continue; + } + hVObject = logSurfaceType->physicalSurfaceType->hVideoObject; + if (hVObject == NULL) + { + layerIter++; + continue; + } + if (logSurfaceType->alphaSurfaceType != NULL) { + hVObjectAlpha = logSurfaceType->alphaSurfaceType->hVideoObject; + } + if (logSurfaceType->paletteTable != NULL) + { + pShadeTable = GetShadeTable(pNode, pSoldier, (SOLDIERTYPE *)logSurfaceType->paletteTable, uiFlags, &gsForceSoldierZLevel); + } + else + { + pShadeTable = pDefaultShadeTable; + } + } + else + { + layerIter++; + continue; + } + } + // RENDER - if ( fTileInvisible ) + if (fTileInvisible) { } - else if ( uiLevelNodeFlags & LEVELNODE_DISPLAY_AP && !( uiFlags&TILES_DIRTY ) ) + else if (uiLevelNodeFlags & LEVELNODE_DISPLAY_AP && !(uiFlags&TILES_DIRTY)) { pTrav = &(hVObject->pETRLEObject[usImageIndex]); sXPos += pTrav->sOffsetX; sYPos += pTrav->sOffsetY; - if ( gfUIDisplayActionPointsInvalid ) + if (gfUIDisplayActionPointsInvalid) { - SetFontBackground( FONT_MCOLOR_BLACK ); - SetFontForeground( FONT_MCOLOR_WHITE ); + SetFontBackground(FONT_MCOLOR_BLACK); + SetFontForeground(FONT_MCOLOR_WHITE); } else { - SetFontBackground( FONT_MCOLOR_BLACK ); - SetFontForeground( FONT_MCOLOR_WHITE ); + SetFontBackground(FONT_MCOLOR_BLACK); + SetFontForeground(FONT_MCOLOR_WHITE); } - if ( gfUIDisplayActionPointsBlack ) + if (gfUIDisplayActionPointsBlack) { - SetFontBackground( FONT_MCOLOR_BLACK ); - SetFontForeground( FONT_MCOLOR_BLACK ); + SetFontBackground(FONT_MCOLOR_BLACK); + SetFontForeground(FONT_MCOLOR_BLACK); } - SetFont( TINYFONT1 ); - SetFontDestBuffer( guiSAVEBUFFER , 0, gsVIEWPORT_WINDOW_START_Y, SCREEN_WIDTH, gsVIEWPORT_WINDOW_END_Y, FALSE ); - VarFindFontCenterCoordinates( sXPos, sYPos, 1, 1, TINYFONT1, &sX, &sY, L"%d", pNode->uiAPCost ); - mprintf_buffer( pDestBuf, uiDestPitchBYTES, TINYFONT1, sX, sY , L"%d", pNode->uiAPCost ); - SetFontDestBuffer( FRAME_BUFFER , 0, 0, SCREEN_WIDTH, SCREEN_HEIGHT, FALSE ); + SetFont(TINYFONT1); + SetFontDestBuffer(guiSAVEBUFFER, 0, gsVIEWPORT_WINDOW_START_Y, SCREEN_WIDTH, gsVIEWPORT_WINDOW_END_Y, FALSE); + VarFindFontCenterCoordinates(sXPos, sYPos, 1, 1, TINYFONT1, &sX, &sY, L"%d", pNode->uiAPCost); + mprintf_buffer(pDestBuf, uiDestPitchBYTES, TINYFONT1, sX, sY, L"%d", pNode->uiAPCost); + SetFontDestBuffer(FRAME_BUFFER, 0, 0, SCREEN_WIDTH, SCREEN_HEIGHT, FALSE); } - else if ( ( uiLevelNodeFlags & LEVELNODE_ERASEZ ) && !( uiFlags&TILES_DIRTY ) ) + else if ((uiLevelNodeFlags & LEVELNODE_ERASEZ) && !(uiFlags&TILES_DIRTY)) { - Zero8BPPDataTo16BPPBufferTransparent( (UINT16*)pDestBuf, uiDestPitchBYTES, hVObject, sXPos, sYPos, usImageIndex ); + Zero8BPPDataTo16BPPBufferTransparent((UINT16*)pDestBuf, uiDestPitchBYTES, hVObject, sXPos, sYPos, usImageIndex); //Zero8BPPDataTo16BPPBufferTransparent( (UINT16*)gpZBuffer, uiDestPitchBYTES, hVObject, sXPos, sYPos, usImageIndex ); } - else if ( ( uiLevelNodeFlags & LEVELNODE_ITEM ) && !( uiFlags&TILES_DIRTY ) ) + else if ((uiLevelNodeFlags & LEVELNODE_ITEM) && !(uiFlags&TILES_DIRTY)) { - BOOLEAN fZBlit = FALSE; + BOOLEAN fZBlit = FALSE; - if ( uiRowFlags == TILES_STATIC_ONROOF || uiRowFlags == TILES_DYNAMIC_ONROOF ) + if (uiRowFlags == TILES_STATIC_ONROOF || uiRowFlags == TILES_DYNAMIC_ONROOF) + { + usOutlineColor = gusYellowItemOutlineColor; + bItemOutline = TRUE; + fZBlit = TRUE; + } + else + { + usOutlineColor = gusNormalItemOutlineColor; + bItemOutline = TRUE; + fZBlit = TRUE; + } + + if (gGameSettings.fOptions[TOPTION_GLOW_ITEMS]) + { + if (uiRowFlags == TILES_STATIC_ONROOF || uiRowFlags == TILES_DYNAMIC_ONROOF) { - usOutlineColor = gusYellowItemOutlineColor; + usOutlineColor = us16BPPItemCycleYellowColors[gsCurrentItemGlowFrame]; bItemOutline = TRUE; - fZBlit = TRUE; } else { - usOutlineColor = gusNormalItemOutlineColor; - bItemOutline = TRUE; - fZBlit = TRUE; - } - - if ( gGameSettings.fOptions[ TOPTION_GLOW_ITEMS ] ) - { - if ( uiRowFlags == TILES_STATIC_ONROOF || uiRowFlags == TILES_DYNAMIC_ONROOF ) - { - usOutlineColor = us16BPPItemCycleYellowColors[ gsCurrentItemGlowFrame ]; - bItemOutline = TRUE; - } - else - { - if ( gTacticalStatus.uiFlags & RED_ITEM_GLOW_ON ) - { - usOutlineColor = us16BPPItemCycleRedColors[ gsCurrentItemGlowFrame ]; - bItemOutline = TRUE; - } - else - { - usOutlineColor = us16BPPItemCycleWhiteColors[ gsCurrentItemGlowFrame ]; - bItemOutline = TRUE; - } - } + if (gTacticalStatus.uiFlags & RED_ITEM_GLOW_ON) + { + usOutlineColor = us16BPPItemCycleRedColors[gsCurrentItemGlowFrame]; + bItemOutline = TRUE; + } + else + { + usOutlineColor = us16BPPItemCycleWhiteColors[gsCurrentItemGlowFrame]; + bItemOutline = TRUE; + } } + } //else //{ @@ -2074,102 +2129,107 @@ void RenderTiles(UINT32 uiFlags, INT32 iStartPointX_M, INT32 iStartPointY_M, INT // bItemOutline = TRUE; //} - bBlitClipVal = BltIsClippedOrOffScreen(hVObject, sXPos, sYPos, usImageIndex, &gClippingRect); + bBlitClipVal = BltIsClippedOrOffScreen(hVObject, sXPos, sYPos, usImageIndex, &gClippingRect); - if ( bBlitClipVal == FALSE ) + if (bBlitClipVal == FALSE) + { + if (fZBlit) { - if ( fZBlit ) + if (fObscuredBlitter) { - if ( fObscuredBlitter ) - { - Blt8BPPDataTo16BPPBufferOutlineZPixelateObscured( (UINT16*)pDestBuf, uiDestPitchBYTES, gpZBuffer, sZLevel, hVObject, sXPos, sYPos, usImageIndex, usOutlineColor, bItemOutline ); - } - else - { - Blt8BPPDataTo16BPPBufferOutlineZ((UINT16*)pDestBuf, uiDestPitchBYTES, gpZBuffer, sZLevel, hVObject, sXPos, sYPos, usImageIndex, usOutlineColor, bItemOutline ); - } + Blt8BPPDataTo16BPPBufferOutlineZPixelateObscured((UINT16*)pDestBuf, uiDestPitchBYTES, gpZBuffer, sZLevel, hVObject, sXPos, sYPos, usImageIndex, usOutlineColor, bItemOutline); } else { - Blt8BPPDataTo16BPPBufferOutline((UINT16*)pDestBuf, uiDestPitchBYTES, hVObject, sXPos, sYPos, usImageIndex, usOutlineColor, bItemOutline ); - } - } - else if ( bBlitClipVal == TRUE ) - { - if ( fZBlit ) - { - if ( fObscuredBlitter ) - { - Blt8BPPDataTo16BPPBufferOutlineZPixelateObscuredClip( (UINT16*)pDestBuf, uiDestPitchBYTES, gpZBuffer, sZLevel, hVObject, sXPos, sYPos, usImageIndex, usOutlineColor, bItemOutline, &gClippingRect ); - } - else - { - Blt8BPPDataTo16BPPBufferOutlineZClip((UINT16*)pDestBuf, uiDestPitchBYTES, gpZBuffer, sZLevel, hVObject, sXPos, sYPos, usImageIndex, usOutlineColor, bItemOutline, &gClippingRect ); - } - } - else - { - Blt8BPPDataTo16BPPBufferOutlineClip((UINT16*)pDestBuf, uiDestPitchBYTES, hVObject, sXPos, sYPos, usImageIndex, usOutlineColor, bItemOutline, &gClippingRect ); - } - } - } - // ATE: Check here for a lot of conditions! - else if ( ( ( uiLevelNodeFlags & LEVELNODE_PHYSICSOBJECT ) ) && !( uiFlags&TILES_DIRTY ) ) - { - bItemOutline = TRUE; - - if ( uiLevelNodeFlags & LEVELNODE_PHYSICSOBJECT ) - { - bItemOutline = FALSE; - } - - bBlitClipVal = BltIsClippedOrOffScreen(hVObject, sXPos, sYPos, usImageIndex, &gClippingRect); - - if ( fShadowBlitter ) - { - if ( bBlitClipVal == FALSE ) - { - Blt8BPPDataTo16BPPBufferShadowZNB( (UINT16*)pDestBuf, uiDestPitchBYTES, gpZBuffer, sZLevel, hVObject, sXPos, sYPos, usImageIndex ); - } - else - { - Blt8BPPDataTo16BPPBufferShadowZNBClip( (UINT16*)pDestBuf, uiDestPitchBYTES, gpZBuffer, sZLevel, hVObject, sXPos, sYPos, usImageIndex, &gClippingRect ); + Blt8BPPDataTo16BPPBufferOutlineZ((UINT16*)pDestBuf, uiDestPitchBYTES, gpZBuffer, sZLevel, hVObject, sXPos, sYPos, usImageIndex, usOutlineColor, bItemOutline); } } else { - if ( bBlitClipVal == FALSE ) + Blt8BPPDataTo16BPPBufferOutline((UINT16*)pDestBuf, uiDestPitchBYTES, hVObject, sXPos, sYPos, usImageIndex, usOutlineColor, bItemOutline); + } + } + else if (bBlitClipVal == TRUE) + { + if (fZBlit) + { + if (fObscuredBlitter) { - Blt8BPPDataTo16BPPBufferOutlineZNB((UINT16*)pDestBuf, uiDestPitchBYTES, gpZBuffer, sZLevel, hVObject, sXPos, sYPos, usImageIndex, usOutlineColor, bItemOutline ); + Blt8BPPDataTo16BPPBufferOutlineZPixelateObscuredClip((UINT16*)pDestBuf, uiDestPitchBYTES, gpZBuffer, sZLevel, hVObject, sXPos, sYPos, usImageIndex, usOutlineColor, bItemOutline, &gClippingRect); } - else if ( bBlitClipVal == TRUE ) + else { - Blt8BPPDataTo16BPPBufferOutlineClip((UINT16*)pDestBuf, uiDestPitchBYTES, hVObject, sXPos, sYPos, usImageIndex, usOutlineColor, bItemOutline, &gClippingRect ); + Blt8BPPDataTo16BPPBufferOutlineZClip((UINT16*)pDestBuf, uiDestPitchBYTES, gpZBuffer, sZLevel, hVObject, sXPos, sYPos, usImageIndex, usOutlineColor, bItemOutline, &gClippingRect); } } + else + { + Blt8BPPDataTo16BPPBufferOutlineClip((UINT16*)pDestBuf, uiDestPitchBYTES, hVObject, sXPos, sYPos, usImageIndex, usOutlineColor, bItemOutline, &gClippingRect); + } + } } - else if(uiFlags&TILES_DIRTY) + // ATE: Check here for a lot of conditions! + else if (((uiLevelNodeFlags & LEVELNODE_PHYSICSOBJECT)) && !(uiFlags&TILES_DIRTY)) + { + bItemOutline = TRUE; + + if (uiLevelNodeFlags & LEVELNODE_PHYSICSOBJECT) + { + bItemOutline = FALSE; + } + + bBlitClipVal = BltIsClippedOrOffScreen(hVObject, sXPos, sYPos, usImageIndex, &gClippingRect); + + if (fShadowBlitter) + { + if (bBlitClipVal == FALSE) + { + Blt8BPPDataTo16BPPBufferShadowZNB((UINT16*)pDestBuf, uiDestPitchBYTES, gpZBuffer, sZLevel, hVObject, sXPos, sYPos, usImageIndex); + } + else + { + Blt8BPPDataTo16BPPBufferShadowZNBClip((UINT16*)pDestBuf, uiDestPitchBYTES, gpZBuffer, sZLevel, hVObject, sXPos, sYPos, usImageIndex, &gClippingRect); + } + } + else + { + if (bBlitClipVal == FALSE) + { + Blt8BPPDataTo16BPPBufferOutlineZNB((UINT16*)pDestBuf, uiDestPitchBYTES, gpZBuffer, sZLevel, hVObject, sXPos, sYPos, usImageIndex, usOutlineColor, bItemOutline); + } + else if (bBlitClipVal == TRUE) + { + Blt8BPPDataTo16BPPBufferOutlineClip((UINT16*)pDestBuf, uiDestPitchBYTES, hVObject, sXPos, sYPos, usImageIndex, usOutlineColor, bItemOutline, &gClippingRect); + } + } + } + else if (uiFlags&TILES_DIRTY) { - if ( !(uiLevelNodeFlags & LEVELNODE_LASTDYNAMIC ) ) + if (!(uiLevelNodeFlags & LEVELNODE_LASTDYNAMIC)) { + // changed the logic to determine the maximum dimensions of the needed back rect + // in case of multi layering. Actual registering of back rect done after layer loop pTrav = &(hVObject->pETRLEObject[usImageIndex]); - uiBrushHeight = (UINT32)pTrav->usHeight; + uiBrushHeight = (UINT32)pTrav->usHeight; uiBrushWidth = (UINT32)pTrav->usWidth; - sXPos += pTrav->sOffsetX; - sYPos += pTrav->sOffsetY; - - RegisterBackgroundRect(uiDirtyFlags, NULL, sXPos, sYPos, (INT16)(sXPos + uiBrushWidth), (INT16)(__min((INT16)(sYPos + uiBrushHeight), gsVIEWPORT_WINDOW_END_Y))); - - if ( fSaveZ ) - { - RegisterBackgroundRect(uiDirtyFlags | BGND_FLAG_SAVE_Z, NULL, sXPos, sYPos, (INT16)(sXPos + uiBrushWidth), (INT16)(__min((INT16)(sYPos + uiBrushHeight), gsVIEWPORT_WINDOW_END_Y))); - } + INT32 rLeft = sXPos + pTrav->sOffsetX; + INT32 rTop = sYPos + pTrav->sOffsetY; + /* + backRect.left = ( !layer ) ? rLeft : min ( backRect.left, rLeft ); + backRect.top = ( !layer ) ? rTop : min ( backRect.top, rTop ); + backRect.right = ( !layer ) ? rLeft + ( INT32 ) uiBrushWidth : max ( backRect.right, rLeft + ( INT32 ) uiBrushWidth ); + backRect.bottom = ( !layer ) ? rTop + ( INT32 ) uiBrushHeight : max ( backRect.bottom, rTop + ( INT32 ) uiBrushHeight ); + */ + backRect.left = min(backRect.left, rLeft); + backRect.top = min(backRect.top, rTop); + backRect.right = max(backRect.right, rLeft + (INT32)uiBrushWidth); + backRect.bottom = max(backRect.bottom, rTop + (INT32)uiBrushHeight); } } else { - if(gbPixelDepth==16) + if (gbPixelDepth == 16) { /*if(fConvertTo16) { @@ -2180,17 +2240,27 @@ void RenderTiles(UINT32 uiFlags, INT32 iStartPointX_M, INT32 iStartPointY_M, INT } }*/ - if( fMultiTransShadowZBlitter ) + if (fMultiTransShadowZBlitter) { - if ( fZBlitter ) + if (fZBlitter) { - if ( fObscuredBlitter ) + if (fObscuredBlitter) { - Blt8BPPDataTo16BPPBufferTransZTransShadowIncObscureClip((UINT16*)pDestBuf, uiDestPitchBYTES, gpZBuffer, sZLevel, hVObject, sXPos, sYPos, usImageIndex, &gClippingRect, sMultiTransShadowZBlitterIndex, pShadeTable ); + if (hVObjectAlpha == NULL) { + Blt8BPPDataTo16BPPBufferTransZTransShadowIncObscureClip((UINT16*)pDestBuf, uiDestPitchBYTES, gpZBuffer, sZLevel, hVObject, sXPos, sYPos, usImageIndex, &gClippingRect, sMultiTransShadowZBlitterIndex, pShadeTable, fIgnoreShadows); + } + else { + Blt8BPPDataTo16BPPBufferTransZTransShadowIncObscureClipAlpha((UINT16*)pDestBuf, uiDestPitchBYTES, gpZBuffer, sZLevel, hVObject, hVObjectAlpha, sXPos, sYPos, usImageIndex, &gClippingRect, sMultiTransShadowZBlitterIndex, pShadeTable, fIgnoreShadows); + } } else { - Blt8BPPDataTo16BPPBufferTransZTransShadowIncClip((UINT16*)pDestBuf, uiDestPitchBYTES, gpZBuffer, sZLevel, hVObject, sXPos, sYPos, usImageIndex, &gClippingRect, sMultiTransShadowZBlitterIndex, pShadeTable ); + if (hVObjectAlpha == NULL) { + Blt8BPPDataTo16BPPBufferTransZTransShadowIncClip((UINT16*)pDestBuf, uiDestPitchBYTES, gpZBuffer, sZLevel, hVObject, sXPos, sYPos, usImageIndex, &gClippingRect, sMultiTransShadowZBlitterIndex, pShadeTable, fIgnoreShadows); + } + else { + Blt8BPPDataTo16BPPBufferTransZTransShadowIncClipAlpha((UINT16*)pDestBuf, uiDestPitchBYTES, gpZBuffer, sZLevel, hVObject, hVObjectAlpha, sXPos, sYPos, usImageIndex, &gClippingRect, sMultiTransShadowZBlitterIndex, pShadeTable, fIgnoreShadows); + } } } else @@ -2198,25 +2268,25 @@ void RenderTiles(UINT32 uiFlags, INT32 iStartPointX_M, INT32 iStartPointY_M, INT //Blt8BPPDataTo16BPPBufferTransparentClip((UINT16*)pDestBuf, uiDestPitchBYTES, hVObject, sXPos, sYPos, usImageIndex, &gClippingRect ); } } - else if( fMultiZBlitter ) + else if (fMultiZBlitter) { - if ( fZBlitter ) + if (fZBlitter) { - if ( fObscuredBlitter ) + if (fObscuredBlitter) { Blt8BPPDataTo16BPPBufferTransZIncObscureClip((UINT16*)pDestBuf, uiDestPitchBYTES, gpZBuffer, sZLevel, hVObject, sXPos, sYPos, usImageIndex, &gClippingRect); } else { - if ( fWallTile ) + if (fWallTile) { - if ( sZStripIndex == -1 ) + if (sZStripIndex == -1) { Blt8BPPDataTo16BPPBufferTransZIncClipZSameZBurnsThrough((UINT16*)pDestBuf, uiDestPitchBYTES, gpZBuffer, sZLevel, hVObject, sXPos, sYPos, usImageIndex, &gClippingRect, usImageIndex); } else { - Blt8BPPDataTo16BPPBufferTransZIncClipZSameZBurnsThrough((UINT16*)pDestBuf, uiDestPitchBYTES, gpZBuffer, sZLevel, hVObject, sXPos, sYPos, usImageIndex, &gClippingRect, sZStripIndex ); + Blt8BPPDataTo16BPPBufferTransZIncClipZSameZBurnsThrough((UINT16*)pDestBuf, uiDestPitchBYTES, gpZBuffer, sZLevel, hVObject, sXPos, sYPos, usImageIndex, &gClippingRect, sZStripIndex); } } else @@ -2227,130 +2297,204 @@ void RenderTiles(UINT32 uiFlags, INT32 iStartPointX_M, INT32 iStartPointY_M, INT } else { - Blt8BPPDataTo16BPPBufferTransparentClip((UINT16*)pDestBuf, uiDestPitchBYTES, hVObject, sXPos, sYPos, usImageIndex, &gClippingRect ); + Blt8BPPDataTo16BPPBufferTransparentClip((UINT16*)pDestBuf, uiDestPitchBYTES, hVObject, sXPos, sYPos, usImageIndex, &gClippingRect); } } else { bBlitClipVal = BltIsClippedOrOffScreen(hVObject, sXPos, sYPos, usImageIndex, &gClippingRect); - if ( bBlitClipVal == TRUE ) + if (bBlitClipVal == TRUE) { - if(fPixelate) + if (fPixelate) { - if(fTranslucencyType) + if (fTranslucencyType) { //if(fZWrite) // Blt8BPPDataTo16BPPBufferTransZClipTranslucent((UINT16*)pDestBuf, uiDestPitchBYTES, gpZBuffer, sZLevel, hVObject, sXPos, sYPos, usImageIndex, &gClippingRect); //else - Blt8BPPDataTo16BPPBufferTransZNBClipTranslucent((UINT16*)pDestBuf, uiDestPitchBYTES, gpZBuffer, sZLevel, hVObject, sXPos, sYPos, usImageIndex, &gClippingRect); + Blt8BPPDataTo16BPPBufferTransZNBClipTranslucent((UINT16*)pDestBuf, uiDestPitchBYTES, gpZBuffer, sZLevel, hVObject, sXPos, sYPos, usImageIndex, &gClippingRect); } else { //if(fZWrite) // Blt8BPPDataTo16BPPBufferTransZClipPixelate((UINT16*)pDestBuf, uiDestPitchBYTES, gpZBuffer, sZLevel, hVObject, sXPos, sYPos, usImageIndex, &gClippingRect); //else - Blt8BPPDataTo16BPPBufferTransZNBClipPixelate((UINT16*)pDestBuf, uiDestPitchBYTES, gpZBuffer, sZLevel, hVObject, sXPos, sYPos, usImageIndex, &gClippingRect); + Blt8BPPDataTo16BPPBufferTransZNBClipPixelate((UINT16*)pDestBuf, uiDestPitchBYTES, gpZBuffer, sZLevel, hVObject, sXPos, sYPos, usImageIndex, &gClippingRect); } } - else if(fMerc) + else if (fMerc) { - if ( fZBlitter ) + if (fZBlitter) { - if ( fZWrite ) + if (fZWrite) { - Blt8BPPDataTo16BPPBufferTransShadowZClip( (UINT16*)pDestBuf, uiDestPitchBYTES, gpZBuffer, sZLevel, - hVObject, - sXPos, sYPos, - usImageIndex, - &gClippingRect, - pShadeTable); - } - else - { - if ( fObscuredBlitter ) + if (hVObjectAlpha != NULL) { - - Blt8BPPDataTo16BPPBufferTransShadowZNBObscuredClip( (UINT16*)pDestBuf, uiDestPitchBYTES, gpZBuffer, sZLevel, - hVObject, - sXPos, sYPos, - usImageIndex, - &gClippingRect, - pShadeTable); + Blt8BPPDataTo16BPPBufferTransShadowZClipAlpha((UINT16*)pDestBuf, uiDestPitchBYTES, gpZBuffer, sZLevel, + hVObject, + hVObjectAlpha, + sXPos, sYPos, + usImageIndex, + &gClippingRect, + pShadeTable, + fIgnoreShadows); } else { - Blt8BPPDataTo16BPPBufferTransShadowZNBClip( (UINT16*)pDestBuf, uiDestPitchBYTES, gpZBuffer, sZLevel, - hVObject, - sXPos, sYPos, - usImageIndex, - &gClippingRect, - pShadeTable); + Blt8BPPDataTo16BPPBufferTransShadowZClip((UINT16*)pDestBuf, uiDestPitchBYTES, gpZBuffer, sZLevel, + hVObject, + sXPos, sYPos, + usImageIndex, + &gClippingRect, + pShadeTable, + fIgnoreShadows); + } + } + else + { + if (fObscuredBlitter) + { + if (hVObjectAlpha != NULL) + { + Blt8BPPDataTo16BPPBufferTransShadowZNBObscuredClipAlpha((UINT16*)pDestBuf, uiDestPitchBYTES, gpZBuffer, sZLevel, + hVObject, + hVObjectAlpha, + sXPos, sYPos, + usImageIndex, + &gClippingRect, + pShadeTable, + fIgnoreShadows); + } + else + { + Blt8BPPDataTo16BPPBufferTransShadowZNBObscuredClip((UINT16*)pDestBuf, uiDestPitchBYTES, gpZBuffer, sZLevel, + hVObject, + sXPos, sYPos, + usImageIndex, + &gClippingRect, + pShadeTable, + fIgnoreShadows); + } + } + else + { + if (hVObjectAlpha != NULL) + { + Blt8BPPDataTo16BPPBufferTransShadowZNBClipAlpha((UINT16*)pDestBuf, uiDestPitchBYTES, gpZBuffer, sZLevel, + hVObject, + hVObjectAlpha, + sXPos, sYPos, + usImageIndex, + &gClippingRect, + pShadeTable, + fIgnoreShadows); + } + else + { + Blt8BPPDataTo16BPPBufferTransShadowZNBClip((UINT16*)pDestBuf, uiDestPitchBYTES, gpZBuffer, sZLevel, + hVObject, + sXPos, sYPos, + usImageIndex, + &gClippingRect, + pShadeTable, + fIgnoreShadows); + } } } - if ( (uiLevelNodeFlags & LEVELNODE_UPDATESAVEBUFFERONCE ) ) + if ((uiLevelNodeFlags & LEVELNODE_UPDATESAVEBUFFERONCE)) { - pSaveBuf = LockVideoSurface(guiSAVEBUFFER, &uiSaveBufferPitchBYTES ); + pSaveBuf = LockVideoSurface(guiSAVEBUFFER, &uiSaveBufferPitchBYTES); // BLIT HERE - Blt8BPPDataTo16BPPBufferTransShadowClip( (UINT16*)pSaveBuf, uiSaveBufferPitchBYTES, - hVObject, - sXPos, sYPos, - usImageIndex, - &gClippingRect, - pShadeTable); + if (hVObjectAlpha != NULL) + { + Blt8BPPDataTo16BPPBufferTransShadowClipAlpha((UINT16*)pSaveBuf, uiSaveBufferPitchBYTES, + hVObject, + hVObjectAlpha, + sXPos, sYPos, + usImageIndex, + &gClippingRect, + pShadeTable, + fIgnoreShadows); + } + else + { + Blt8BPPDataTo16BPPBufferTransShadowClip((UINT16*)pSaveBuf, uiSaveBufferPitchBYTES, + hVObject, + sXPos, sYPos, + usImageIndex, + &gClippingRect, + pShadeTable, + fIgnoreShadows); + } UnLockVideoSurface(guiSAVEBUFFER); // Turn it off! - pNode->uiFlags &= ( ~LEVELNODE_UPDATESAVEBUFFERONCE ); + pNode->uiFlags &= (~LEVELNODE_UPDATESAVEBUFFERONCE); } } else { - Blt8BPPDataTo16BPPBufferTransShadowClip( (UINT16*)pDestBuf, uiDestPitchBYTES, - hVObject, - sXPos, sYPos, - usImageIndex, - &gClippingRect, - pShadeTable); + if (hVObjectAlpha != NULL) + { + Blt8BPPDataTo16BPPBufferTransShadowClipAlpha((UINT16*)pDestBuf, uiDestPitchBYTES, + hVObject, + hVObjectAlpha, + sXPos, sYPos, + usImageIndex, + &gClippingRect, + pShadeTable, + fIgnoreShadows); + } + else + { + Blt8BPPDataTo16BPPBufferTransShadowClip((UINT16*)pDestBuf, uiDestPitchBYTES, + hVObject, + sXPos, sYPos, + usImageIndex, + &gClippingRect, + pShadeTable, + fIgnoreShadows); + } } } - else if(fShadowBlitter) + else if (fShadowBlitter) { - if ( fZBlitter ) + if (fZBlitter) { - if(fZWrite) - Blt8BPPDataTo16BPPBufferShadowZClip((UINT16*)pDestBuf, uiDestPitchBYTES, gpZBuffer, sZLevel, hVObject, sXPos, sYPos, usImageIndex, &gClippingRect); - else - Blt8BPPDataTo16BPPBufferShadowZClip((UINT16*)pDestBuf, uiDestPitchBYTES, gpZBuffer, sZLevel, hVObject, sXPos, sYPos, usImageIndex, &gClippingRect); + if (fZWrite) + Blt8BPPDataTo16BPPBufferShadowZClip((UINT16*)pDestBuf, uiDestPitchBYTES, gpZBuffer, sZLevel, hVObject, sXPos, sYPos, usImageIndex, &gClippingRect); + else + Blt8BPPDataTo16BPPBufferShadowZClip((UINT16*)pDestBuf, uiDestPitchBYTES, gpZBuffer, sZLevel, hVObject, sXPos, sYPos, usImageIndex, &gClippingRect); } else { - Blt8BPPDataTo16BPPBufferShadowClip((UINT16*)pDestBuf, uiDestPitchBYTES, hVObject, sXPos, sYPos, usImageIndex, &gClippingRect); + Blt8BPPDataTo16BPPBufferShadowClip((UINT16*)pDestBuf, uiDestPitchBYTES, hVObject, sXPos, sYPos, usImageIndex, &gClippingRect); } } - else if( fIntensityBlitter) + else if (fIntensityBlitter) { - if ( fZBlitter ) + if (fZBlitter) { - if(fZWrite) - Blt8BPPDataTo16BPPBufferIntensityZClip((UINT16*)pDestBuf, uiDestPitchBYTES, gpZBuffer, sZLevel, hVObject, sXPos, sYPos, usImageIndex, &gClippingRect); - else - Blt8BPPDataTo16BPPBufferIntensityZClip((UINT16*)pDestBuf, uiDestPitchBYTES, gpZBuffer, sZLevel, hVObject, sXPos, sYPos, usImageIndex, &gClippingRect); + if (fZWrite) + Blt8BPPDataTo16BPPBufferIntensityZClip((UINT16*)pDestBuf, uiDestPitchBYTES, gpZBuffer, sZLevel, hVObject, sXPos, sYPos, usImageIndex, &gClippingRect); + else + Blt8BPPDataTo16BPPBufferIntensityZClip((UINT16*)pDestBuf, uiDestPitchBYTES, gpZBuffer, sZLevel, hVObject, sXPos, sYPos, usImageIndex, &gClippingRect); } else { Blt8BPPDataTo16BPPBufferIntensityClip((UINT16*)pDestBuf, uiDestPitchBYTES, hVObject, sXPos, sYPos, usImageIndex, &gClippingRect); } } - else if(fZBlitter) + else if (fZBlitter) { - if(fZWrite) + if (fZWrite) { - if ( fObscuredBlitter ) + if (fObscuredBlitter) { Blt8BPPDataTo16BPPBufferTransZClipPixelateObscured((UINT16*)pDestBuf, uiDestPitchBYTES, gpZBuffer, sZLevel, hVObject, sXPos, sYPos, usImageIndex, &gClippingRect); } @@ -2364,108 +2508,171 @@ void RenderTiles(UINT32 uiFlags, INT32 iStartPointX_M, INT32 iStartPointY_M, INT Blt8BPPDataTo16BPPBufferTransZNBClip((UINT16*)pDestBuf, uiDestPitchBYTES, gpZBuffer, sZLevel, hVObject, sXPos, sYPos, usImageIndex, &gClippingRect); } - if ( (uiLevelNodeFlags & LEVELNODE_UPDATESAVEBUFFERONCE ) ) + if ((uiLevelNodeFlags & LEVELNODE_UPDATESAVEBUFFERONCE)) { - pSaveBuf = LockVideoSurface(guiSAVEBUFFER, &uiSaveBufferPitchBYTES ); + pSaveBuf = LockVideoSurface(guiSAVEBUFFER, &uiSaveBufferPitchBYTES); // BLIT HERE Blt8BPPDataTo16BPPBufferTransZClip((UINT16*)pSaveBuf, uiSaveBufferPitchBYTES, gpZBuffer, sZLevel, hVObject, sXPos, sYPos, usImageIndex, &gClippingRect); UnLockVideoSurface(guiSAVEBUFFER); - - // Turn it off! - pNode->uiFlags &= ( ~LEVELNODE_UPDATESAVEBUFFERONCE ); } } else - Blt8BPPDataTo16BPPBufferTransparentClip((UINT16*)pDestBuf, uiDestPitchBYTES, hVObject, sXPos, sYPos, usImageIndex, &gClippingRect); + Blt8BPPDataTo16BPPBufferTransparentClip((UINT16*)pDestBuf, uiDestPitchBYTES, hVObject, sXPos, sYPos, usImageIndex, &gClippingRect); } - else if ( bBlitClipVal == FALSE ) + else if (bBlitClipVal == FALSE) { - if(fPixelate) + if (fPixelate) { - if(fTranslucencyType) + if (fTranslucencyType) { - if(fZWrite) + if (fZWrite) Blt8BPPDataTo16BPPBufferTransZTranslucent((UINT16*)pDestBuf, uiDestPitchBYTES, gpZBuffer, sZLevel, hVObject, sXPos, sYPos, usImageIndex); else Blt8BPPDataTo16BPPBufferTransZNBTranslucent((UINT16*)pDestBuf, uiDestPitchBYTES, gpZBuffer, sZLevel, hVObject, sXPos, sYPos, usImageIndex); } else { - if(fZWrite) + if (fZWrite) Blt8BPPDataTo16BPPBufferTransZPixelate((UINT16*)pDestBuf, uiDestPitchBYTES, gpZBuffer, sZLevel, hVObject, sXPos, sYPos, usImageIndex); else Blt8BPPDataTo16BPPBufferTransZNBPixelate((UINT16*)pDestBuf, uiDestPitchBYTES, gpZBuffer, sZLevel, hVObject, sXPos, sYPos, usImageIndex); } } - else if(fMerc) + else if (fMerc) { - if ( fZBlitter ) + if (fZBlitter) { - if ( fZWrite ) + if (fZWrite) { - Blt8BPPDataTo16BPPBufferTransShadowZ( (UINT16*)pDestBuf, uiDestPitchBYTES, gpZBuffer, sZLevel, - hVObject, - sXPos, sYPos, - usImageIndex, - pShadeTable); - } - else - { - if ( fObscuredBlitter ) + if (hVObjectAlpha != NULL) { - Blt8BPPDataTo16BPPBufferTransShadowZNBObscured( (UINT16*)pDestBuf, uiDestPitchBYTES, gpZBuffer, sZLevel, - hVObject, - sXPos, sYPos, - usImageIndex, - pShadeTable); + Blt8BPPDataTo16BPPBufferTransShadowZAlpha((UINT16*)pDestBuf, uiDestPitchBYTES, gpZBuffer, sZLevel, + hVObject, + hVObjectAlpha, + sXPos, sYPos, + usImageIndex, + pShadeTable, + fIgnoreShadows); } else { - Blt8BPPDataTo16BPPBufferTransShadowZNB( (UINT16*)pDestBuf, uiDestPitchBYTES, gpZBuffer, sZLevel, - hVObject, - sXPos, sYPos, - usImageIndex, - pShadeTable); + Blt8BPPDataTo16BPPBufferTransShadowZ((UINT16*)pDestBuf, uiDestPitchBYTES, gpZBuffer, sZLevel, + hVObject, + sXPos, sYPos, + usImageIndex, + pShadeTable, + fIgnoreShadows); + } + } + else + { + if (fObscuredBlitter) + { + if (hVObjectAlpha != NULL) { + Blt8BPPDataTo16BPPBufferTransShadowZNBObscuredAlpha((UINT16*)pDestBuf, uiDestPitchBYTES, gpZBuffer, sZLevel, + hVObject, + hVObjectAlpha, + sXPos, sYPos, + usImageIndex, + pShadeTable, + fIgnoreShadows); + } + else { + Blt8BPPDataTo16BPPBufferTransShadowZNBObscured((UINT16*)pDestBuf, uiDestPitchBYTES, gpZBuffer, sZLevel, + hVObject, + sXPos, sYPos, + usImageIndex, + pShadeTable, + fIgnoreShadows); + } + } + else + { + if (hVObjectAlpha != NULL) + { + Blt8BPPDataTo16BPPBufferTransShadowZNBAlpha((UINT16*)pDestBuf, uiDestPitchBYTES, gpZBuffer, sZLevel, + hVObject, + hVObjectAlpha, + sXPos, sYPos, + usImageIndex, + pShadeTable, + fIgnoreShadows); + } + else + { + Blt8BPPDataTo16BPPBufferTransShadowZNB((UINT16*)pDestBuf, uiDestPitchBYTES, gpZBuffer, sZLevel, + hVObject, + sXPos, sYPos, + usImageIndex, + pShadeTable, + fIgnoreShadows); + } } } - if ( (uiLevelNodeFlags & LEVELNODE_UPDATESAVEBUFFERONCE ) ) + if ((uiLevelNodeFlags & LEVELNODE_UPDATESAVEBUFFERONCE)) { - pSaveBuf = LockVideoSurface(guiSAVEBUFFER, &uiSaveBufferPitchBYTES ); + pSaveBuf = LockVideoSurface(guiSAVEBUFFER, &uiSaveBufferPitchBYTES); // BLIT HERE - Blt8BPPDataTo16BPPBufferTransShadow( (UINT16*)pSaveBuf, uiSaveBufferPitchBYTES, - hVObject, - sXPos, sYPos, - usImageIndex, - pShadeTable); + if (hVObjectAlpha != NULL) + { + Blt8BPPDataTo16BPPBufferTransShadowAlpha((UINT16*)pSaveBuf, uiSaveBufferPitchBYTES, + hVObject, + hVObjectAlpha, + sXPos, sYPos, + usImageIndex, + pShadeTable, + fIgnoreShadows); + } + else + { + Blt8BPPDataTo16BPPBufferTransShadow((UINT16*)pSaveBuf, uiSaveBufferPitchBYTES, + hVObject, + sXPos, sYPos, + usImageIndex, + pShadeTable, + fIgnoreShadows); + } UnLockVideoSurface(guiSAVEBUFFER); - // Turn it off! - pNode->uiFlags &= ( ~LEVELNODE_UPDATESAVEBUFFERONCE ); } } else { + if (hVObjectAlpha != NULL) + { + Blt8BPPDataTo16BPPBufferTransShadowAlpha((UINT16*)pDestBuf, uiDestPitchBYTES, + hVObject, + hVObjectAlpha, + sXPos, sYPos, + usImageIndex, + pShadeTable, + fIgnoreShadows); + } + else + { + Blt8BPPDataTo16BPPBufferTransShadow((UINT16*)pDestBuf, uiDestPitchBYTES, + hVObject, + sXPos, sYPos, + usImageIndex, + pShadeTable, + fIgnoreShadows); + } - Blt8BPPDataTo16BPPBufferTransShadow( (UINT16*)pDestBuf, uiDestPitchBYTES, - hVObject, - sXPos, sYPos, - usImageIndex, - pShadeTable); } } - else if(fShadowBlitter) + else if (fShadowBlitter) { - if ( fZBlitter ) + if (fZBlitter) { - if(fZWrite) + if (fZWrite) Blt8BPPDataTo16BPPBufferShadowZ((UINT16*)pDestBuf, uiDestPitchBYTES, gpZBuffer, sZLevel, hVObject, sXPos, sYPos, usImageIndex); else Blt8BPPDataTo16BPPBufferShadowZNB((UINT16*)pDestBuf, uiDestPitchBYTES, gpZBuffer, sZLevel, hVObject, sXPos, sYPos, usImageIndex); @@ -2475,11 +2682,11 @@ void RenderTiles(UINT32 uiFlags, INT32 iStartPointX_M, INT32 iStartPointY_M, INT Blt8BPPDataTo16BPPBufferShadow((UINT16*)pDestBuf, uiDestPitchBYTES, hVObject, sXPos, sYPos, usImageIndex); } } - else if( fIntensityBlitter ) + else if (fIntensityBlitter) { - if ( fZBlitter ) + if (fZBlitter) { - if(fZWrite) + if (fZWrite) Blt8BPPDataTo16BPPBufferIntensityZ((UINT16*)pDestBuf, uiDestPitchBYTES, gpZBuffer, sZLevel, hVObject, sXPos, sYPos, usImageIndex); else Blt8BPPDataTo16BPPBufferIntensityZNB((UINT16*)pDestBuf, uiDestPitchBYTES, gpZBuffer, sZLevel, hVObject, sXPos, sYPos, usImageIndex); @@ -2489,16 +2696,16 @@ void RenderTiles(UINT32 uiFlags, INT32 iStartPointX_M, INT32 iStartPointY_M, INT Blt8BPPDataTo16BPPBufferIntensity((UINT16*)pDestBuf, uiDestPitchBYTES, hVObject, sXPos, sYPos, usImageIndex); } } - else if(fZBlitter) + else if (fZBlitter) { - if(fZWrite) + if (fZWrite) { // TEST //Blt8BPPDataTo16BPPBufferTransZPixelate( (UINT16*)pDestBuf, uiDestPitchBYTES, gpZBuffer, sZLevel, hVObject, sXPos, sYPos, usImageIndex); - if ( fObscuredBlitter ) + if (fObscuredBlitter) { - Blt8BPPDataTo16BPPBufferTransZPixelateObscured( (UINT16*)pDestBuf, uiDestPitchBYTES, gpZBuffer, sZLevel, hVObject, sXPos, sYPos, usImageIndex); + Blt8BPPDataTo16BPPBufferTransZPixelateObscured((UINT16*)pDestBuf, uiDestPitchBYTES, gpZBuffer, sZLevel, hVObject, sXPos, sYPos, usImageIndex); } else { @@ -2509,118 +2716,155 @@ void RenderTiles(UINT32 uiFlags, INT32 iStartPointX_M, INT32 iStartPointY_M, INT Blt8BPPDataTo16BPPBufferTransZNB((UINT16*)pDestBuf, uiDestPitchBYTES, gpZBuffer, sZLevel, hVObject, sXPos, sYPos, usImageIndex); - if ( (uiLevelNodeFlags & LEVELNODE_UPDATESAVEBUFFERONCE ) ) + if ((uiLevelNodeFlags & LEVELNODE_UPDATESAVEBUFFERONCE)) { - pSaveBuf = LockVideoSurface(guiSAVEBUFFER, &uiSaveBufferPitchBYTES ); + pSaveBuf = LockVideoSurface(guiSAVEBUFFER, &uiSaveBufferPitchBYTES); // BLIT HERE - Blt8BPPDataTo16BPPBufferTransZ((UINT16*)pSaveBuf, uiSaveBufferPitchBYTES, gpZBuffer, sZLevel, hVObject, sXPos, sYPos, usImageIndex ); + Blt8BPPDataTo16BPPBufferTransZ((UINT16*)pSaveBuf, uiSaveBufferPitchBYTES, gpZBuffer, sZLevel, hVObject, sXPos, sYPos, usImageIndex); UnLockVideoSurface(guiSAVEBUFFER); - - // Turn it off! - pNode->uiFlags &= ( ~LEVELNODE_UPDATESAVEBUFFERONCE ); } } else - Blt8BPPDataTo16BPPBufferTransparent((UINT16*)pDestBuf, uiDestPitchBYTES, hVObject, sXPos, sYPos, usImageIndex); + Blt8BPPDataTo16BPPBufferTransparent((UINT16*)pDestBuf, uiDestPitchBYTES, hVObject, sXPos, sYPos, usImageIndex); } } } else // 8bpp section { - if(fPixelate) + if (fPixelate) { - if(fZWrite) + if (fZWrite) Blt8BPPDataTo8BPPBufferTransZClipPixelate((UINT16*)pDestBuf, uiDestPitchBYTES, gpZBuffer, sZLevel, hVObject, sXPos, sYPos, usImageIndex, &gClippingRect); else Blt8BPPDataTo8BPPBufferTransZNBClipPixelate((UINT16*)pDestBuf, uiDestPitchBYTES, gpZBuffer, sZLevel, hVObject, sXPos, sYPos, usImageIndex, &gClippingRect); } - else if(BltIsClipped(hVObject, sXPos, sYPos, usImageIndex, &gClippingRect)) + else if (BltIsClipped(hVObject, sXPos, sYPos, usImageIndex, &gClippingRect)) { - if(fMerc) + if (fMerc) { - Blt8BPPDataTo8BPPBufferTransShadowZNBClip( (UINT16*)pDestBuf, uiDestPitchBYTES, gpZBuffer, sZLevel, - hVObject, - sXPos, sYPos, - usImageIndex, - &gClippingRect, - pShadeTable); + Blt8BPPDataTo8BPPBufferTransShadowZNBClip((UINT16*)pDestBuf, uiDestPitchBYTES, gpZBuffer, sZLevel, + hVObject, + sXPos, sYPos, + usImageIndex, + &gClippingRect, + pShadeTable); } - else if(fShadowBlitter) - if(fZWrite) + else if (fShadowBlitter) + if (fZWrite) Blt8BPPDataTo8BPPBufferShadowZClip((UINT16*)pDestBuf, uiDestPitchBYTES, gpZBuffer, sZLevel, hVObject, sXPos, sYPos, usImageIndex, &gClippingRect); - else + else Blt8BPPDataTo8BPPBufferShadowZClip((UINT16*)pDestBuf, uiDestPitchBYTES, gpZBuffer, sZLevel, hVObject, sXPos, sYPos, usImageIndex, &gClippingRect); - else if(fZBlitter) + else if (fZBlitter) { - if(fZWrite) + if (fZWrite) Blt8BPPDataTo8BPPBufferTransZClip((UINT16*)pDestBuf, uiDestPitchBYTES, gpZBuffer, sZLevel, hVObject, sXPos, sYPos, usImageIndex, &gClippingRect); else Blt8BPPDataTo8BPPBufferTransZNBClip((UINT16*)pDestBuf, uiDestPitchBYTES, gpZBuffer, sZLevel, hVObject, sXPos, sYPos, usImageIndex, &gClippingRect); } else - Blt8BPPDataTo8BPPBufferTransparentClip((UINT16*)pDestBuf, uiDestPitchBYTES, hVObject, sXPos, sYPos, usImageIndex, &gClippingRect); + Blt8BPPDataTo8BPPBufferTransparentClip((UINT16*)pDestBuf, uiDestPitchBYTES, hVObject, sXPos, sYPos, usImageIndex, &gClippingRect); } else { - if(fMerc) + if (fMerc) { - Blt8BPPDataTo16BPPBufferTransShadowZNBObscured( (UINT16*)pDestBuf, uiDestPitchBYTES, gpZBuffer, sZLevel, - hVObject, - sXPos, sYPos, - usImageIndex, - pShadeTable); + // why to 16BPP here?? + if (hVObjectAlpha != NULL) + { + Blt8BPPDataTo16BPPBufferTransShadowZNBObscuredAlpha((UINT16*)pDestBuf, uiDestPitchBYTES, gpZBuffer, sZLevel, + hVObject, + hVObjectAlpha, + sXPos, sYPos, + usImageIndex, + pShadeTable, + fIgnoreShadows); + } + else + { + Blt8BPPDataTo16BPPBufferTransShadowZNBObscured((UINT16*)pDestBuf, uiDestPitchBYTES, gpZBuffer, sZLevel, + hVObject, + sXPos, sYPos, + usImageIndex, + pShadeTable, + fIgnoreShadows); + } - - // Blt8BPPDataTo8BPPBufferTransShadowZNB( (UINT16*)pDestBuf, uiDestPitchBYTES, gpZBuffer, sZLevel, - // hVObject, - // sXPos, sYPos, - // usImageIndex, - // pShadeTable); + // Blt8BPPDataTo8BPPBufferTransShadowZNB( (UINT16*)pDestBuf, uiDestPitchBYTES, gpZBuffer, sZLevel, + // hVObject, + // sXPos, sYPos, + // usImageIndex, + // pShadeTable); } - else if(fShadowBlitter) + else if (fShadowBlitter) { - if(fZWrite) + if (fZWrite) Blt8BPPDataTo8BPPBufferShadowZ((UINT16*)pDestBuf, uiDestPitchBYTES, gpZBuffer, sZLevel, hVObject, sXPos, sYPos, usImageIndex); else Blt8BPPDataTo8BPPBufferShadowZNB((UINT16*)pDestBuf, uiDestPitchBYTES, gpZBuffer, sZLevel, hVObject, sXPos, sYPos, usImageIndex); } - else if(fZBlitter) + else if (fZBlitter) { - if(fZWrite) + if (fZWrite) Blt8BPPDataTo8BPPBufferTransZ((UINT16*)pDestBuf, uiDestPitchBYTES, gpZBuffer, sZLevel, hVObject, sXPos, sYPos, usImageIndex); else Blt8BPPDataTo8BPPBufferTransZNB((UINT16*)pDestBuf, uiDestPitchBYTES, gpZBuffer, sZLevel, hVObject, sXPos, sYPos, usImageIndex); } else - Blt8BPPDataTo8BPPBufferTransparent((UINT16*)pDestBuf, uiDestPitchBYTES, hVObject, sXPos, sYPos, usImageIndex); + Blt8BPPDataTo8BPPBufferTransparent((UINT16*)pDestBuf, uiDestPitchBYTES, hVObject, sXPos, sYPos, usImageIndex); } } } - // RENDR APS ONTOP OF PLANNED MERC GUY - if ( fRenderTile && !( uiFlags&TILES_DIRTY ) ) + + if (bt == NULL) { - if ( fMerc ) + break; // no logical body type found, no layers to render + } + layerIter++; + } + // background rect registration. Have to do this here, can't do it in the loop + // as we don't know what the last rendered layer is upfront + if (uiFlags & TILES_DIRTY) + { + sXPos = (INT16)backRect.left; + sYPos = (INT16)backRect.top; + RegisterBackgroundRect(uiDirtyFlags, NULL, sXPos, sYPos, (INT16)backRect.right, (INT16)(__min((INT16)(backRect.bottom), gsVIEWPORT_WINDOW_END_Y))); + if (fSaveZ) { - if ( pSoldier != NULL && pSoldier->ubID >= MAX_NUM_SOLDIERS ) + RegisterBackgroundRect(uiDirtyFlags | BGND_FLAG_SAVE_Z, NULL, sXPos, sYPos, (INT16)backRect.right, (INT16)(__min((INT16)(backRect.bottom), gsVIEWPORT_WINDOW_END_Y))); + } + } + // unset save buffer once flag after all layers have been rendered } + if ((uiLevelNodeFlags & LEVELNODE_UPDATESAVEBUFFERONCE)) + { + pNode->uiFlags &= (~LEVELNODE_UPDATESAVEBUFFERONCE); + } + + + // RENDER APS ONTOP OF PLANNED MERC GUY + if (fRenderTile && !(uiFlags&TILES_DIRTY)) + { + if (fMerc) + { + if (pSoldier != NULL && pSoldier->ubID >= MAX_NUM_SOLDIERS) { - SetFont( TINYFONT1 ); - SetFontDestBuffer( guiSAVEBUFFER , 0, gsVIEWPORT_WINDOW_START_Y, SCREEN_WIDTH, gsVIEWPORT_WINDOW_END_Y, FALSE ); - VarFindFontCenterCoordinates( sXPos, sYPos, 1, 1, TINYFONT1, &sX, &sY, L"%d", pSoldier->ubPlannedUIAPCost ); - mprintf_buffer( pDestBuf, uiDestPitchBYTES, TINYFONT1, sX, sY , L"%d", pSoldier->ubPlannedUIAPCost ); - SetFontDestBuffer( FRAME_BUFFER , 0, 0, SCREEN_WIDTH, SCREEN_HEIGHT, FALSE ); + SetFont(TINYFONT1); + SetFontDestBuffer(guiSAVEBUFFER, 0, gsVIEWPORT_WINDOW_START_Y, SCREEN_WIDTH, gsVIEWPORT_WINDOW_END_Y, FALSE); + VarFindFontCenterCoordinates(sXPos, sYPos, 1, 1, TINYFONT1, &sX, &sY, L"%d", pSoldier->ubPlannedUIAPCost); + mprintf_buffer(pDestBuf, uiDestPitchBYTES, TINYFONT1, sX, sY, L"%d", pSoldier->ubPlannedUIAPCost); + SetFontDestBuffer(FRAME_BUFFER, 0, 0, SCREEN_WIDTH, SCREEN_HEIGHT, FALSE); } } } } - if(!fLinkedListDirection) + if (!fLinkedListDirection) pNode = pNode->pPrevNode; else pNode = pNode->pNext; @@ -2630,7 +2874,7 @@ void RenderTiles(UINT32 uiFlags, INT32 iStartPointX_M, INT32 iStartPointY_M, INT } else { - if( gfEditMode ) + if (gfEditMode) { //ATE: Used here in the editor to denote then an area is not in the world @@ -2643,64 +2887,63 @@ void RenderTiles(UINT32 uiFlags, INT32 iStartPointX_M, INT32 iStartPointY_M, INT // only crash on my computer and not Emmons, so this should work. Also, I changed the color // from fluorescent green to black, which is easier on the eyes, and prevent the drawing of the // end of the world if it would be drawn on the editor's taskbar. - if( iTempPosY_S < INTERFACE_START_Y ) + if (iTempPosY_S < INTERFACE_START_Y) { - if(!(uiFlags&TILES_DIRTY)) - UnLockVideoSurface( FRAME_BUFFER ); - ColorFillVideoSurfaceArea( FRAME_BUFFER, iTempPosX_S, iTempPosY_S, (iTempPosX_S + 40), - ( min( iTempPosY_S + 20, INTERFACE_START_Y )), Get16BPPColor( FROMRGB( 0, 0, 0 ) ) ); - if(!(uiFlags&TILES_DIRTY)) - pDestBuf = LockVideoSurface( FRAME_BUFFER, &uiDestPitchBYTES ); + if (!(uiFlags&TILES_DIRTY)) + UnLockVideoSurface(FRAME_BUFFER); + ColorFillVideoSurfaceArea(FRAME_BUFFER, iTempPosX_S, iTempPosY_S, (iTempPosX_S + 40), + (min(iTempPosY_S + 20, INTERFACE_START_Y)), Get16BPPColor(FROMRGB(0, 0, 0))); + if (!(uiFlags&TILES_DIRTY)) + pDestBuf = LockVideoSurface(FRAME_BUFFER, &uiDestPitchBYTES); } } } iTempPosX_S += 40; - iTempPosX_M ++; - iTempPosY_M --; + iTempPosX_M++; + iTempPosY_M--; - if ( iTempPosX_S >= iEndXS ) + if (iTempPosX_S >= iEndXS) { fEndRenderRow = TRUE; } - } while( !fEndRenderRow ); + } while (!fEndRenderRow); } } // } while( FALSE ); - if ( bXOddFlag > 0 ) + if (bXOddFlag > 0) { - iAnchorPosY_M ++; + iAnchorPosY_M++; } else { - iAnchorPosX_M ++; + iAnchorPosX_M++; } bXOddFlag = !bXOddFlag; iAnchorPosY_S += 10; - if ( iAnchorPosY_S >= iEndYS ) + if (iAnchorPosY_S >= iEndYS) { fEndRenderCol = TRUE; } } - while( !fEndRenderCol ); + while (!fEndRenderCol); - if(!(uiFlags&TILES_DIRTY)) - UnLockVideoSurface( FRAME_BUFFER ); + if (!(uiFlags&TILES_DIRTY)) + UnLockVideoSurface(FRAME_BUFFER); - if ( uiFlags & TILES_DYNAMIC_CHECKFOR_INT_TILE ) + if (uiFlags & TILES_DYNAMIC_CHECKFOR_INT_TILE) { - EndCurInteractiveTileCheck( ); + EndCurInteractiveTileCheck(); } } -/// kONIE Renderowania klastra void DeleteFromWorld( UINT16 usTileIndex, UINT32 uiRenderTiles, UINT16 usIndex ) @@ -3002,7 +3245,7 @@ void RenderStaticWorldRect(INT16 sLeft, INT16 sTop, INT16 sRight, INT16 sBottom, uiLevelFlags[0] = TILES_STATIC_LAND; sLevelIDs [0] = RENDER_STATIC_LAND; RenderTiles( 0 , gsLStartPointX_M, gsLStartPointY_M, gsLStartPointX_S, gsLStartPointY_S, gsLEndXS, gsLEndYS, 1, uiLevelFlags, sLevelIDs ); - + //rendering objects uiLevelFlags[0] = TILES_STATIC_OBJECTS; sLevelIDs [0] = RENDER_STATIC_OBJECTS; @@ -5682,7 +5925,7 @@ BlitDone: // 3 ) clipped // 4 ) trans shadow - if value is 254, makes a shadow // -BOOLEAN Blt8BPPDataTo16BPPBufferTransZTransShadowIncObscureClip( UINT16 *pBuffer, UINT32 uiDestPitchBYTES, UINT16 *pZBuffer, UINT16 usZValue, HVOBJECT hSrcVObject, INT32 iX, INT32 iY, UINT16 usIndex, SGPRect *clipregion, INT16 sZIndex, UINT16 *p16BPPPalette ) +BOOLEAN Blt8BPPDataTo16BPPBufferTransZTransShadowIncObscureClip(UINT16 *pBuffer, UINT32 uiDestPitchBYTES, UINT16 *pZBuffer, UINT16 usZValue, HVOBJECT hSrcVObject, INT32 iX, INT32 iY, UINT16 usIndex, SGPRect *clipregion, INT16 sZIndex, UINT16 *p16BPPPalette, BOOLEAN fIgnoreShadows) { UINT32 uiOffset, uiLineFlag; UINT32 usHeight, usWidth, Unblitted; @@ -5953,6 +6196,10 @@ BlitPixel1: cmp al, 254 jne BlitNTL66 + mov al, fIgnoreShadows + cmp al, 0 + jne BlitNTL2 + mov ax, [edi] mov ax, ShadeTable[eax*2] mov [edi], ax @@ -6102,6 +6349,517 @@ BlitDone: } +// Blitter Specs +// 1 ) 8 to 16 bpp +// 2 ) strip z-blitter +// 3 ) clipped +// 4 ) trans shadow - if value is 254, makes a shadow +// +BOOLEAN Blt8BPPDataTo16BPPBufferTransZTransShadowIncObscureClipAlpha(UINT16 *pBuffer, UINT32 uiDestPitchBYTES, UINT16 *pZBuffer, UINT16 usZValue, HVOBJECT hSrcVObject, HVOBJECT hAlphaVObject, INT32 iX, INT32 iY, UINT16 usIndex, SGPRect *clipregion, INT16 sZIndex, UINT16 *p16BPPPalette, BOOLEAN fIgnoreShadows) +{ + UINT32 uiOffset, uiLineFlag; + UINT32 usHeight, usWidth, Unblitted; + UINT8 *SrcPtr, *DestPtr, *ZPtr, *AlphaPtr; + UINT32 LineSkip; + ETRLEObject *pTrav; + INT32 iTempX, iTempY, LeftSkip, RightSkip, TopSkip, BottomSkip, BlitLength, BlitHeight, LSCount; + INT32 ClipX1, ClipY1, ClipX2, ClipY2; + UINT16 usZLevel, usZStartLevel, usZColsToGo, usZStartIndex, usCount, usZIndex, usZStartCols; + INT8 *pZArray; + ZStripInfo *pZInfo; + + // Assertions + Assert(hSrcVObject != NULL); + Assert(hAlphaVObject != NULL); + Assert(pBuffer != NULL); + + // Get Offsets from Index into structure + pTrav = &(hSrcVObject->pETRLEObject[usIndex]); + usHeight = (UINT32)pTrav->usHeight; + usWidth = (UINT32)pTrav->usWidth; + uiOffset = pTrav->uiDataOffset; + + // Add to start position of dest buffer + iTempX = iX + pTrav->sOffsetX; + iTempY = iY + pTrav->sOffsetY; + + if (clipregion == NULL) + { + ClipX1 = ClippingRect.iLeft; + ClipY1 = ClippingRect.iTop; + ClipX2 = ClippingRect.iRight; + ClipY2 = ClippingRect.iBottom; + } + else + { + ClipX1 = clipregion->iLeft; + ClipY1 = clipregion->iTop; + ClipX2 = clipregion->iRight; + ClipY2 = clipregion->iBottom; + } + + // Calculate rows hanging off each side of the screen + LeftSkip = __min(ClipX1 - min(ClipX1, iTempX), (INT32)usWidth); + RightSkip = __min(max(ClipX2, (iTempX + (INT32)usWidth)) - ClipX2, (INT32)usWidth); + TopSkip = __min(ClipY1 - __min(ClipY1, iTempY), (INT32)usHeight); + BottomSkip = __min(__max(ClipY2, (iTempY + (INT32)usHeight)) - ClipY2, (INT32)usHeight); + + uiLineFlag = (iTempY & 1); + + // calculate the remaining rows and columns to blit + BlitLength = ((INT32)usWidth - LeftSkip - RightSkip); + BlitHeight = ((INT32)usHeight - TopSkip - BottomSkip); + + // check if whole thing is clipped + if ((LeftSkip >= (INT32)usWidth) || (RightSkip >= (INT32)usWidth)) + return(TRUE); + + // check if whole thing is clipped + if ((TopSkip >= (INT32)usHeight) || (BottomSkip >= (INT32)usHeight)) + return(TRUE); + + SrcPtr = (UINT8 *)hSrcVObject->pPixData + uiOffset; + AlphaPtr = (UINT8 *)hAlphaVObject->pPixData + (hAlphaVObject->pETRLEObject[usIndex]).uiDataOffset; + DestPtr = (UINT8 *)pBuffer + (uiDestPitchBYTES*(iTempY + TopSkip)) + ((iTempX + LeftSkip) * 2); + ZPtr = (UINT8 *)pZBuffer + (uiDestPitchBYTES*(iTempY + TopSkip)) + ((iTempX + LeftSkip) * 2); + LineSkip = (uiDestPitchBYTES - (BlitLength * 2)); + + if (hSrcVObject->ppZStripInfo == NULL) + { + DebugMsg(TOPIC_VIDEOOBJECT, DBG_LEVEL_0, String("Missing Z-Strip info on multi-Z object")); + return(FALSE); + } + // setup for the z-column blitting stuff + pZInfo = hSrcVObject->ppZStripInfo[sZIndex]; + if (pZInfo == NULL) + { + DebugMsg(TOPIC_VIDEOOBJECT, DBG_LEVEL_0, String("Missing Z-Strip info on multi-Z object")); + return(FALSE); + } + + usZStartLevel = (UINT16)((INT16)usZValue + ((INT16)pZInfo->bInitialZChange*Z_SUBLAYERS * 10)); + + if (LeftSkip > pZInfo->ubFirstZStripWidth) + { + usZStartCols = (LeftSkip - pZInfo->ubFirstZStripWidth); + usZStartCols = 20 - (usZStartCols % 20); + } + else if (LeftSkip < pZInfo->ubFirstZStripWidth) + usZStartCols = (UINT16)(pZInfo->ubFirstZStripWidth - LeftSkip); + else + usZStartCols = 20; + + // set to odd number of pixels for first column + usZColsToGo = usZStartCols; + + pZArray = pZInfo->pbZChange; + + if (LeftSkip >= usZColsToGo) + { + // Index into array after doing left clipping + usZStartIndex = 1 + ((LeftSkip - pZInfo->ubFirstZStripWidth) / 20); + + //calculates the Z-value after left-side clipping + if (usZStartIndex) + { + for (usCount = 0; usCount < usZStartIndex; usCount++) + { + switch (pZArray[usCount]) + { + case -1: usZStartLevel -= Z_SUBLAYERS; + break; + case 0: //no change + break; + case 1: usZStartLevel += Z_SUBLAYERS; + break; + } + } + } + } + else + usZStartIndex = 0; + + usZLevel = usZStartLevel; + usZIndex = usZStartIndex; + + __asm { + + mov esi, SrcPtr + mov edi, DestPtr + mov edx, p16BPPPalette + xor eax, eax + mov ebx, ZPtr + xor ecx, ecx + + cmp TopSkip, 0 // check for nothing clipped on top + je LeftSkipSetup + + + // Skips the number of lines clipped at the top + TopSkipLoop : + + mov cl, [esi] + inc esi + + push esi + mov esi, AlphaPtr + inc esi + mov AlphaPtr, esi + pop esi + + or cl, cl + js TopSkipLoop + jz TSEndLine + + add esi, ecx + + push esi + mov esi, AlphaPtr + add esi, ecx + mov AlphaPtr, esi + pop esi + + jmp TopSkipLoop + + TSEndLine : + + xor uiLineFlag, 1 + dec TopSkip + jnz TopSkipLoop + + + // Start of line loop + + // Skips the pixels hanging outside the left-side boundry + LeftSkipSetup: + + mov Unblitted, 0 // Unblitted counts any pixels left from a run + mov eax, LeftSkip // after we have skipped enough left-side pixels + mov LSCount, eax // LSCount counts how many pixels skipped so far + or eax, eax + jz BlitLineSetup // check for nothing to skip + + LeftSkipLoop : + + mov cl, [esi] + inc esi + + push esi + mov esi, AlphaPtr + inc esi + mov AlphaPtr, esi + pop esi + + or cl, cl + js LSTrans + + cmp ecx, LSCount + je LSSkip2 // if equal, skip whole, and start blit with new run + jb LSSkip1 // if less, skip whole thing + + add esi, LSCount // skip partial run, jump into normal loop for rest + + push esi + mov esi, AlphaPtr + add esi, LSCount + mov AlphaPtr, esi + pop esi + + sub ecx, LSCount + mov eax, BlitLength + mov LSCount, eax + mov Unblitted, 0 + jmp BlitNTL1 // *** jumps into non-transparent blit loop + + LSSkip2 : + add esi, ecx // skip whole run, and start blit with new run + + push esi + mov esi, AlphaPtr + add esi, ecx + mov AlphaPtr, esi + pop esi + + jmp BlitLineSetup + + + LSSkip1 : + add esi, ecx // skip whole run, continue skipping + + push esi + mov esi, AlphaPtr + add esi, ecx + mov AlphaPtr, esi + pop esi + + sub LSCount, ecx + jmp LeftSkipLoop + + + LSTrans : + and ecx, 07fH + cmp ecx, LSCount + je BlitLineSetup // if equal, skip whole, and start blit with new run + jb LSTrans1 // if less, skip whole thing + + sub ecx, LSCount // skip partial run, jump into normal loop for rest + mov eax, BlitLength + mov LSCount, eax + + mov Unblitted, 0 + jmp BlitTransparent // *** jumps into transparent blit loop + + + LSTrans1 : + sub LSCount, ecx // skip whole run, continue skipping + jmp LeftSkipLoop + + //------------------------------------------------- + // setup for beginning of line + + BlitLineSetup : + mov eax, BlitLength + mov LSCount, eax + mov Unblitted, 0 + + BlitDispatch : + + cmp LSCount, 0 // Check to see if we're done blitting + je RightSkipLoop + + mov cl, [esi] + inc esi + + push esi + mov esi, AlphaPtr + inc esi + mov AlphaPtr, esi + pop esi + + or cl, cl + js BlitTransparent + jz RSLoop2 + + //-------------------------------- + // blitting non-transparent pixels + + and ecx, 07fH + + BlitNTL1 : + mov ax, [ebx] // check z-level of pixel + cmp ax, usZLevel + jae BlitPixellate1 + jmp BlitPixel1 + + BlitPixellate1 : + + // OK, DO PIXELLATE SCHEME HERE! + test uiLineFlag, 1 + jz BlitSkip1 + + test edi, 2 + jz BlitNTL2 + jmp BlitPixel1 + + BlitSkip1 : + test edi, 2 + jnz BlitNTL2 + + BlitPixel1 : + + mov ax, usZLevel // update z-level of pixel + mov[ebx], ax + + // Check for shadow... + xor eax, eax + mov al, [esi] + cmp al, 254 + jne BlitNTL66 + + mov al, fIgnoreShadows + cmp al, 0 + jne BlitNTL2 + + mov ax, [edi] + mov ax, ShadeTable[eax * 2] + mov[edi], ax + jmp BlitNTL2 + + BlitNTL66 : + + mov ax, [edx + eax * 2] // Copy pixel + + push edx + push ecx + push ebx + push esi + mov esi, AlphaPtr + xor ebx, ebx + mov bl, [esi] + pop esi + push ebx + push[edi] + push eax + call blendWithAlpha + add esp, 12 + pop ebx + pop ecx + pop edx + + mov[edi], ax + + BlitNTL2 : + inc esi + + push esi + mov esi, AlphaPtr + inc esi + mov AlphaPtr, esi + pop esi + + add edi, 2 + add ebx, 2 + + dec usZColsToGo + jnz BlitNTL6 + + // update the z-level according to the z-table + + push edx + mov edx, pZArray // get pointer to array + xor eax, eax + mov ax, usZIndex // pick up the current array index + add edx, eax + inc eax // increment it + mov usZIndex, ax // store incremented value + + mov al, [edx] // get direction instruction + mov dx, usZLevel // get current z-level + + or al, al + jz BlitNTL5 // dir = 0 no change + js BlitNTL4 // dir < 0 z-level down + // dir > 0 z-level up (default) + add dx, Z_SUBLAYERS + jmp BlitNTL5 + + BlitNTL4 : + sub dx, Z_SUBLAYERS + + BlitNTL5 : + mov usZLevel, dx // store the now-modified z-level + mov usZColsToGo, 20 // reset the next z-level change to 20 cols + pop edx + + BlitNTL6 : + dec LSCount // decrement pixel length to blit + jz RightSkipLoop // done blitting the visible line + + dec ecx + jnz BlitNTL1 // continue current run + + jmp BlitDispatch // done current run, go for another + + + //---------------------------- + // skipping transparent pixels + + BlitTransparent: // skip transparent pixels + + and ecx, 07fH + + BlitTrans2 : + + add edi, 2 // move up the destination pointer + add ebx, 2 + + dec usZColsToGo + jnz BlitTrans1 + + // update the z-level according to the z-table + + push edx + mov edx, pZArray // get pointer to array + xor eax, eax + mov ax, usZIndex // pick up the current array index + add edx, eax + inc eax // increment it + mov usZIndex, ax // store incremented value + + mov al, [edx] // get direction instruction + mov dx, usZLevel // get current z-level + + or al, al + jz BlitTrans5 // dir = 0 no change + js BlitTrans4 // dir < 0 z-level down + // dir > 0 z-level up (default) + add dx, Z_SUBLAYERS + jmp BlitTrans5 + + BlitTrans4 : + sub dx, Z_SUBLAYERS + + BlitTrans5 : + mov usZLevel, dx // store the now-modified z-level + mov usZColsToGo, 20 // reset the next z-level change to 20 cols + pop edx + + BlitTrans1 : + + dec LSCount // decrement the pixels to blit + jz RightSkipLoop // done the line + + dec ecx + jnz BlitTrans2 + + jmp BlitDispatch + + //--------------------------------------------- + // Scans the ETRLE until it finds an EOL marker + + RightSkipLoop : + + + RSLoop1: + mov al, [esi] + inc esi + + push esi + mov esi, AlphaPtr + inc esi + mov AlphaPtr, esi + pop esi + + or al, al + jnz RSLoop1 + + RSLoop2 : + + xor uiLineFlag, 1 + dec BlitHeight + jz BlitDone + add edi, LineSkip + add ebx, LineSkip + + // reset all the z-level stuff for a new line + + mov ax, usZStartLevel + mov usZLevel, ax + mov ax, usZStartIndex + mov usZIndex, ax + mov ax, usZStartCols + mov usZColsToGo, ax + + + jmp LeftSkipSetup + + + BlitDone : + } + + return(TRUE); +} + void CorrectRenderCenter( INT16 sRenderX, INT16 sRenderY, INT16 *pSNewX, INT16 *pSNewY ) @@ -6146,7 +6904,7 @@ void CorrectRenderCenter( INT16 sRenderX, INT16 sRenderY, INT16 *pSNewX, INT16 * // 3 ) clipped // 4 ) trans shadow - if value is 254, makes a shadow // -BOOLEAN Blt8BPPDataTo16BPPBufferTransZTransShadowIncClip( UINT16 *pBuffer, UINT32 uiDestPitchBYTES, UINT16 *pZBuffer, UINT16 usZValue, HVOBJECT hSrcVObject, INT32 iX, INT32 iY, UINT16 usIndex, SGPRect *clipregion, INT16 sZIndex, UINT16 *p16BPPPalette ) +BOOLEAN Blt8BPPDataTo16BPPBufferTransZTransShadowIncClip(UINT16 *pBuffer, UINT32 uiDestPitchBYTES, UINT16 *pZBuffer, UINT16 usZValue, HVOBJECT hSrcVObject, INT32 iX, INT32 iY, UINT16 usIndex, SGPRect *clipregion, INT16 sZIndex, UINT16 *p16BPPPalette, BOOLEAN fIgnoreShadows) { UINT32 uiOffset; UINT32 usHeight, usWidth, Unblitted; @@ -6396,6 +7154,10 @@ BlitNTL1: cmp al, 254 jne BlitNTL66 + mov al, fIgnoreShadows + cmp al, 0 + jne BlitNTL2 + mov ax, [edi] mov ax, ShadeTable[eax*2] mov [edi], ax @@ -6544,6 +7306,495 @@ BlitDone: } +// Blitter Specs +// 1 ) 8 to 16 bpp +// 2 ) strip z-blitter +// 3 ) clipped +// 4 ) trans shadow - if value is 254, makes a shadow +// +BOOLEAN Blt8BPPDataTo16BPPBufferTransZTransShadowIncClipAlpha(UINT16 *pBuffer, UINT32 uiDestPitchBYTES, UINT16 *pZBuffer, UINT16 usZValue, HVOBJECT hSrcVObject, HVOBJECT hAlphaVObject, INT32 iX, INT32 iY, UINT16 usIndex, SGPRect *clipregion, INT16 sZIndex, UINT16 *p16BPPPalette, BOOLEAN fIgnoreShadows) +{ + UINT32 uiOffset; + UINT32 usHeight, usWidth, Unblitted; + UINT8 *SrcPtr, *DestPtr, *ZPtr, *AlphaPtr; + UINT32 LineSkip; + ETRLEObject *pTrav; + INT32 iTempX, iTempY, LeftSkip, RightSkip, TopSkip, BottomSkip, BlitLength, BlitHeight, LSCount; + INT32 ClipX1, ClipY1, ClipX2, ClipY2; + UINT16 usZLevel, usZStartLevel, usZColsToGo, usZStartIndex, usCount, usZIndex, usZStartCols; + INT8 *pZArray; + ZStripInfo *pZInfo; + + // Assertions + Assert(hSrcVObject != NULL); + Assert(hAlphaVObject != NULL); + Assert(pBuffer != NULL); + + // Get Offsets from Index into structure + pTrav = &(hSrcVObject->pETRLEObject[usIndex]); + usHeight = (UINT32)pTrav->usHeight; + usWidth = (UINT32)pTrav->usWidth; + uiOffset = pTrav->uiDataOffset; + + // Add to start position of dest buffer + iTempX = iX + pTrav->sOffsetX; + iTempY = iY + pTrav->sOffsetY; + + if (clipregion == NULL) + { + ClipX1 = ClippingRect.iLeft; + ClipY1 = ClippingRect.iTop; + ClipX2 = ClippingRect.iRight; + ClipY2 = ClippingRect.iBottom; + } + else + { + ClipX1 = clipregion->iLeft; + ClipY1 = clipregion->iTop; + ClipX2 = clipregion->iRight; + ClipY2 = clipregion->iBottom; + } + + // Calculate rows hanging off each side of the screen + LeftSkip = __min(ClipX1 - min(ClipX1, iTempX), (INT32)usWidth); + RightSkip = __min(max(ClipX2, (iTempX + (INT32)usWidth)) - ClipX2, (INT32)usWidth); + TopSkip = __min(ClipY1 - __min(ClipY1, iTempY), (INT32)usHeight); + BottomSkip = __min(__max(ClipY2, (iTempY + (INT32)usHeight)) - ClipY2, (INT32)usHeight); + + // calculate the remaining rows and columns to blit + BlitLength = ((INT32)usWidth - LeftSkip - RightSkip); + BlitHeight = ((INT32)usHeight - TopSkip - BottomSkip); + + // check if whole thing is clipped + if ((LeftSkip >= (INT32)usWidth) || (RightSkip >= (INT32)usWidth)) + return(TRUE); + + // check if whole thing is clipped + if ((TopSkip >= (INT32)usHeight) || (BottomSkip >= (INT32)usHeight)) + return(TRUE); + + SrcPtr = (UINT8 *)hSrcVObject->pPixData + uiOffset; + AlphaPtr = (UINT8 *)hAlphaVObject->pPixData + (hAlphaVObject->pETRLEObject[usIndex]).uiDataOffset; + DestPtr = (UINT8 *)pBuffer + (uiDestPitchBYTES*(iTempY + TopSkip)) + ((iTempX + LeftSkip) * 2); + ZPtr = (UINT8 *)pZBuffer + (uiDestPitchBYTES*(iTempY + TopSkip)) + ((iTempX + LeftSkip) * 2); + LineSkip = (uiDestPitchBYTES - (BlitLength * 2)); + + if (hSrcVObject->ppZStripInfo == NULL) + { + DebugMsg(TOPIC_VIDEOOBJECT, DBG_LEVEL_0, String("Missing Z-Strip info on multi-Z object")); + return(FALSE); + } + // setup for the z-column blitting stuff + pZInfo = hSrcVObject->ppZStripInfo[sZIndex]; + if (pZInfo == NULL) + { + DebugMsg(TOPIC_VIDEOOBJECT, DBG_LEVEL_0, String("Missing Z-Strip info on multi-Z object")); + return(FALSE); + } + + usZStartLevel = (UINT16)((INT16)usZValue + ((INT16)pZInfo->bInitialZChange*Z_SUBLAYERS * 10)); + + if (LeftSkip > pZInfo->ubFirstZStripWidth) + { + usZStartCols = (LeftSkip - pZInfo->ubFirstZStripWidth); + usZStartCols = 20 - (usZStartCols % 20); + } + else if (LeftSkip < pZInfo->ubFirstZStripWidth) + usZStartCols = (UINT16)(pZInfo->ubFirstZStripWidth - LeftSkip); + else + usZStartCols = 20; + + // set to odd number of pixels for first column + usZColsToGo = usZStartCols; + + pZArray = pZInfo->pbZChange; + + if (LeftSkip >= usZColsToGo) + { + // Index into array after doing left clipping + usZStartIndex = 1 + ((LeftSkip - pZInfo->ubFirstZStripWidth) / 20); + + //calculates the Z-value after left-side clipping + if (usZStartIndex) + { + for (usCount = 0; usCount < usZStartIndex; usCount++) + { + switch (pZArray[usCount]) + { + case -1: usZStartLevel -= Z_SUBLAYERS; + break; + case 0: //no change + break; + case 1: usZStartLevel += Z_SUBLAYERS; + break; + } + } + } + } + else + usZStartIndex = 0; + + usZLevel = usZStartLevel; + usZIndex = usZStartIndex; + + __asm { + + mov esi, SrcPtr + mov edi, DestPtr + mov edx, p16BPPPalette + xor eax, eax + mov ebx, ZPtr + xor ecx, ecx + + cmp TopSkip, 0 // check for nothing clipped on top + je LeftSkipSetup + + + // Skips the number of lines clipped at the top + TopSkipLoop : + + mov cl, [esi] + inc esi + + push esi + mov esi, AlphaPtr + inc esi + mov AlphaPtr, esi + pop esi + + or cl, cl + js TopSkipLoop + jz TSEndLine + + add esi, ecx + + push esi + mov esi, AlphaPtr + add esi, ecx + mov AlphaPtr, esi + pop esi + + jmp TopSkipLoop + + TSEndLine : + dec TopSkip + jnz TopSkipLoop + + + // Start of line loop + + // Skips the pixels hanging outside the left-side boundry + LeftSkipSetup: + + mov Unblitted, 0 // Unblitted counts any pixels left from a run + mov eax, LeftSkip // after we have skipped enough left-side pixels + mov LSCount, eax // LSCount counts how many pixels skipped so far + or eax, eax + jz BlitLineSetup // check for nothing to skip + + LeftSkipLoop : + + mov cl, [esi] + inc esi + + push esi + mov esi, AlphaPtr + inc esi + mov AlphaPtr, esi + pop esi + + or cl, cl + js LSTrans + + cmp ecx, LSCount + je LSSkip2 // if equal, skip whole, and start blit with new run + jb LSSkip1 // if less, skip whole thing + + add esi, LSCount // skip partial run, jump into normal loop for rest + + push esi + mov esi, AlphaPtr + add esi, LSCount + mov AlphaPtr, esi + pop esi + + sub ecx, LSCount + mov eax, BlitLength + mov LSCount, eax + mov Unblitted, 0 + jmp BlitNTL1 // *** jumps into non-transparent blit loop + + LSSkip2 : + add esi, ecx // skip whole run, and start blit with new run + + push esi + mov esi, AlphaPtr + add esi, ecx + mov AlphaPtr, esi + pop esi + + jmp BlitLineSetup + + + LSSkip1 : + add esi, ecx // skip whole run, continue skipping + + push esi + mov esi, AlphaPtr + add esi, ecx + mov AlphaPtr, esi + pop esi + + sub LSCount, ecx + jmp LeftSkipLoop + + + LSTrans : + and ecx, 07fH + cmp ecx, LSCount + je BlitLineSetup // if equal, skip whole, and start blit with new run + jb LSTrans1 // if less, skip whole thing + + sub ecx, LSCount // skip partial run, jump into normal loop for rest + mov eax, BlitLength + mov LSCount, eax + + mov Unblitted, 0 + jmp BlitTransparent // *** jumps into transparent blit loop + + + LSTrans1 : + sub LSCount, ecx // skip whole run, continue skipping + jmp LeftSkipLoop + + //------------------------------------------------- + // setup for beginning of line + + BlitLineSetup : + mov eax, BlitLength + mov LSCount, eax + mov Unblitted, 0 + + BlitDispatch : + + cmp LSCount, 0 // Check to see if we're done blitting + je RightSkipLoop + + mov cl, [esi] + inc esi + + push esi + mov esi, AlphaPtr + inc esi + mov AlphaPtr, esi + pop esi + + or cl, cl + js BlitTransparent + jz RSLoop2 + + //-------------------------------- + // blitting non-transparent pixels + + and ecx, 07fH + + BlitNTL1 : + mov ax, [ebx] // check z-level of pixel + cmp ax, usZLevel + ja BlitNTL2 + + mov ax, usZLevel // update z-level of pixel + mov[ebx], ax + + // Check for shadow... + xor eax, eax + mov al, [esi] + cmp al, 254 + jne BlitNTL66 + + mov al, fIgnoreShadows + cmp al, 0 + jne BlitNTL2 + + mov ax, [edi] + mov ax, ShadeTable[eax * 2] + mov[edi], ax + jmp BlitNTL2 + + BlitNTL66 : + + mov ax, [edx + eax * 2] // Copy pixel + + push edx + push ecx + push ebx + push esi + mov esi, AlphaPtr + xor ebx, ebx + mov bl, [esi] + pop esi + push ebx + push[edi] + push eax + call blendWithAlpha + add esp, 12 + pop ebx + pop ecx + pop edx + + mov[edi], ax + + BlitNTL2 : + inc esi + + push esi + mov esi, AlphaPtr + inc esi + mov AlphaPtr, esi + pop esi + + add edi, 2 + add ebx, 2 + + dec usZColsToGo + jnz BlitNTL6 + + // update the z-level according to the z-table + + push edx + mov edx, pZArray // get pointer to array + xor eax, eax + mov ax, usZIndex // pick up the current array index + add edx, eax + inc eax // increment it + mov usZIndex, ax // store incremented value + + mov al, [edx] // get direction instruction + mov dx, usZLevel // get current z-level + + or al, al + jz BlitNTL5 // dir = 0 no change + js BlitNTL4 // dir < 0 z-level down + // dir > 0 z-level up (default) + add dx, Z_SUBLAYERS + jmp BlitNTL5 + + BlitNTL4 : + sub dx, Z_SUBLAYERS + + BlitNTL5 : + mov usZLevel, dx // store the now-modified z-level + mov usZColsToGo, 20 // reset the next z-level change to 20 cols + pop edx + + BlitNTL6 : + dec LSCount // decrement pixel length to blit + jz RightSkipLoop // done blitting the visible line + + dec ecx + jnz BlitNTL1 // continue current run + + jmp BlitDispatch // done current run, go for another + + + //---------------------------- + // skipping transparent pixels + + BlitTransparent: // skip transparent pixels + + and ecx, 07fH + + BlitTrans2 : + + add edi, 2 // move up the destination pointer + add ebx, 2 + + dec usZColsToGo + jnz BlitTrans1 + + // update the z-level according to the z-table + + push edx + mov edx, pZArray // get pointer to array + xor eax, eax + mov ax, usZIndex // pick up the current array index + add edx, eax + inc eax // increment it + mov usZIndex, ax // store incremented value + + mov al, [edx] // get direction instruction + mov dx, usZLevel // get current z-level + + or al, al + jz BlitTrans5 // dir = 0 no change + js BlitTrans4 // dir < 0 z-level down + // dir > 0 z-level up (default) + add dx, Z_SUBLAYERS + jmp BlitTrans5 + + BlitTrans4 : + sub dx, Z_SUBLAYERS + + BlitTrans5 : + mov usZLevel, dx // store the now-modified z-level + mov usZColsToGo, 20 // reset the next z-level change to 20 cols + pop edx + + BlitTrans1 : + + dec LSCount // decrement the pixels to blit + jz RightSkipLoop // done the line + + dec ecx + jnz BlitTrans2 + + jmp BlitDispatch + + //--------------------------------------------- + // Scans the ETRLE until it finds an EOL marker + + RightSkipLoop : + + + RSLoop1: + mov al, [esi] + inc esi + + push esi + mov esi, AlphaPtr + inc esi + mov AlphaPtr, esi + pop esi + + or al, al + jnz RSLoop1 + + RSLoop2 : + + dec BlitHeight + jz BlitDone + add edi, LineSkip + add ebx, LineSkip + + // reset all the z-level stuff for a new line + + mov ax, usZStartLevel + mov usZLevel, ax + mov ax, usZStartIndex + mov usZIndex, ax + mov ax, usZStartCols + mov usZColsToGo, ax + + + jmp LeftSkipSetup + + + BlitDone : + } + + return(TRUE); +} + void RenderRoomInfo( INT16 sStartPointX_M, INT16 sStartPointY_M, INT16 sStartPointX_S, INT16 sStartPointY_S, INT16 sEndXS, INT16 sEndYS ) diff --git a/TileEngine/renderworld.h b/TileEngine/renderworld.h index 02537da7..e58ba872 100644 --- a/TileEngine/renderworld.h +++ b/TileEngine/renderworld.h @@ -2,6 +2,8 @@ #define __RENDERWORLD_H #include "worlddef.h" +#include "LogicalBodyTypes/Layers.h" +#include "LogicalBodyTypes/BodyTypeDB.h" // TEMP SELECT STUFF #define NO_SELECT 0 @@ -221,8 +223,10 @@ BOOLEAN Zero8BPPDataTo16BPPBufferTransparent( UINT16 *pBuffer, UINT32 uiDestPitc BOOLEAN Blt8BPPDataTo16BPPBufferTransZIncClipZSameZBurnsThrough( UINT16 *pBuffer, UINT32 uiDestPitchBYTES, UINT16 *pZBuffer, UINT16 usZValue, HVOBJECT hSrcVObject, INT32 iX, INT32 iY, UINT16 usIndex, SGPRect *clipregion, INT16 sZStripIndex ); BOOLEAN Blt8BPPDataTo16BPPBufferTransInvZ( UINT16 *pBuffer, UINT32 uiDestPitchBYTES, UINT16 *pZBuffer, UINT16 usZValue, HVOBJECT hSrcVObject, INT32 iX, INT32 iY, UINT16 usIndex ); -BOOLEAN Blt8BPPDataTo16BPPBufferTransZTransShadowIncClip( UINT16 *pBuffer, UINT32 uiDestPitchBYTES, UINT16 *pZBuffer, UINT16 usZValue, HVOBJECT hSrcVObject, INT32 iX, INT32 iY, UINT16 usIndex, SGPRect *clipregion, INT16 sZIndex, UINT16 *p16BPPPalette ); -BOOLEAN Blt8BPPDataTo16BPPBufferTransZIncObscureClip( UINT16 *pBuffer, UINT32 uiDestPitchBYTES, UINT16 *pZBuffer, UINT16 usZValue, HVOBJECT hSrcVObject, INT32 iX, INT32 iY, UINT16 usIndex, SGPRect *clipregion); -BOOLEAN Blt8BPPDataTo16BPPBufferTransZTransShadowIncObscureClip( UINT16 *pBuffer, UINT32 uiDestPitchBYTES, UINT16 *pZBuffer, UINT16 usZValue, HVOBJECT hSrcVObject, INT32 iX, INT32 iY, UINT16 usIndex, SGPRect *clipregion, INT16 sZIndex, UINT16 *p16BPPPalette ); +BOOLEAN Blt8BPPDataTo16BPPBufferTransZTransShadowIncClip(UINT16 *pBuffer, UINT32 uiDestPitchBYTES, UINT16 *pZBuffer, UINT16 usZValue, HVOBJECT hSrcVObject, INT32 iX, INT32 iY, UINT16 usIndex, SGPRect *clipregion, INT16 sZIndex, UINT16 *p16BPPPalette, BOOLEAN fIgnoreShadows = FALSE); +BOOLEAN Blt8BPPDataTo16BPPBufferTransZTransShadowIncClipAlpha(UINT16 *pBuffer, UINT32 uiDestPitchBYTES, UINT16 *pZBuffer, UINT16 usZValue, HVOBJECT hSrcVObject, HVOBJECT hAlphaVObject, INT32 iX, INT32 iY, UINT16 usIndex, SGPRect *clipregion, INT16 sZIndex, UINT16 *p16BPPPalette, BOOLEAN fIgnoreShadows = FALSE); +BOOLEAN Blt8BPPDataTo16BPPBufferTransZIncObscureClip(UINT16 *pBuffer, UINT32 uiDestPitchBYTES, UINT16 *pZBuffer, UINT16 usZValue, HVOBJECT hSrcVObject, INT32 iX, INT32 iY, UINT16 usIndex, SGPRect *clipregion); +BOOLEAN Blt8BPPDataTo16BPPBufferTransZTransShadowIncObscureClip(UINT16 *pBuffer, UINT32 uiDestPitchBYTES, UINT16 *pZBuffer, UINT16 usZValue, HVOBJECT hSrcVObject, INT32 iX, INT32 iY, UINT16 usIndex, SGPRect *clipregion, INT16 sZIndex, UINT16 *p16BPPPalette, BOOLEAN fIgnoreShadows = FALSE); +BOOLEAN Blt8BPPDataTo16BPPBufferTransZTransShadowIncObscureClipAlpha(UINT16 *pBuffer, UINT32 uiDestPitchBYTES, UINT16 *pZBuffer, UINT16 usZValue, HVOBJECT hSrcVObject, HVOBJECT hAlphaVObject, INT32 iX, INT32 iY, UINT16 usIndex, SGPRect *clipregion, INT16 sZIndex, UINT16 *p16BPPPalette, BOOLEAN fIgnoreShadows = FALSE); #endif \ No newline at end of file diff --git a/TileEngine/structure.cpp b/TileEngine/structure.cpp index 2b7d310d..293f3b3f 100644 --- a/TileEngine/structure.cpp +++ b/TileEngine/structure.cpp @@ -2249,20 +2249,20 @@ BOOLEAN AddZStripInfoToVObject( HVOBJECT hVObject, STRUCTURE_FILE_REF * pStructu sNext = sSTIStartIndex + sSTIStep; fFirstTime = TRUE; - for (uiLoop = (UINT8)sSTIStartIndex; uiLoop < hVObject->usNumberOfObjects; uiLoop++ ) + for (uiLoop = (UINT8)sSTIStartIndex; uiLoop < hVObject->usNumberOfObjects; uiLoop++) { // Defualt to true fCopyIntoVo = TRUE; // Increment struct index.... - if ( uiLoop == (UINT32)sNext ) + if (uiLoop == (UINT32)sNext) { - sNext = (UINT16)( uiLoop + sSTIStep ); + sNext = (UINT16)(uiLoop + sSTIStep); sStructIndex++; } else { - if ( fFirstTime ) + if (fFirstTime) { fFirstTime = FALSE; } @@ -2272,7 +2272,7 @@ BOOLEAN AddZStripInfoToVObject( HVOBJECT hVObject, STRUCTURE_FILE_REF * pStructu } } - if ( fFromAnimation ) + if (fFromAnimation) { uiDestVoIndex = sStructIndex; } @@ -2282,17 +2282,17 @@ BOOLEAN AddZStripInfoToVObject( HVOBJECT hVObject, STRUCTURE_FILE_REF * pStructu } - if ( fCopyIntoVo && sStructIndex < pStructureFileRef->usNumberOfStructures ) + if (fCopyIntoVo && sStructIndex < pStructureFileRef->usNumberOfStructures) { - pDBStructure = pStructureFileRef->pDBStructureRef[ sStructIndex ].pDBStructure; - if (pDBStructure != NULL && ( pDBStructure->ubNumberOfTiles > 1 || ( pDBStructure->fFlags & STRUCTURE_CORPSE ) ) ) - //if (pDBStructure != NULL && pDBStructure->ubNumberOfTiles > 1 ) + pDBStructure = pStructureFileRef->pDBStructureRef[sStructIndex].pDBStructure; + if (pDBStructure != NULL && (pDBStructure->ubNumberOfTiles > 1 || (pDBStructure->fFlags & STRUCTURE_CORPSE))) + //if (pDBStructure != NULL && pDBStructure->ubNumberOfTiles > 1 ) { // ATE: We allow SLIDING DOORS of 2 tile sizes... - if ( !(pDBStructure->fFlags & STRUCTURE_ANYDOOR) || ( (pDBStructure->fFlags & ( STRUCTURE_ANYDOOR ) ) && ( pDBStructure->fFlags & STRUCTURE_SLIDINGDOOR ) ) ) + if (!(pDBStructure->fFlags & STRUCTURE_ANYDOOR) || ((pDBStructure->fFlags & (STRUCTURE_ANYDOOR)) && (pDBStructure->fFlags & STRUCTURE_SLIDINGDOOR))) { - hVObject->ppZStripInfo[ uiDestVoIndex ] = (ZStripInfo *) MemAlloc( sizeof( ZStripInfo ) ); - if (hVObject->ppZStripInfo[ uiDestVoIndex ] == NULL) + hVObject->ppZStripInfo[uiDestVoIndex] = (ZStripInfo *)MemAlloc(sizeof(ZStripInfo)); + if (hVObject->ppZStripInfo[uiDestVoIndex] == NULL) { // augh!! out of memory! free everything allocated and abort for (ubLoop2 = 0; ubLoop2 < uiLoop; ubLoop2++) @@ -2302,13 +2302,13 @@ BOOLEAN AddZStripInfoToVObject( HVOBJECT hVObject, STRUCTURE_FILE_REF * pStructu MemFree(hVObject->ppZStripInfo[uiLoop]); } } - MemFree( hVObject->ppZStripInfo ); + MemFree(hVObject->ppZStripInfo); hVObject->ppZStripInfo = NULL; - return( FALSE ); + return(FALSE); } else { - pCurr = hVObject->ppZStripInfo[ uiDestVoIndex ]; + pCurr = hVObject->ppZStripInfo[uiDestVoIndex]; ubNumIncreasing = 0; ubNumStable = 0; @@ -2319,7 +2319,7 @@ BOOLEAN AddZStripInfoToVObject( HVOBJECT hVObject, STRUCTURE_FILE_REF * pStructu sOffsetY = hVObject->pETRLEObject[uiLoop].sOffsetY; usWidth = hVObject->pETRLEObject[uiLoop].usWidth; usHeight = hVObject->pETRLEObject[uiLoop].usHeight; - if (pDBStructure->fFlags & (STRUCTURE_MOBILE | STRUCTURE_CORPSE) ) + if (pDBStructure->fFlags & (STRUCTURE_MOBILE | STRUCTURE_CORPSE)) { // adjust for the difference between the animation and structure base tile @@ -2427,44 +2427,58 @@ BOOLEAN AddZStripInfoToVObject( HVOBJECT hVObject, STRUCTURE_FILE_REF * pStructu // now create the array! pCurr->ubNumberOfZChanges = ubNumIncreasing + ubNumStable + ubNumDecreasing; - pCurr->pbZChange = (INT8 *) MemAlloc( pCurr->ubNumberOfZChanges ); - if ( pCurr->pbZChange == NULL) + // BIO (LOBOT): had to add a conditional as otherwise function would report a failure + // which then would prompt LOBOT to issue an error when trying to load animation surfaces with + // frames with a certain geometry. + // Only allocate memory and stuff if ubNumberOfZChanges > 0. Otherwise + // MemAlloc returns a NULL pointer which the code would interpret as + // allocation failing because of no memory. + // I hope this is OK, I don't entirely understand what is done here... + if (pCurr->ubNumberOfZChanges > 0) { - // augh! - for (ubLoop2 = 0; ubLoop2 < uiLoop; ubLoop2++) + pCurr->pbZChange = (INT8 *)MemAlloc(pCurr->ubNumberOfZChanges); + if (pCurr->pbZChange == NULL) { - if (hVObject->ppZStripInfo[ubLoop2] != NULL) + // augh! + for (ubLoop2 = 0; ubLoop2 < uiLoop; ubLoop2++) { - MemFree(hVObject->ppZStripInfo[uiLoop]); + if (hVObject->ppZStripInfo[ubLoop2] != NULL) + { + MemFree(hVObject->ppZStripInfo[uiLoop]); + } } + MemFree(hVObject->ppZStripInfo); + hVObject->ppZStripInfo = NULL; + return(FALSE); + } + for (ubLoop2 = 0; ubLoop2 < ubNumIncreasing; ubLoop2++) + { + pCurr->pbZChange[ubLoop2] = 1; + } + for (; ubLoop2 < ubNumIncreasing + ubNumStable; ubLoop2++) + { + pCurr->pbZChange[ubLoop2] = 0; + } + for (; ubLoop2 < pCurr->ubNumberOfZChanges; ubLoop2++) + { + pCurr->pbZChange[ubLoop2] = -1; + } + if (ubNumIncreasing > 0) + { + pCurr->bInitialZChange = -(ubNumIncreasing); + } + else if (ubNumStable > 0) + { + pCurr->bInitialZChange = 0; + } + else + { + pCurr->bInitialZChange = -(ubNumDecreasing); } - MemFree( hVObject->ppZStripInfo ); - hVObject->ppZStripInfo = NULL; - return( FALSE ); - } - for (ubLoop2 = 0; ubLoop2 < ubNumIncreasing; ubLoop2++) - { - pCurr->pbZChange[ubLoop2] = 1; - } - for (; ubLoop2 < ubNumIncreasing + ubNumStable; ubLoop2++) - { - pCurr->pbZChange[ubLoop2] = 0; - } - for (; ubLoop2 < pCurr->ubNumberOfZChanges; ubLoop2++) - { - pCurr->pbZChange[ubLoop2] = -1; - } - if (ubNumIncreasing > 0) - { - pCurr->bInitialZChange = -(ubNumIncreasing); - } - else if (ubNumStable > 0) - { - pCurr->bInitialZChange = 0; } else { - pCurr->bInitialZChange = -(ubNumDecreasing); + pCurr->pbZChange = NULL; } } } diff --git a/Utils/_ChineseText.cpp b/Utils/_ChineseText.cpp index 64770381..6ae1534e 100644 --- a/Utils/_ChineseText.cpp +++ b/Utils/_ChineseText.cpp @@ -6352,6 +6352,7 @@ STR16 zOptionsToggleText[] = L"属性进度条", //L"Stat Progress Bars", // Show progress towards stat increase //ham3.6 L"替代战略地图颜色", // Change color scheme of Strategic Map L"替代子弹图像", // Show alternate bullet graphics (tracers) + L"Use Logical Bodytypes", L"显示佣兵军衔", // shows mercs ranks L"显示脸部装备图", L"显示脸部装备图标", @@ -6466,6 +6467,7 @@ STR16 zOptionsScreenHelpText[] = L"打开时,显示各属性的增长进度。", // L"When ON, shows character progress towards gaining levels.", //ham3.6 L"打开时,战略地图将会根据探索状态显示不同的着色。", L"打开时,当你射击时会显示间隔子弹图像。", + L"When ON, mercenary body graphic can change along with equipped gear.", // TODO.Translate L"打开时,在战略界面的佣兵名旁显示军衔。", L"打开时,显示佣兵脸部装备图。", L"打开时,佣兵肖像右下角显示脸部装备图标", diff --git a/Utils/_DutchText.cpp b/Utils/_DutchText.cpp index f020002d..99cf00da 100644 --- a/Utils/_DutchText.cpp +++ b/Utils/_DutchText.cpp @@ -6359,6 +6359,7 @@ STR16 zOptionsToggleText[] = L"Stat Progress Bars", // Show progress towards stat increase // TODO.Translate L"Alternate Strategy-Map Colors", // Change color scheme of Strategic Map L"Alternate bullet graphics", // Show alternate bullet graphics (tracers) // TODO.Translate + L"Use Logical Bodytypes", L"Show Merc Ranks", // shows mercs ranks // TODO.Translate L"Show Face gear graphics", // TODO.Translate L"Show Face gear icons", @@ -6473,6 +6474,7 @@ STR16 zOptionsScreenHelpText[] = L"When ON, shows character progress towards gaining levels.", // TODO.Translate L"When ON, the Strategic Map will be colored differently based on exploration.", L"When ON, alternate bullet graphics will be shown when you shoot.", // TODO.Translate + L"When ON, mercenary body graphic can change along with equipped gear.", // TODO.Translate L"When ON, ranks will be displayed before merc names in the strategic view.", // TODO.Translate L"When ON, you will see the equipped face gear on the merc portraits.", // TODO.Translate L"When ON, you will see icons for the equipped face gear on the merc portraits in the lower right corner.", diff --git a/Utils/_EnglishText.cpp b/Utils/_EnglishText.cpp index 3882526e..443c9107 100644 --- a/Utils/_EnglishText.cpp +++ b/Utils/_EnglishText.cpp @@ -20,52 +20,52 @@ void this_is_the_EnglishText_public_symbol(void); #if defined( ENGLISH ) /* - + ****************************************************************************************************** ** IMPORTANT TRANSLATION NOTES ** ****************************************************************************************************** GENERAL INSTRUCTIONS -- Always be aware that foreign strings should be of equal or shorter length than the English equivalent. - I know that this is difficult to do on many occasions due to the nature of foreign languages when - compared to English. By doing so, this will greatly reduce the amount of work on both sides. In - most cases (but not all), JA2 interfaces were designed with just enough space to fit the English word. - The general rule is if the string is very short (less than 10 characters), then it's short because of - interface limitations. On the other hand, full sentences commonly have little limitations for length. +- Always be aware that foreign strings should be of equal or shorter length than the English equivalent. + I know that this is difficult to do on many occasions due to the nature of foreign languages when + compared to English. By doing so, this will greatly reduce the amount of work on both sides. In + most cases (but not all), JA2 interfaces were designed with just enough space to fit the English word. + The general rule is if the string is very short (less than 10 characters), then it's short because of + interface limitations. On the other hand, full sentences commonly have little limitations for length. Strings in between are a little dicey. -- Never translate a string to appear on multiple lines. All strings L"This is a really long string...", +- Never translate a string to appear on multiple lines. All strings L"This is a really long string...", must fit on a single line no matter how long the string is. All strings start with L" and end with ", -- Never remove any extra spaces in strings. In addition, all strings containing multiple sentences only - have one space after a period, which is different than standard typing convention. Never modify sections - of strings contain combinations of % characters. These are special format characters and are always +- Never remove any extra spaces in strings. In addition, all strings containing multiple sentences only + have one space after a period, which is different than standard typing convention. Never modify sections + of strings contain combinations of % characters. These are special format characters and are always used in conjunction with other characters. For example, %s means string, and is commonly used for names, - locations, items, etc. %d is used for numbers. %c%d is a character and a number (such as A9). - %% is how a single % character is built. There are countless types, but strings containing these - special characters are usually commented to explain what they mean. If it isn't commented, then + locations, items, etc. %d is used for numbers. %c%d is a character and a number (such as A9). + %% is how a single % character is built. There are countless types, but strings containing these + special characters are usually commented to explain what they mean. If it isn't commented, then if you can't figure out the context, then feel free to ask SirTech. -- Comments are always started with // Anything following these two characters on the same line are - considered to be comments. Do not translate comments. Comments are always applied to the following - string(s) on the next line(s), unless the comment is on the same line as a string. -- All new comments made by SirTech will use "//@@@ comment" (without the quotes) notation. By searching +- Comments are always started with // Anything following these two characters on the same line are + considered to be comments. Do not translate comments. Comments are always applied to the following + string(s) on the next line(s), unless the comment is on the same line as a string. +- All new comments made by SirTech will use "//@@@ comment" (without the quotes) notation. By searching for @@@ everytime you recieve a new version, it will simplify your task and identify special instructions. - Commonly, these types of comments will be used to ask you to abbreviate a string. Please leave the + Commonly, these types of comments will be used to ask you to abbreviate a string. Please leave the comments intact, and SirTech will remove them once the translation for that particular area is resolved. -- If you have a problem or question with translating certain strings, please use "//!!! comment" - (without the quotes). The syntax is important, and should be identical to the comments used with @@@ - symbols. SirTech will search for !!! to look for your problems and questions. This is a more +- If you have a problem or question with translating certain strings, please use "//!!! comment" + (without the quotes). The syntax is important, and should be identical to the comments used with @@@ + symbols. SirTech will search for !!! to look for your problems and questions. This is a more efficient method than detailing questions in email, so try to do this whenever possible. - + FAST HELP TEXT -- Explains how the syntax of fast help text works. ************** 1) BOLDED LETTERS - The popup help text system supports special characters to specify the hot key(s) for a button. + The popup help text system supports special characters to specify the hot key(s) for a button. Anytime you see a '|' symbol within the help text string, that means the following key is assigned - to activate the action which is usually a button. + to activate the action which is usually a button. - EX: L"|Map Screen" + EX: L"|Map Screen" This means the 'M' is the hotkey. In the game, when somebody hits the 'M' key, it activates that button. When translating the text to another language, it is best to attempt to choose a word that @@ -78,10 +78,10 @@ FAST HELP TEXT -- Explains how the syntax of fast help text works. 2) NEWLINE Any place you see a \n within the string, you are looking at another string that is part of the fast help - text system. \n notation doesn't need to be precisely placed within that string, but whereever you wish - to start a new line. + text system. \n notation doesn't need to be precisely placed within that string, but whereever you wish + to start a new line. - EX: L"Clears all the mercs' positions,\nand allows you to re-enter them manually." + EX: L"Clears all the mercs' positions,\nand allows you to re-enter them manually." Would appear as: @@ -92,10 +92,10 @@ FAST HELP TEXT -- Explains how the syntax of fast help text works. in the above example, we would see WRONG WAY -- spaces before and after the \n - EX: L"Clears all the mercs' positions, \n and allows you to re-enter them manually." + EX: L"Clears all the mercs' positions, \n and allows you to re-enter them manually." Would appear as: (the second line is moved in a character) - + Clears all the mercs' positions, and allows you to re-enter them manually. @@ -105,7 +105,7 @@ FAST HELP TEXT -- Explains how the syntax of fast help text works. Throughout the text files, you'll find an assortment of comments. Comments are used to describe the text to make translation easier, but comments don't need to be translated. A good thing is to search for - "@@@" after receiving new version of the text file, and address the special notes in this manner. + "@@@" after receiving new version of the text file, and address the special notes in this manner. !!! NOTATION ************ @@ -115,7 +115,7 @@ FAST HELP TEXT -- Explains how the syntax of fast help text works. */ -CHAR16 XMLTacticalMessages[1000][MAX_MESSAGE_NAMES_CHARS] = +CHAR16 XMLTacticalMessages[1000][MAX_MESSAGE_NAMES_CHARS] = { L"", }; @@ -131,7 +131,7 @@ STR16 pMenuStrings[] = L"Quests", L"Menu 5", L"Menu 6", //5 - L"Menu 7", + L"Menu 7", L"Menu 8", L"Menu 9", L"Menu 10", @@ -141,14 +141,14 @@ STR16 pMenuStrings[] = L"Menu 14", L"Menu 15", L"Menu 15", // 15 - + //Briefing Room L"Enter", }; STR16 pOtherButtonsText[] = { - L"Briefing", + L"Briefing", L"Accept", }; @@ -162,7 +162,7 @@ STR16 pOtherButtonsHelpText[] = STR16 pLocationPageText[] = { L"Prev page", - L"Photo", + L"Photo", L"Next page", }; @@ -177,22 +177,22 @@ STR16 pSectorPageText[] = L"Briefing Room. Please click the 'Enter' button.", }; -STR16 pEncyclopediaTypeText[] = +STR16 pEncyclopediaTypeText[] = { L"Unknown",// 0 - unknown L"City", //1 - city L"SAM Site", //2 - SAM Site L"Other Location", //3 - other location - L"Mine", //4 - mines - L"Military Complex", //5 - military complex - L"Laboratory Complex", //6 - laboratory complex - L"Factory Complex", //7 - factory complex - L"Hospital", //8 - hospital + L"Mine", //4 - mines + L"Military Complex", //5 - military complex + L"Laboratory Complex", //6 - laboratory complex + L"Factory Complex", //7 - factory complex + L"Hospital", //8 - hospital L"Prison", //9 - prison - L"Airport", //10 - airport + L"Airport", //10 - airport }; -STR16 pEncyclopediaHelpCharacterText[] = +STR16 pEncyclopediaHelpCharacterText[] = { L"Show All", L"Show AIM", @@ -205,7 +205,7 @@ STR16 pEncyclopediaHelpCharacterText[] = L"Filter", }; -STR16 pEncyclopediaShortCharacterText[] = +STR16 pEncyclopediaShortCharacterText[] = { L"All", L"AIM", @@ -218,7 +218,7 @@ STR16 pEncyclopediaShortCharacterText[] = L"Filter", }; -STR16 pEncyclopediaHelpText[] = +STR16 pEncyclopediaHelpText[] = { L"Show All", L"Show City", @@ -233,7 +233,7 @@ STR16 pEncyclopediaHelpText[] = L"Show Airport", }; -STR16 pEncyclopediaSkrotyText[] = +STR16 pEncyclopediaSkrotyText[] = { L"All", L"City", @@ -321,7 +321,7 @@ STR16 pEncyclopediaSubFilterCharText[] = L"",//reserved. Insert new Other filters above! }; -STR16 pEncyclopediaFilterItemText[] = +STR16 pEncyclopediaFilterItemText[] = {//major item filter button text max 7 chars //..L"------v" L"All",//0 @@ -423,14 +423,14 @@ STR16 pEncyclopediaSubFilterQuestText[] = L"",//reserved. insert new completed quest subfilters above! }; -STR16 pEncyclopediaShortInventoryText[] = +STR16 pEncyclopediaShortInventoryText[] = { L"All", //0 L"Gun", L"Ammo", L"LBE", L"Misc", - + L"Show All", //5 L"Show Gun", L"Show Ammo", @@ -486,7 +486,7 @@ STR16 BoxFilter[] = L"Misc", //34 }; -STR16 QuestDescText[] = +STR16 QuestDescText[] = { L"Deliver Letter", L"Food Route", @@ -523,7 +523,7 @@ STR16 QuestDescText[] = L"No 29 Yet", }; -STR16 FactDescText[] = +STR16 FactDescText[] = { L"Omerta Liberated", L"Drassen Liberated", @@ -645,7 +645,7 @@ STR16 FactDescText[] = L"Past club closing time and Darren warned Player. (reset every day)", L"Joey is EPC", L"Joey is in C5", - + L"Joey is within 5 tiles of Martha(109) in sector G8", //110 L"Joey is Dead!", L"At least one player merc within 5 tiles of Martha", @@ -656,7 +656,7 @@ STR16 FactDescText[] = L"Maria is EPC and inside leather Shop", L"Player wants to buy vest", L"Maria rescue was noticed by KingPin goons and Kingpin now enemy", - + L"Angel left deed on counter", //120 L"Maria quest over", L"Player bandaged NPC today", @@ -667,7 +667,7 @@ STR16 FactDescText[] = L"Player is giving amount of money >= $1000", L"Player is giving amount less than $1000", L"Waldo agreed to fix helicopter( heli is damaged )", - + L"Helicopter was destroyed", //130 L"Waldo told us about heli pilot", L"Father told us about Deidranna killing sick people", @@ -678,7 +678,7 @@ STR16 FactDescText[] = L"Loyalty is High", L"Player doing poorly", L"Player gave valid head to Carmen", - + L"Current sector is G9(Cambria)", //140 L"Current sector is C5(SanMona)", L"Current sector is C13(Drassen", @@ -689,7 +689,7 @@ STR16 FactDescText[] = L"Carmen gave us final warning", L"Vince has explained that he has to charge", L"Vince is expecting cash (reset everyday)", - + L"Player stole some medical supplies once", //150 L"Player stole some medical supplies again", L"Vince can be recruited", @@ -700,7 +700,7 @@ STR16 FactDescText[] = L"", L"Maria left in wrong sector", L"Skyrider left in wrong sector", - + L"Joey left in wrong sector", //160 L"John left in wrong sector", L"Mary left in wrong sector", @@ -711,7 +711,7 @@ STR16 FactDescText[] = L"Shank(67) is not in secotr", L"Bloodcat quest on for more than 2 days", L"Effective threat made to Armand", - + L"Queen is DEAD!", //170 L"Speaker is with Aim or Aim person on squad within 10 tiles", L"Current mine is empty", @@ -720,7 +720,7 @@ STR16 FactDescText[] = L"Creatures invaded current mine", L"Player LOST current mine", L"Current mine is at FULL production", - L"Dynamo(66) is Speaker or within 10 tiles of speaker", + L"Dynamo(66) is Speaker or within 10 tiles of speaker", L"Fred told us about creatures", L"Matt told us about creatures", //180 @@ -729,21 +729,21 @@ STR16 FactDescText[] = L"Carl told us about creatures", L"Chalice stolen from museam", L"John(118) is EPC", - L"Mary(119) and John (118) are EPC's", + L"Mary(119) and John (118) are EPC's", L"Mary(119) is alive", - L"Mary(119)is EPC", - L"Mary(119) is bleeding", + L"Mary(119)is EPC", + L"Mary(119) is bleeding", L"John(118) is alive", //190 - L"John(118) is bleeding", + L"John(118) is bleeding", L"John or Mary close to airport in Drassen(B13)", L"Mary is Dead", L"Miners placed", L"Krott planning to shoot player", L"Madlab explained his situation", L"Madlab expecting a firearm", - L"Madlab expecting a video camera.", - L"Item condition is < 70 ", + L"Madlab expecting a video camera.", + L"Item condition is < 70 ", L"Madlab complained about bad firearm.", //200 L"Madlab complained about bad video camera.", @@ -753,7 +753,7 @@ STR16 FactDescText[] = L"Robot is ready to go a second time!", L"Second robot destroyed.", L"Mines explained to player.", - L"Dynamo (#66) is in sector J9.", + L"Dynamo (#66) is in sector J9.", L"Dynamo (#66) is alive.", L"One PC hasn't fought, but is able, and less than 3 fights have occured", //210 @@ -777,7 +777,7 @@ STR16 FactDescText[] = L"Dave has gas. (randomized daily)", L"Vehicle is present", L"First battle won by player", - L"Robot recruited and moved", + L"Robot recruited and moved", L"No club fighting allowed", //230 L"Player already fought 3 fights today", @@ -788,7 +788,7 @@ STR16 FactDescText[] = L"Micky (#96) is drunk", L"Player has attempted to force their way into brothel", L"Rat effectively threatened 3 times", - L"Player paid for two people to enter brothel", + L"Player paid for two people to enter brothel", L"", //240 L"", @@ -827,7 +827,7 @@ STR16 FactDescText[] = L"Fact willis heard about joey rescue",// 271 L"Fact willis gives discount",// 272 L"Fact hillbillies killed",// 273 - L"Fact keith out of business", // 274 + L"Fact keith out of business", // 274 L"Fact mike available to army",// 275 L"Fact kingpin can send assassins",// 276 L"Fact estoni refuelling possible",// 277 @@ -1088,8 +1088,8 @@ STR16 iEditorItemStatsButtonsText[] = L"Delete item (|D|e|l)", }; -STR16 FaceDirs[8] = -{ +STR16 FaceDirs[8] = +{ L"north", L"northeast", L"east", @@ -1100,20 +1100,20 @@ STR16 FaceDirs[8] = L"northwest" }; -STR16 iEditorMercsToolbarText[] = +STR16 iEditorMercsToolbarText[] = { L"Toggle viewing of players", //0 L"Toggle viewing of enemies", L"Toggle viewing of creatures", L"Toggle viewing of rebels", L"Toggle viewing of civilians", - + L"Player", L"Enemy", L"Creature", L"Rebels", L"Civilian", - + L"DETAILED PLACEMENT", //10 L"General information mode", L"Physical appearance mode", @@ -1128,7 +1128,7 @@ STR16 iEditorMercsToolbarText[] = L"Find next merc (|S|p|a|c|e)\nFind previous merc (|C|t|r|l+|S|p|a|c|e)", L"Toggle priority existance", L"Toggle whether or not placement\nhas access to all doors", - + //Orders L"STATIONARY", L"ON GUARD", @@ -1138,7 +1138,7 @@ STR16 iEditorMercsToolbarText[] = L"FAR PATROL", L"POINT PATROL", //30 L"RND PT PATROL", - + //Attitudes L"DEFENSIVE", L"BRAVE SOLO", @@ -1146,40 +1146,40 @@ STR16 iEditorMercsToolbarText[] = L"AGGRESSIVE", L"CUNNING SOLO", L"CUNNING AID", - + L"Set merc to face %s", - + L"Find", L"BAD", //40 L"POOR", L"AVERAGE", L"GOOD", L"GREAT", - + L"BAD", L"POOR", L"AVERAGE", L"GOOD", L"GREAT", - + L"Previous color set", //50 L"Next color set", - + L"Previous body type", L"Next body type", - + L"Toggle time variance (+ or - 15 minutes)", L"Toggle time variance (+ or - 15 minutes)", L"Toggle time variance (+ or - 15 minutes)", L"Toggle time variance (+ or - 15 minutes)", - + L"No action", L"No action", L"No action", //60 L"No action", - + L"Clear Schedule", - + L"Find selected merc", }; @@ -1314,7 +1314,7 @@ STR16 iRenderMapEntryPointsAndLightsText[] = L"South Entry Point", L"Center Entry Point", L"Isolated Entry Point", - + L"Prime", L"Night", L"24Hour", @@ -1326,7 +1326,7 @@ STR16 iBuildTriggerNameText[] = L"Panic Trigger2", L"Panic Trigger3", L"Trigger%d", - + L"Pressure Action", L"Panic Action1", L"Panic Action2", @@ -1375,14 +1375,14 @@ STR16 iRenderDoorEditingWindowText[] = //EditorItems.cpp -STR16 pInitEditorItemsInfoText[] = +STR16 pInitEditorItemsInfoText[] = { L"Pressure Action", //0 L"Panic Action1", L"Panic Action2", L"Panic Action3", L"Action%d", - + L"Panic Trigger1", //5 L"Panic Trigger2", L"Panic Trigger3", @@ -1404,7 +1404,7 @@ STR16 pUpdateMapInfoText[] = L"R", //0 L"G", L"B", - + L"Prime", L"Night", L"24Hrs", //5 @@ -1445,16 +1445,16 @@ CHAR16 gszScheduleActions[ 11 ][20] = }; STR16 zDiffNames[5] = // NUM_DIFF_LVLS = 5 -{ - L"Wimp", - L"Easy", +{ + L"Wimp", + L"Easy", L"Average", - L"Tough", - L"Steroid Users Only" + L"Tough", + L"Steroid Users Only" }; -STR16 EditMercStat[12] = -{ +STR16 EditMercStat[12] = +{ L"Max Health", L"Cur Health", L"Strength", @@ -1466,30 +1466,30 @@ STR16 EditMercStat[12] = L"Explosives", L"Medical", L"Scientific", - L"Exp Level", + L"Exp Level", }; -STR16 EditMercOrders[8] = -{ +STR16 EditMercOrders[8] = +{ L"Stationary", L"On Guard", L"Close Patrol", L"Far Patrol", L"Point Patrol", L"On Call", - L"Seek Enemy", + L"Seek Enemy", L"Random Point Patrol", }; -STR16 EditMercAttitudes[6] = -{ +STR16 EditMercAttitudes[6] = +{ L"Defensive", L"Brave Loner", L"Brave Buddy", L"Cunning Loner", L"Cunning Buddy", - L"Aggressive", + L"Aggressive", }; STR16 pDisplayEditMercWindowText[] = @@ -1499,17 +1499,17 @@ STR16 pDisplayEditMercWindowText[] = L"Combat Attitude:", }; -STR16 pCreateEditMercWindowText[] = +STR16 pCreateEditMercWindowText[] = { L"Merc Colors", //0 L"Done", - + L"Previous merc standing orders", - L"Next merc standing orders", - + L"Next merc standing orders", + L"Previous merc combat attitude", L"Next merc combat attitude", //5 - + L"Decrease merc stat", L"Increase merc stat", }; @@ -1547,24 +1547,24 @@ STR16 pDisplayBodyTypeInfoText[] = L"Humvee", }; -STR16 pUpdateMercsInfoText[] = +STR16 pUpdateMercsInfoText[] = { L" --=ORDERS=-- ", //0 L"--=ATTITUDE=--", - + L"RELATIVE", L"ATTRIBUTES", - + L"RELATIVE", L"EQUIPMENT", - + L"RELATIVE", L"ATTRIBUTES", - + L"Army", L"Admin", L"Elite", //10 - + L"Exp. Level", L"Life", L"LifeMax", @@ -1578,26 +1578,26 @@ STR16 pUpdateMercsInfoText[] = L"Medical", L"Mechanical", L"Morale", - + L"Hair color:", L"Skin color:", L"Vest color:", L"Pant color:", - + L"RANDOM", L"RANDOM", L"RANDOM", //30 L"RANDOM", - + L"By specifying a profile index, all of the information will be extracted from the profile ", L"and override any values that you have edited. It will also disable the editing features ", L"though, you will still be able to view stats, etc. Pressing ENTER will automatically ", L"extract the number you have typed. A blank field will clear the profile. The current ", L"number of profiles range from 0 to ", - + L"Current Profile: n/a ", L"Current Profile: %s", - + L"STATIONARY", L"ON CALL", //40 L"ON GUARD", @@ -1616,12 +1616,12 @@ STR16 pUpdateMercsInfoText[] = L"2)", L"3)", L"4)", - + L"lock", L"unlock", L"open", L"close", - + L"Click on the gridno adjacent to the door that you wish to %s.", //60 L"Click on the gridno where you wish to move after you %s the door.", L"Click on the gridno where you wish to move to.", @@ -1647,7 +1647,7 @@ STR16 pCopyMercPlacementText[] = L"Placement copied.", }; -STR16 pPasteMercPlacementText[] = +STR16 pPasteMercPlacementText[] = { L"Placement not pasted as no placement is saved in buffer.", L"Placement pasted.", @@ -1655,49 +1655,49 @@ STR16 pPasteMercPlacementText[] = }; //editscreen.cpp -STR16 pEditModeShutdownText[] = +STR16 pEditModeShutdownText[] = { L"Exit editor?", }; -STR16 pHandleKeyboardShortcutsText[] = +STR16 pHandleKeyboardShortcutsText[] = { L"Are you sure you wish to remove all lights?", //0 L"Are you sure you wish to reverse the schedules?", L"Are you sure you wish to clear all of the schedules?", - + L"Clicked Placement Enabled", L"Clicked Placement Disabled", - + L"Draw High Ground Enabled", //5 L"Draw High Ground Disabled", - + L"Number of edge points: N=%d E=%d S=%d W=%d", - + L"Random Placement Enabled", L"Random Placement Disabled", - + L"Removing Treetops", //10 L"Showing Treetops", - + L"World Raise Reset", - + L"World Raise Set Old", L"World Raise Set", }; -STR16 pPerformSelectedActionText[] = +STR16 pPerformSelectedActionText[] = { L"Creating radar map for %S", //0 - + L"Delete current map and start a new basement level?", L"Delete current map and start a new cave level?", L"Delete current map and start a new outdoor level?", - + L" Wipe out ground textures? ", }; -STR16 pWaitForHelpScreenResponseText[] = +STR16 pWaitForHelpScreenResponseText[] = { L"HOME", //0 L"Toggle fake editor lighting ON/OFF", @@ -1897,49 +1897,49 @@ STR16 pRenderSectorInformationText[] = { L"Tileset: %s", //0 L"Version Info: Summary: 1.%02d, Map: %1.2f / %02d", - L"Number of items: %d", + L"Number of items: %d", L"Number of lights: %d", L"Number of entry points: %d", - + L"N", L"E", L"S", L"W", L"C", L"I", //10 - + L"Number of rooms: %d", L"Total map population: %d", L"Enemies: %d", L"Admins: %d", - + L"(%d detailed, %d profile -- %d have priority existance)", L"Troops: %d", - + L"(%d detailed, %d profile -- %d have priority existance)", L"Elites: %d", - + L"(%d detailed, %d profile -- %d have priority existance)", L"Civilians: %d", //20 - + L"(%d detailed, %d profile -- %d have priority existance)", - + L"Humans: %d", L"Cows: %d", L"Bloodcats: %d", - + L"Creatures: %d", - + L"Monsters: %d", L"Bloodcats: %d", - + L"Number of locked and/or trapped doors: %d", L"Locked: %d", L"Trapped: %d", //30 L"Locked & Trapped: %d", - + L"Civilians with schedules: %d", - + L"Too many exit grid destinations (more than 4)...", L"ExitGrids: %d (%d with a long distance destination)", L"ExitGrids: none", @@ -1952,7 +1952,7 @@ STR16 pRenderSectorInformationText[] = L"%d placements have patrol orders without any waypoints defined.", L"%d placements have waypoints, but without any patrol orders.", L"%d gridnos have questionable room numbers. Please validate.", - + }; STR16 pRenderItemDetailsText[] = @@ -1960,9 +1960,9 @@ STR16 pRenderItemDetailsText[] = L"R", //0 L"S", L"Enemy", - + L"TOO MANY ITEMS TO DISPLAY!", - + L"Panic1", L"Panic2", L"Panic3", @@ -1971,18 +1971,18 @@ STR16 pRenderItemDetailsText[] = L"Norm3", L"Norm4", //10 L"Pressure Actions", - + L"TOO MANY ITEMS TO DISPLAY!", - + L"PRIORITY ENEMY DROPPED ITEMS", L"None", - + L"TOO MANY ITEMS TO DISPLAY!", L"NORMAL ENEMY DROPPED ITEMS", L"TOO MANY ITEMS TO DISPLAY!", L"None", L"TOO MANY ITEMS TO DISPLAY!", - L"ERROR: Can't load the items for this map. Reason unknown.", //20 + L"ERROR: Can't load the items for this map. Reason unknown.", //20 }; STR16 pRenderSummaryWindowText[] = @@ -1994,58 +1994,58 @@ STR16 pRenderSummaryWindowText[] = L"approximately 4 minutes on a P200MMX to analyse 100 maps, so", L"depending on your computer, it may vary.", L"Do you wish to regenerate info for ALL these maps at this time (y/n)?", - + L"There is no sector currently selected.", - + L"Entering a temp file name that doesn't follow campaign editor conventions...", - + L"You need to either load an existing map or create a new map before being", L"able to enter the editor, or you can quit (ESC or Alt+x).", //10 - L", ground level", - L", underground level 1", - L", underground level 2", - L", underground level 3", - L", alternate G level", - L", alternate B1 level", - L", alternate B2 level", + L", ground level", + L", underground level 1", + L", underground level 2", + L", underground level 3", + L", alternate G level", + L", alternate B1 level", + L", alternate B2 level", L", alternate B3 level", - + L"ITEM DETAILS -- sector %s", L"Summary Information for sector %s:",//20 - + L"Summary Information for sector %s", L"does not exist.", - + L"Summary Information for sector %s", L"does not exist.", - + L"No information exists for sector %s.", - + L"No information exists for sector %s.", - + L"FILE: %s", - + L"FILE: %s", - + L"Override READONLY", L"Overwrite File", //30 - + L"You currently have no summary data. By creating one, you will be able to keep track", L"of information pertaining to all of the sectors you edit and save. The creation process", L"will analyse all maps in your \\MAPS directory, and generate a new one. This could", L"take a few minutes depending on how many valid maps you have. Valid maps are", - L"maps following the proper naming convention from a1.dat - p16.dat. Underground maps", + L"maps following the proper naming convention from a1.dat - p16.dat. Underground maps", L"are signified by appending _b1 to _b3 before the .dat (ex: a9_b1.dat). ", - + L"Do you wish to do this now (y/n)?", - + L"No summary info. Creation denied.", - + L"Grid", L"Progress", //40 L"Use Alternate Maps", - + L"Summary", L"Items", }; @@ -2100,12 +2100,12 @@ STR16 pDisplaySelectionWindowButtonText[] = //Cursor Modes.cpp STR16 wszSelType[6] = { - L"Small", - L"Medium", - L"Large", - L"XLarge", - L"Width: xx", - L"Area" + L"Small", + L"Medium", + L"Large", + L"XLarge", + L"Width: xx", + L"Area" }; //--- @@ -2114,11 +2114,11 @@ CHAR16 gszAimPages[ 6 ][ 20 ] = { L"Page 1/2", //0 L"Page 2/2", - + L"Page 1/3", L"Page 2/3", L"Page 3/3", - + L"Page 1/1", //5 }; @@ -2179,7 +2179,7 @@ CHAR16 AmmoCaliber[MAXITEMS][20];// = //}; // This BobbyRayAmmoCaliber is virtually the same as AmmoCaliber however the bobby version doesnt have as much room for the words. -// +// // Different weapon calibres // CAWS is Close Assault Weapon System and should probably be left as it is // NATO is the North Atlantic Treaty Organization @@ -2309,7 +2309,7 @@ CHAR16 Message[][STRING_LENGTH] = L"None", L"Eject ammo", L"Attachments", - + //You cannot use "item(s)" and your "other item" at the same time. //Ex: You cannot use sun goggles and you gas mask at the same time. L"You cannot use your %s and your %s at the same time.", @@ -2317,7 +2317,7 @@ CHAR16 Message[][STRING_LENGTH] = L"The item you have in your cursor can be attached to certain items by placing it in one of the four attachment slots.", L"The item you have in your cursor can be attached to certain items by placing it in one of the four attachment slots. (However in this case, the item is not compatible.)", L"The sector isn't cleared of enemies!", - L"You still need to give %s %s", + L"You still need to give %s %s", L"%s is hit in the head!", L"Abandon the fight?", L"This attachment will be permanent. Go ahead with it?", @@ -2342,13 +2342,13 @@ CHAR16 Message[][STRING_LENGTH] = L"%s's desert camouflage has worn off.", L"%s's desert camouflage has washed off.", - + L"%s's wood camouflage has worn off.", L"%s's wood camouflage has washed off.", - + L"%s's urban camouflage has worn off.", L"%s's urban camouflage has washed off.", - + L"%s's snow camouflage snow has worn off.", L"%s's snow camouflage has washed off.", @@ -2406,11 +2406,11 @@ STR16 sTimeStrings[] = L"5 min", L"30 min", L"60 min", - L"6 hrs", + L"6 hrs", }; -// Assignment Strings: what assignment does the merc have right now? For example, are they on a squad, training, +// Assignment Strings: what assignment does the merc have right now? For example, are they on a squad, training, // administering medical aid (doctor) or training a town. All are abbreviated. 8 letters is the longest it can be. STR16 pAssignmentStrings[] = @@ -2442,11 +2442,11 @@ STR16 pAssignmentStrings[] = L"In Trans", // in transit - abbreviated form L"Repair", // repairing L"Radio Scan", // scanning for nearby patrols - L"Practice", // training themselves - L"Militia", // training a town to revolt + L"Practice", // training themselves + L"Militia", // training a town to revolt L"M.Militia", //training moving militia units L"Trainer", // training a teammate - L"Student", // being trained by someone else + L"Student", // being trained by someone else L"GetItem", // move items L"Staff", // operating a strategic facility L"Eat", // eating at a facility (cantina etc.) @@ -2455,7 +2455,7 @@ STR16 pAssignmentStrings[] = L"Dead", // dead L"Incap.", // abbreviation for incapacitated L"POW", // Prisoner of war - captured - L"Hospital", // patient in a hospital + L"Hospital", // patient in a hospital L"Empty", // Vehicle is empty L"Snitch", // facility: undercover prisoner (snitch) L"Propag.", // facility: spread propaganda @@ -2497,7 +2497,7 @@ STR16 pMilitiaButtonString[] = L"Unassign All", // move all milita troops to unassigned pool }; -STR16 pConditionStrings[] = +STR16 pConditionStrings[] = { L"Excellent", //the state of a soldier .. excellent health L"Good", // good health @@ -2505,7 +2505,7 @@ STR16 pConditionStrings[] = L"Wounded", // wounded health L"Fatigued", // tired L"Bleeding", // bleeding to death - L"Unconscious", // knocked out + L"Unconscious", // knocked out L"Dying", // near death L"Dead", // dead }; @@ -2551,7 +2551,7 @@ STR16 pPersonnelAssignmentStrings[] = L"In Transit", L"Repair", L"Radio Scan", - L"Practice", + L"Practice", L"Training Militia", L"Training Mobile Militia", // Missing L"Trainer", @@ -2564,12 +2564,12 @@ STR16 pPersonnelAssignmentStrings[] = L"Dead", L"Incap.", L"POW", - L"Hospital", + L"Hospital", L"Empty", // Vehicle is empty L"Undercover Snitch", // facility: undercover prisoner (snitch) L"Spreading Propaganda", // facility: spread propaganda L"Spreading Propaganda", // facility: spread propaganda (globally) - L"Gathering Rumours", // facility: gather rumours + L"Gathering Rumours", // facility: gather rumours L"Spreading Propaganda", // spread propaganda L"Gathering Rumours", // gather information L"Commanding Militia", // militia movement orders @@ -2620,7 +2620,7 @@ STR16 pLongAssignmentStrings[] = L"In Transit", L"Repair", L"Radio Scan", - L"Practice", + L"Practice", L"Train Militia", L"Train Mobiles", // Missing L"Train Teammate", @@ -2632,12 +2632,12 @@ STR16 pLongAssignmentStrings[] = L"Dead", L"Incap.", L"POW", - L"Hospital", // patient in a hospital + L"Hospital", // patient in a hospital L"Empty", // Vehicle is empty L"Undercover Snitch", // facility: undercover prisoner (snitch) L"Spread Propaganda", // facility: spread propaganda L"Spread Propaganda", // facility: spread propaganda (globally) - L"Gather Rumours", // facility: gather rumours + L"Gather Rumours", // facility: gather rumours L"Spread Propaganda", // spread propaganda L"Gather Rumours", // gather information L"Commanding Militia", // militia movement orders @@ -2661,7 +2661,7 @@ STR16 pLongAssignmentStrings[] = STR16 pContractStrings[] = { - L"Contract Options:", + L"Contract Options:", L"", // a blank line, required L"Offer One Day", // offer merc a one day contract extension L"Offer One Week", // 1 week @@ -2678,10 +2678,10 @@ STR16 pPOWStrings[] = STR16 pLongAttributeStrings[] = { - L"STRENGTH", - L"DEXTERITY", - L"AGILITY", - L"WISDOM", + L"STRENGTH", + L"DEXTERITY", + L"AGILITY", + L"WISDOM", L"MARKSMANSHIP", L"MEDICAL", L"MECHANICAL", @@ -2716,7 +2716,7 @@ STR16 pShortAttributeStrings[] = STR16 pUpperLeftMapScreenStrings[] = { - L"Assignment", // the mercs current assignment + L"Assignment", // the mercs current assignment L"Contract", // the contract info about the merc L"Health", // the health level of the current merc L"Morale", // the morale of the current merc @@ -2726,18 +2726,18 @@ STR16 pUpperLeftMapScreenStrings[] = STR16 pTrainingStrings[] = { - L"Practice", // tell merc to train self - L"Militia", // tell merc to train town + L"Practice", // tell merc to train self + L"Militia", // tell merc to train town L"Trainer", // tell merc to act as trainer - L"Student", // tell merc to be train by other + L"Student", // tell merc to be train by other }; STR16 pGuardMenuStrings[] = { L"Fire Rate:", // the allowable rate of fire for a merc who is guarding L" Aggressive Fire", // the merc can be aggressive in their choice of fire rates - L" Conserve Ammo", // conserve ammo - L" Refrain From Firing", // fire only when the merc needs to + L" Conserve Ammo", // conserve ammo + L" Refrain From Firing", // fire only when the merc needs to L"Other Options:", // other options available to merc L" Can Retreat", // merc can retreat L" Can Seek Cover", // merc is allowed to seek cover @@ -2769,7 +2769,7 @@ STR16 pAssignMenuStrings[] = L"Disease", // merc is a doctor doing diagnosis L"Patient", // the merc is receiving medical attention L"Vehicle", // the merc is in a vehicle - L"Repair", // the merc is repairing items + L"Repair", // the merc is repairing items L"Radio Scan", // the merc is scanning for patrols in neighbouring sectors L"Snitch", // anv: snitch actions L"Train", // the merc is training @@ -2792,7 +2792,7 @@ STR16 pMilitiaControlMenuStrings[] = L"Get down", L"Crouch", L"Take cover", - L"All: Attack", + L"All: Attack", L"All: Hold Position", L"All: Retreat", L"All: Come to me", @@ -2885,7 +2885,7 @@ STR16 pSnitchMenuStrings[] = { // snitch L"Team Informant", - L"Town Assignment", + L"Town Assignment", L"Cancel", }; @@ -3001,8 +3001,8 @@ STR16 pTrainingMenuStrings[] = { L"Practice", // train yourself L"Train workers", - L"Trainer", // train your teammates - L"Student", // be trained by an instructor + L"Trainer", // train your teammates + L"Student", // be trained by an instructor L"Cancel", // cancel this menu }; @@ -3040,13 +3040,13 @@ STR16 pPersonnelTitle[] = STR16 pPersonnelScreenStrings[] = { L"Health: ", // health of merc - L"Agility: ", + L"Agility: ", L"Dexterity: ", L"Strength: ", L"Leadership: ", L"Wisdom: ", L"Exp. Lvl: ", // experience level - L"Marksmanship: ", + L"Marksmanship: ", L"Mechanical: ", L"Explosives: ", L"Medical: ", @@ -3075,7 +3075,7 @@ STR16 pPersonnelRecordsHelpTexts[] = L"Admin soldiers: %d\n", L"Hostile groups: %d\n", L"Creatures: %d\n", - L"Tanks: %d\n", + L"Tanks: %d\n", L"Others: %d\n", L"Mercs: %d\n", @@ -3138,7 +3138,7 @@ STR16 pPersonnelRecordsHelpTexts[] = //These string correspond to enums used in by the SkillTrait enums in SoldierProfileType.h -STR16 gzMercSkillText[] = +STR16 gzMercSkillText[] = { // SANDRO - tweaked this L"No Skill", @@ -3156,12 +3156,12 @@ STR16 gzMercSkillText[] = L"Martial Arts", L"Knifing", L"Sniper", - L"Camouflage", //JA25: modified + L"Camouflage", //JA25: modified L"(Expert)", }; ////////////////////////////////////////////////////////// // SANDRO - added this -STR16 gzMercSkillTextNew[] = +STR16 gzMercSkillTextNew[] = { // Major traits L"No Skill", // 0 @@ -3173,7 +3173,7 @@ STR16 gzMercSkillTextNew[] = L"Hand to Hand", L"Deputy", L"Technician", - L"Paramedic", // 9 + L"Paramedic", // 9 // Minor traits L"Ambidextrous", // 10 L"Melee", @@ -3280,10 +3280,10 @@ STR16 pMapScreenMouseRegionHelpText[] = L"Plot Travel Route", L"Merc |Contract", L"Remove Merc", - L"Sleep", + L"Sleep", }; -// volumes of noises +// volumes of noises STR16 pNoiseVolStr[] = { @@ -3293,7 +3293,7 @@ STR16 pNoiseVolStr[] = L"VERY LOUD", }; -// types of noises +// types of noises STR16 pNoiseTypeStr[] = // OBSOLETE { @@ -3313,7 +3313,7 @@ STR16 pNoiseTypeStr[] = // OBSOLETE // Directions that are used to report noises -STR16 pDirectionStr[] = +STR16 pDirectionStr[] = { L"the NORTHEAST", L"the EAST", @@ -3325,7 +3325,7 @@ STR16 pDirectionStr[] = L"the NORTH", }; -// These are the different terrain types. +// These are the different terrain types. STR16 pLandTypeStrings[] = { @@ -3334,9 +3334,9 @@ STR16 pLandTypeStrings[] = L"Plains", L"Desert", L"Woods", - L"Forest", + L"Forest", L"Swamp", - L"Water", + L"Water", L"Hills", L"Impassable", L"River", //river from north to south @@ -3359,7 +3359,7 @@ STR16 pLandTypeStrings[] = L"Desert, SAM site", L"Tropical, SAM site", L"Meduna, SAM site", - + //These are descriptions for special sectors L"Cambria Hospital", L"Drassen Airport", @@ -3370,7 +3370,7 @@ STR16 pLandTypeStrings[] = L"Tixa Dungeon", //The basement of the Tixa Prison (J9) L"Creature Lair", //Any mine sector with creatures in it L"Orta Basement", //The basement of Orta (K4) - L"Tunnel", //The tunnel access from the maze garden in Meduna + L"Tunnel", //The tunnel access from the maze garden in Meduna //leading to the secret shelter underneath the palace L"Shelter", //The shelter underneath the queen's palace L"", //Unused @@ -3388,7 +3388,7 @@ STR16 gpStrategicString[] = L"The enemy offers you the chance to surrender.", //STR_ENEMY_SURRENDER_OFFER L"The enemy has captured your remaining unconscious mercs.", //STR_ENEMY_CAPTURED - //The text that goes on the autoresolve buttons + //The text that goes on the autoresolve buttons L"Retreat", //The retreat button //STR_AR_RETREAT_BUTTON L"Done", //The done button //STR_AR_DONE_BUTTON @@ -3400,7 +3400,7 @@ STR16 gpStrategicString[] = L"ENCOUNTER", //STR_AR_ENCOUNTER_HEADER L"Sector", //The Sector A9 part of the header //STR_AR_SECTOR_HEADER - //The battle ending conditions + //The battle ending conditions L"VICTORY!", //STR_AR_OVER_VICTORY L"DEFEAT!", //STR_AR_OVER_DEFEAT @@ -3420,13 +3420,13 @@ STR16 gpStrategicString[] = L"Time Elapsed", //STR_AR_TIME_ELAPSED, - //Labels for status of merc if retreating. (UPPERCASE) + //Labels for status of merc if retreating. (UPPERCASE) L"RETREATED", //STR_AR_MERC_RETREATED, L"RETREATING", //STR_AR_MERC_RETREATING, L"RETREAT", //STR_AR_MERC_RETREAT, - //PRE BATTLE INTERFACE STRINGS + //PRE BATTLE INTERFACE STRINGS //Goes on the three buttons in the prebattle interface. The Auto resolve button represents //a system that automatically resolves the combat for the player without having to do anything. //These strings must be short (two lines -- 6-8 chars per line) @@ -3461,7 +3461,7 @@ STR16 gpStrategicString[] = L"h", //One letter abbreviation of hour //TACTICAL PLACEMENT USER INTERFACE STRINGS - //The four buttons + //The four buttons L"Clear", L"Spread", @@ -3470,7 +3470,7 @@ STR16 gpStrategicString[] = //The help text for the four buttons. Use \n to denote new line (just like enter). - L"|Clears all the mercs' positions, \nand allows you to re-enter them manually.", + L"|Clears all the mercs' positions, \nand allows you to re-enter them manually.", L"Randomly |spreads your mercs out \neach time it's pressed.", L"Allows you to select where you wish to |group your mercs.", L"Click this button when you're finished \nchoosing your mercs' positions. (|E|n|t|e|r)", @@ -3489,7 +3489,7 @@ STR16 gpStrategicString[] = //This message is for mercs arriving in sectors. Ex: Red has arrived in sector A9. //Don't uppercase first character, or add spaces on either end. - L"has arrived in sector", + L"has arrived in sector", //These entries are for button popup help text for the prebattle interface. All popup help //text supports the use of \n to denote new line. Do not use spaces before or after the \n. @@ -3499,7 +3499,7 @@ STR16 gpStrategicString[] = L"|Retreat group to their previous sector.", //singular version L"|Retreat all groups to their previous sectors.", //multiple groups with same previous sector - //various popup messages for battle conditions. + //various popup messages for battle conditions. //%c%d is the sector -- ex: A9 L"Enemies attack your militia in sector %c%d.", @@ -3522,7 +3522,7 @@ STR16 gpStrategicString[] = L"\nBreath regeneration per hour: %d", // STR_BREATH_REGEN_SLEEP - L"Zombies", + L"Zombies", L"Bandits", L"BLOODCAT ATTACK", L"ZOMBIE ATTACK", @@ -3532,13 +3532,13 @@ STR16 gpStrategicString[] = L"Bandits attack and kill %d civilians in sector %s.", }; -STR16 gpGameClockString[] = +STR16 gpGameClockString[] = { //This is the day represented in the game clock. Must be very short, 4 characters max. - L"Day", + L"Day", }; -//When the merc finds a key, they can get a description of it which +//When the merc finds a key, they can get a description of it which //tells them where and when they found it. STR16 sKeyDescriptionStrings[2] = { @@ -3552,8 +3552,8 @@ CHAR16 gWeaponStatsDesc[][ 20 ] = { // HEADROCK: Changed this for Extended Description project L"Status:", - L"Weight:", - L"AP Costs", + L"Weight:", + L"AP Costs", L"Rng:", // Range L"Dam:", // Damage L"Amount:", // Number of bullets left in a magazine @@ -3562,7 +3562,7 @@ CHAR16 gWeaponStatsDesc[][ 20 ] = L"=", //Lal: additional strings for tooltips L"Accuracy:", //9 - L"Range:", //10 + L"Range:", //10 L"Damage:", //11 L"Weight:", //12 L"Stun Damage:",//13 @@ -3689,7 +3689,7 @@ CHAR16 gMoneyStatsDesc[][ 14 ] = }; //The health of various creatures, enemies, characters in the game. The numbers following each are for comment -//only, but represent the precentage of points remaining. +//only, but represent the precentage of points remaining. CHAR16 zHealthStr[][13] = { @@ -3705,11 +3705,11 @@ CHAR16 zHealthStr[][13] = STR16 gzHiddenHitCountStr[1] = { - L"?", + L"?", }; -STR16 gzMoneyAmounts[6] = -{ +STR16 gzMoneyAmounts[6] = +{ L"$1000", L"$100", L"$10", @@ -3718,13 +3718,13 @@ STR16 gzMoneyAmounts[6] = L"Withdraw", }; -// short words meaning "Advantages" for "Pros" and "Disadvantages" for "Cons." -CHAR16 gzProsLabel[10] = +// short words meaning "Advantages" for "Pros" and "Disadvantages" for "Cons." +CHAR16 gzProsLabel[10] = { L"Pros:", }; -CHAR16 gzConsLabel[10] = +CHAR16 gzConsLabel[10] = { L"Cons:", }; @@ -3732,11 +3732,11 @@ CHAR16 gzConsLabel[10] = //Conversation options a player has when encountering an NPC CHAR16 zTalkMenuStrings[6][ SMALL_STRING_LENGTH ] = { - L"Come Again?", //meaning "Repeat yourself" + L"Come Again?", //meaning "Repeat yourself" L"Friendly", //approach in a friendly L"Direct", //approach directly - let's get down to business L"Threaten", //approach threateningly - talk now, or I'll blow your face off - L"Give", + L"Give", L"Recruit", }; @@ -3749,7 +3749,7 @@ CHAR16 zDealerStrings[4][ SMALL_STRING_LENGTH ]= L"Repair", }; -CHAR16 zDialogActions[1][ SMALL_STRING_LENGTH ] = +CHAR16 zDialogActions[1][ SMALL_STRING_LENGTH ] = { L"Done", }; @@ -3799,14 +3799,14 @@ CHAR16 TacticalStr[][ MED_STRING_LENGTH ] = { L"Air Raid", L"Apply first aid automatically?", - + // CAMFIELD NUKE THIS and add quote #66. - + L"%s notices that items are missing from the shipment.", - + // The %s is a string from pDoorTrapStrings - - L"The lock has %s.", + + L"The lock has %s.", L"There's no lock.", L"Success!", L"Failure.", @@ -3856,7 +3856,7 @@ CHAR16 TacticalStr[][ MED_STRING_LENGTH ] = // In the next 3 strings, %s is a name L"%s can't change to that stance here.", - L"%s can't have first aid done here.", + L"%s can't have first aid done here.", L"%s doesn't need first aid.", L"Can't move there.", L"Your team's full. No room for a recruit.", //there's no room for a recruit on the player's team @@ -3877,11 +3877,11 @@ CHAR16 TacticalStr[][ MED_STRING_LENGTH ] = L"Hire %s for %s per day?", - // This line is used repeatedly to ask player if they wish to participate in a boxing match. + // This line is used repeatedly to ask player if they wish to participate in a boxing match. L"You want to fight?", - // In the next string, the first %s is an item name and the + // In the next string, the first %s is an item name and the // second %s is an amount of money (including $ sign) L"Buy %s for %s?", @@ -3914,15 +3914,15 @@ CHAR16 TacticalStr[][ MED_STRING_LENGTH ] = L"|Burst Mode", L"|Look/Turn", L"Health: %d/%d\nEnergy: %d/%d\nMorale: %s", - L"Heh?", //this means "what?" - L"Cont", //an abbrieviation for "Continued" + L"Heh?", //this means "what?" + L"Cont", //an abbrieviation for "Continued" L"Mute off for %s.", L"Mute on for %s.", L"Health: %d/%d\nFuel: %d/%d", L"Exit Vehicle" , L"Change Squad ( |S|h|i|f|t |S|p|a|c|e )", L"Drive", - L"N/A", //this is an acronym for "Not Applicable." + L"N/A", //this is an acronym for "Not Applicable." L"Use ( Hand To Hand )", L"Use ( Firearm )", L"Use ( Blade )", @@ -3970,7 +3970,7 @@ CHAR16 TacticalStr[][ MED_STRING_LENGTH ] = L"Invalid fingerprint ID. Weapon non-functional", L"Target aquired", L"Path Blocked", - L"Deposit/Withdraw Money", //Help text over the $ button on the Single Merc Panel + L"Deposit/Withdraw Money", //Help text over the $ button on the Single Merc Panel L"No one needs first aid.", L"Jam.", // Short form of JAMMED, for small inv slots L"Can't get there.", // used ( now ) for when we click on a cliff @@ -4003,7 +4003,7 @@ CHAR16 TacticalStr[][ MED_STRING_LENGTH ] = L"Set detonation frequency (1 - 4) and defusing frequency (A - D):", L"Set detonation time in turns (1 - 4) and defusing frequency (A - D):", L"Select tripwire hierarchy (1 - 4) and network (A - D):", - + // added by Flugente to display food status L"Health: %d/%d\nEnergy: %d/%d\nMorale: %s\nWater: %d%s\nFood: %d%s", @@ -4059,7 +4059,7 @@ CHAR16 TacticalStr[][ MED_STRING_LENGTH ] = L"Mask", L"NVG", L"Item", - + L"This feature works only with New Inventory System", L"No item in your main hand", L"Nowhere to place item from main hand", @@ -4087,7 +4087,7 @@ STR16 pExitingSectorHelpText[] = //If you attempt to leave a sector when you have multiple squads in a hostile sector. L"This sector is enemy occupied and you can't leave mercs here.\nYou must deal with this situation before loading any other sectors.", - //Because you only have one squad in the sector, and the "move all" option is checked, the "go to sector" option is locked to on. + //Because you only have one squad in the sector, and the "move all" option is checked, the "go to sector" option is locked to on. //The helptext explains why it is locked. L"By moving your remaining mercs out of this sector,\nthe adjacent sector will immediately be loaded.", L"By moving your remaining mercs out of this sector,\nyou will be placed automatically in the map screen\nas it will take time for your mercs to travel.", @@ -4124,7 +4124,7 @@ STR16 pExitingSectorHelpText[] = -STR16 pRepairStrings[] = +STR16 pRepairStrings[] = { L"Items", // tell merc to repair items in inventory L"SAM Site", // tell merc to repair SAM site - SAM is an acronym for Surface to Air Missile @@ -4134,7 +4134,7 @@ STR16 pRepairStrings[] = // NOTE: combine prestatbuildstring with statgain to get a line like the example below. -// "John has gained 3 points of marksmanship skill." +// "John has gained 3 points of marksmanship skill." STR16 sPreStatBuildString[] = { @@ -4168,13 +4168,13 @@ STR16 pHelicopterEtaStrings[] = L" Safe: ", // distance to travel to destination L" Unsafe:", // distance to return from destination to airport L"Total Cost: ", // total cost of trip by helicopter - L"ETA: ", // ETA is an acronym for "estimated time of arrival" - L"Helicopter is low on fuel and must land in hostile territory!", // warning that the sector the helicopter is going to use for refueling is under enemy control -> + L"ETA: ", // ETA is an acronym for "estimated time of arrival" + L"Helicopter is low on fuel and must land in hostile territory!", // warning that the sector the helicopter is going to use for refueling is under enemy control -> L"Passengers: ", L"Select Skyrider or the Arrivals Drop-off?", L"Skyrider", L"Arrivals", - L"Helicopter is seriously damaged and must land in hostile territory!", // warning that the sector the helicopter is going to use for refueling is under enemy control -> + L"Helicopter is seriously damaged and must land in hostile territory!", // warning that the sector the helicopter is going to use for refueling is under enemy control -> L"Helicopter will now return straight to base, do you want to drop down passengers before?", L"Remaining Fuel:", L"Dist. To Refuel Site:", @@ -4206,7 +4206,7 @@ STR16 gsLoyalString[] = STR16 gsUndergroundString[] = { - L"can't get travel orders underground.", + L"can't get travel orders underground.", }; STR16 gsTimeStrings[] = @@ -4346,7 +4346,7 @@ STR16 pMapScreenFastHelpTextList[] = STR16 pMovementMenuStrings[] = { - L"Move Mercs In Sector", // title for movement box + L"Move Mercs In Sector", // title for movement box L"Plot Travel Route", // done with movement menu, start plotting movement L"Cancel", // cancel this menu L"Other", // title for group of mercs not on squads nor in vehicles @@ -4488,7 +4488,7 @@ CHAR16 pSenderNameList[500][128] = L"MD", L"Meltdown", //---------- - L"M.I.S. Insurance", + L"M.I.S. Insurance", L"Bobby Rays", L"Kingpin", L"John Kulba", @@ -4504,7 +4504,7 @@ STR16 pTraverseStrings[] = L"Next", }; -// new mail notify string +// new mail notify string STR16 pNewMailStrings[] = { @@ -4571,7 +4571,7 @@ STR16 pFinanceHeaders[] = L"Transaction", // transaction type - see TransactionText below L"Balance", // balance at this point in time L"Page", // page number - L"Day(s)", // the day(s) of transactions this page displays + L"Day(s)", // the day(s) of transactions this page displays }; @@ -4579,21 +4579,21 @@ STR16 pTransactionText[] = { L"Accrued Interest", // interest the player has accumulated so far L"Anonymous Deposit", - L"Transaction Fee", + L"Transaction Fee", L"Hired", // Merc was hired L"Bobby Ray Purchase", // Bobby Ray is the name of an arms dealer L"Settled Accounts at M.E.R.C.", L"Medical Deposit for %s", // medical deposit for merc L"IMP Profile Analysis", // IMP is the acronym for International Mercenary Profiling - L"Purchased Insurance for %s", + L"Purchased Insurance for %s", L"Reduced Insurance for %s", L"Extended Insurance for %s", // johnny contract extended - L"Canceled Insurance for %s", + L"Canceled Insurance for %s", L"Insurance Claim for %s", // insurance claim for merc L"a day", // merc's contract extended for a day L"1 week", // merc's contract extended for a week L"2 weeks", // ... for 2 weeks - L"Mine income", + L"Mine income", L"", //String nuked L"Purchased Flowers", L"Full Medical Refund for %s", @@ -4624,7 +4624,7 @@ STR16 pTransactionAlternateText[] = L"Ext. %s contract by 2 weeks.", }; -// helicopter pilot payment +// helicopter pilot payment STR16 pSkyriderText[] = { @@ -4642,7 +4642,7 @@ STR16 pSkyriderText[] = STR16 pMoralStrings[] = { - L"Great", + L"Great", L"Good", L"Stable", L"Poor", @@ -4653,8 +4653,8 @@ STR16 pMoralStrings[] = // Mercs equipment has now arrived and is now available in Omerta or Drassen. STR16 pLeftEquipmentString[] = -{ - L"%s's equipment is now available in Omerta (A9).", +{ + L"%s's equipment is now available in Omerta (A9).", L"%s's equipment is now available in Drassen (B13).", }; @@ -4669,7 +4669,7 @@ STR16 pMapScreenStatusStrings[] = L"Fuel", // the fuel level of the current vehicle (its "energy") L"Poison", // for display of poisoning L"Water", // drink level - L"Food", // food level + L"Food", // food level }; @@ -4692,7 +4692,7 @@ STR16 pTrashItemText[] = }; -STR16 pMapErrorString[] = +STR16 pMapErrorString[] = { L"Squad can't move with a sleeping merc on it.", @@ -4700,7 +4700,7 @@ STR16 pMapErrorString[] = L"Move the squad above ground first.", L"Movement orders? It's a hostile sector!", L"Mercs must be assigned to a squad or vehicle in order to travel.", - L"You don't have any team members yet.", // you have no members, can't do anything + L"You don't have any team members yet.", // you have no members, can't do anything L"Merc can't comply.", // merc can't comply with your order //6-10 L"needs an escort to move. Place him on a squad with one.", // merc can't move unescorted .. for a male @@ -4712,7 +4712,7 @@ STR16 pMapErrorString[] = L"Movement orders? There's a battle going on!", L"You have been ambushed by bloodcats in sector %s!", L"You have just entered what appears to be a bloodcat lair in sector %s!", // HEADROCK HAM 3.6: Added argument. - L"", + L"", L"The SAM site in %s has been taken over.", //16-20 L"The mine in %s has been taken over. Your daily income has been reduced to %s per day.", @@ -4854,13 +4854,13 @@ STR16 pImpButtonText[] = L"Voice %d", // the voice selection L"Done", // done profiling L"Start Over", // start over profiling - L"Yes, I choose the highlighted answer.", - L"Yes", + L"Yes, I choose the highlighted answer.", + L"Yes", L"No", L"Finished", // finished answering questions L"Prev", // previous question..abbreviated form L"Next", // next question - L"YES, I AM.", // yes, I am certain + L"YES, I AM.", // yes, I am certain L"NO, I WANT TO START OVER.", // no, I want to start over the profiling process L"YES, I DO.", L"NO", @@ -4932,7 +4932,7 @@ STR16 pHistoryStrings[] = L"%s was hired from M.E.R.C.", // merc was hired from the aim site L"%s died.", // merc was killed L"Settled Accounts at M.E.R.C.", // paid outstanding bills at MERC - L"Accepted Assignment From Enrico Chivaldori", + L"Accepted Assignment From Enrico Chivaldori", //6-10 L"IMP Profile Generated", L"Purchased Insurance Contract for %s.", // insurance contract purchased @@ -5110,14 +5110,14 @@ STR16 sATMText[ ]= L"Amount must be a multiple of $10", // transfer amount must be a multiple of $10 }; -// Web error messages. Please use foreign language equivilant for these messages. +// Web error messages. Please use foreign language equivilant for these messages. // DNS is the acronym for Domain Name Server // URL is the acronym for Uniform Resource Locator STR16 pErrorStrings[] = { L"Error", - L"Server does not have DNS entry.", + L"Server does not have DNS entry.", L"Check URL address and try again.", L"OK", L"Intermittent Connection to Host. Expect longer transfer times.", @@ -5157,7 +5157,7 @@ STR16 pWebPagesTitles[] = L"Bobby Ray's - Guns", L"Bobby Ray's - Ammo", L"Bobby Ray's - Armor", - L"Bobby Ray's - Misc", //misc is an abbreviation for miscellaneous + L"Bobby Ray's - Misc", //misc is an abbreviation for miscellaneous L"Bobby Ray's - Used", L"Bobby Ray's - Mail Order", L"I.M.P.", @@ -5343,8 +5343,8 @@ CHAR16 LargeTacticalStr[][ LARGE_STRING_LENGTH ] = //Insurance Contract.c //The text on the buttons at the bottom of the screen. -STR16 InsContractText[] = -{ +STR16 InsContractText[] = +{ L"Previous", L"Next", L"Accept", @@ -5356,9 +5356,9 @@ STR16 InsContractText[] = //Insurance Info // Text on the buttons on the bottom of the screen -STR16 InsInfoText[] = -{ - L"Previous", +STR16 InsInfoText[] = +{ + L"Previous", L"Next", }; @@ -5366,7 +5366,7 @@ STR16 InsInfoText[] = //For use at the M.E.R.C. web site. Text relating to the player's account with MERC -STR16 MercAccountText[] = +STR16 MercAccountText[] = { // Text on the buttons on the bottom of the screen L"Authorize", @@ -5382,7 +5382,7 @@ STR16 MercAccountText[] = }; // Merc Account Page buttons -STR16 MercAccountPageText[] = +STR16 MercAccountPageText[] = { // Text on the buttons on the bottom of the screen L"Previous", @@ -5479,7 +5479,7 @@ STR16 sFuneralString[] = // Text for the florist Home page -STR16 sFloristText[] = +STR16 sFloristText[] = { //Text on the button on the bottom of the page @@ -5509,7 +5509,7 @@ STR16 sFloristText[] = //Florist OrderForm -STR16 sOrderFormText[] = +STR16 sOrderFormText[] = { //Text on the buttons @@ -5534,7 +5534,7 @@ STR16 sOrderFormText[] = L"Due to the size of gift cards, your message can be no longer than 75 characters.", L"...or select from one of our", - L"STANDARDIZED CARDS", + L"STANDARDIZED CARDS", L"Billing Information",//20 //The text that goes beside the area where the user can enter their name @@ -5574,7 +5574,7 @@ STR16 sFloristCards[] = // Text for Bobby Ray's Mail Order Site -STR16 BobbyROrderFormText[] = +STR16 BobbyROrderFormText[] = { L"Order Form", //Title of the page L"Qty", // The number of items ordered @@ -5583,9 +5583,9 @@ STR16 BobbyROrderFormText[] = L"Unit Price", // the item's weight L"Total", //5 // The total price of all of items of the same type L"Sub-Total", // The sub total of all the item totals added - L"S&H (See Delivery Loc.)", // S&H is an acronym for Shipping and Handling + L"S&H (See Delivery Loc.)", // S&H is an acronym for Shipping and Handling L"Grand Total", // The grand total of all item totals + the shipping and handling - L"Delivery Location", + L"Delivery Location", L"Shipping Speed", //10 // See below L"Cost (per %s.)", // The cost to ship the items L"Overnight Express", // Gets deliverd the next day @@ -5601,7 +5601,7 @@ STR16 BobbyROrderFormText[] = L"Are you sure you want to send this order to %s?", // A popup that asks if the city selected is the correct one L"Package Weight**", // Displays the weight of the package L"** Min. Wt.", // Disclaimer states that there is a minimum weight for the package - L"Shipments", + L"Shipments", }; STR16 BobbyRFilter[] = @@ -5661,15 +5661,15 @@ STR16 BobbyRFilter[] = // This text is used when on the various Bobby Ray Web site pages that sell items -STR16 BobbyRText[] = +STR16 BobbyRText[] = { L"To Order", // Title // instructions on how to order - L"Click on the item(s). For more than one, keep on clicking. Right click for less. Once you've selected all you'd like to buy, go on to the order form.", + L"Click on the item(s). For more than one, keep on clicking. Right click for less. Once you've selected all you'd like to buy, go on to the order form.", //Text on the buttons to go the various links - L"Previous Items", // + L"Previous Items", // L"Guns", //3 L"Ammo", //4 L"Armor", //5 @@ -5679,7 +5679,7 @@ STR16 BobbyRText[] = L"ORDER FORM", L"Home", //10 - //The following 2 lines are used on the Ammunition page. + //The following 2 lines are used on the Ammunition page. //They are used for help text to display how many items the player's merc has //that can use this type of ammo @@ -5692,7 +5692,7 @@ STR16 BobbyRText[] = L"Cal:", // the caliber of the gun L"Size:", // number of rounds of ammo the Magazine can hold L"Rng:", // The range of the gun - L"Dam:", // Damage of the weapon + L"Dam:", // Damage of the weapon L"ROF:", // Weapon's Rate Of Fire, acronym ROF L"AP:", // Weapon's Action Points, acronym AP L"Stun:", // Weapon's Stun Damage @@ -5707,7 +5707,7 @@ STR16 BobbyRText[] = L"* %% Functional", // if the item is damaged, displays the percent function of the item //Popup that tells the player that they can only order 10 items at a time - + L"Darn! This on-line order form will only accept " ,//First part L" items per order. If you're looking to order more stuff (and we hope you are), kindly make a separate order and accept our apologies.", //Second part @@ -5754,11 +5754,11 @@ STR16 AimSortText[] = { L"A.I.M. Members", // Title // Title for the way to sort - L"Sort By:", + L"Sort By:", // sort by... - L"Price", + L"Price", L"Experience", L"Marksmanship", L"Mechanical", @@ -5793,7 +5793,7 @@ STR16 AimPolicyText[] = // The text on the buttons at the bottom of the page L"Previous Page", - L"AIM HomePage", + L"AIM HomePage", L"Policy Index", L"Next Page", L"Disagree", @@ -5813,7 +5813,7 @@ STR16 AimMemberText[] = L"to Contact Merc.", L"Right Click", L"for Mug Shot Index.", -}; +}; //Aim Member.c //The page in which the players hires AIM mercenaries @@ -5822,9 +5822,9 @@ STR16 CharacterInfo[] = { // The various attributes of the merc - L"Health", - L"Agility", - L"Dexterity", + L"Health", + L"Agility", + L"Dexterity", L"Strength", L"Leadership", L"Wisdom", @@ -5836,13 +5836,13 @@ STR16 CharacterInfo[] = // the contract expenses' area - L"Fee", - L"Contract", - L"one day", + L"Fee", + L"Contract", + L"one day", L"one week", L"two weeks", - // text for the buttons that either go to the previous merc, + // text for the buttons that either go to the previous merc, // start talking to the merc, or go to the next merc L"Previous", @@ -5873,11 +5873,11 @@ STR16 VideoConfercingText[] = //Text on the buttons to select the length of time the merc can be hired - L"One Day", + L"One Day", L"One Week", L"Two Weeks", - //Text on the buttons to determine if you want the merc to come with the equipment + //Text on the buttons to determine if you want the merc to come with the equipment L"No Equipment", L"Buy Equipment", @@ -5888,12 +5888,12 @@ STR16 VideoConfercingText[] = L"CANCEL", // go back to the previous menu L"HIRE", // go to menu in which you can hire the merc L"HANG UP", // stops talking with the merc - L"OK", - L"LEAVE MESSAGE", // if the merc is not there, you can leave a message + L"OK", + L"LEAVE MESSAGE", // if the merc is not there, you can leave a message //Text on the top of the video conference popup - L"Video Conferencing with", + L"Video Conferencing with", L"Connecting. . .", L"with medical" // Displays if you are hiring the merc with the medical deposit @@ -5914,7 +5914,7 @@ STR16 AimPopUpText[] = // if the merc is not available, one of the following is displayed over the merc's face - L"On Assignment", + L"On Assignment", L"Please Leave Message", L"Deceased", @@ -5947,7 +5947,7 @@ STR16 AimHistoryText[] = // Text on the buttons at the bottom of the page L"Previous Page", - L"Home", + L"Home", L"A.I.M. Alumni", L"Next Page", }; @@ -6023,7 +6023,7 @@ STR16 AimAlumniText[] = STR16 AimScreenText[] = { // AIM disclaimers - + L"A.I.M. and the A.I.M. logo are registered trademarks in most countries.", L"So don't even think of trying to copy us.", L"Copyright 2005 A.I.M., Ltd. All rights reserved.", //1.13 modified to 2005 @@ -6054,10 +6054,10 @@ STR16 AimBottomMenuText[] = //ShopKeeper Interface -// The shopkeeper interface is displayed when the merc wants to interact with +// The shopkeeper interface is displayed when the merc wants to interact with // the various store clerks scattered through out the game. -STR16 SKI_Text[ ] = +STR16 SKI_Text[ ] = { L"MERCHANDISE IN STOCK", //Header for the merchandise available L"PAGE", //The current store inventory page being displayed @@ -6101,8 +6101,8 @@ STR16 SkiAtmText[] = //Shopkeeper Interface -STR16 gzSkiAtmText[] = -{ +STR16 gzSkiAtmText[] = +{ // Text on the bank machine panel that.... L"Select Type", // tells the user to select either to give or take from the merc @@ -6131,7 +6131,7 @@ STR16 SkiMessageBoxText[] = //OptionScreen.c -STR16 zOptionsText[] = +STR16 zOptionsText[] = { //button Text L"Save Game", @@ -6153,8 +6153,8 @@ STR16 zOptionsText[] = }; -//SaveLoadScreen -STR16 zSaveLoadText[] = +//SaveLoadScreen +STR16 zSaveLoadText[] = { L"Save Game", L"Load Game", @@ -6195,7 +6195,7 @@ STR16 zSaveLoadText[] = //The first %d is a number that contains the amount of free space on the users hard drive, //the second is the recommended amount of free space. - L"You are running low on disk space. You only have %d Megs free and Jagged should have at least %d Megs free.", + L"You are running low on disk space. You only have %d Megs free and Jagged should have at least %d Megs free.", L"Saving", //When saving a game, a message box with this string appears on the screen @@ -6228,9 +6228,9 @@ STR16 zMarksMapScreenText[] = L"Map Level", L"You have no militia. You need to train town residents in order to have a town militia.", L"Daily Income", - L"Merc has life insurance", - L"%s isn't tired.", - L"%s is on the move and can't sleep", + L"Merc has life insurance", + L"%s isn't tired.", + L"%s is on the move and can't sleep", L"%s is too tired, try a little later.", L"%s is driving.", L"Squad can't move with a sleeping merc on it.", @@ -6240,18 +6240,18 @@ STR16 zMarksMapScreenText[] = L"%s insurance premium will cost %s for %d extra day(s). Do you want to pay?", L"Sector Inventory", L"Merc has a medical deposit.", - + // other items - L"Medics", // people acting a field medics and bandaging wounded mercs - L"Patients", // people who are being bandaged by a medic - L"Done", // Continue on with the game after autobandage is complete - L"Stop", // Stop autobandaging of patients by medics now - L"Sorry. This option has been disabled in this demo.", // informs player this option/button has been disabled in the demo + L"Medics", // people acting a field medics and bandaging wounded mercs + L"Patients", // people who are being bandaged by a medic + L"Done", // Continue on with the game after autobandage is complete + L"Stop", // Stop autobandaging of patients by medics now + L"Sorry. This option has been disabled in this demo.", // informs player this option/button has been disabled in the demo L"%s doesn't have a repair kit.", L"%s doesn't have a medical kit.", L"There aren't enough people willing to be trained right now.", L"%s is full of militia.", - L"Merc has a finite contract.", + L"Merc has a finite contract.", L"Merc's contract is not insured", L"Map Overview", // 24 @@ -6287,7 +6287,7 @@ STR16 pMilitiaConfirmStrings[] = L"You cannot afford the $%d to train town militia here.", L"%s needs a loyalty of %d percent for you to be able to continue training militia.", - L"You cannot train the militia in %s any further.", + L"You cannot train the militia in %s any further.", L"liberate more town sectors", L"liberate new town sectors", @@ -6299,19 +6299,19 @@ STR16 pMilitiaConfirmStrings[] = }; //Strings used in the popup box when withdrawing, or depositing money from the $ sign at the bottom of the single merc panel -STR16 gzMoneyWithdrawMessageText[] = +STR16 gzMoneyWithdrawMessageText[] = { L"You can only withdraw up to $20,000 at a time.", L"Are you sure you want to deposit the %s into your account?", }; -STR16 gzCopyrightText[] = +STR16 gzCopyrightText[] = { L"Copyright (C) 1999 Sir-tech Canada Ltd. All rights reserved.", }; //option Text -STR16 zOptionsToggleText[] = +STR16 zOptionsToggleText[] = { L"Speech", L"Mute Confirmations", @@ -6324,7 +6324,7 @@ STR16 zOptionsToggleText[] = L"Show Movement Path", L"Show Misses", L"Real Time Confirmation", - L"Display Sleep/Wake Notifications", + L"Sleep/Wake Notifications", L"Use Metric System", L"Merc Lights during Movement", L"Snap Cursor to Mercs", @@ -6352,8 +6352,9 @@ STR16 zOptionsToggleText[] = L"Stat Progress Bars", // Show progress towards stat increase L"Alternate Strategy Map Colors", // Change color scheme of Strategic Map L"Alternate Bullet Graphics", // Show alternate bullet graphics (tracers) + L"Use Logical Bodytypes", L"Show Merc Ranks", // shows mercs ranks - L"Show Face Gear Graphics", + L"Show Face Gear Graphics", L"Show Face Gear Icons", L"Disable Cursor Swap", // Disable Cursor Swap L"Quiet Training", // Madd: mercs don't say quotes while training @@ -6376,7 +6377,7 @@ STR16 zOptionsToggleText[] = L"Debug Options in other builds", // allow debugging in release or mapeditor L"DEBUG Render Option group", // an example option that will show/hide other options L"Render Mouse Regions", // an example of a DEBUG build option - L"-----------------", // an example options screen options divider (pure text) + L"-----------------", // an example options screen options divider (pure text) // this is THE LAST option that exists (debug the options screen, doesnt do anything, except exist) L"THE_LAST_OPTION", @@ -6416,7 +6417,7 @@ STR16 zOptionsScreenHelpText[] = //show misses L"Turn ON to have the game show you where your bullets ended up when you \"miss\".", - + //Real Time Confirmation L"When ON, an additional \"safety\" click will be required for movement in Real-time.", @@ -6435,7 +6436,7 @@ STR16 zOptionsScreenHelpText[] = //snap cursor to the door L"When ON, moving the cursor near a door will automatically position the cursor over the door.", - //glow items + //glow items L"When ON, Items continuously glow. (|C|t|r|l+|A|l|t+|I)", //toggle tree tops @@ -6466,6 +6467,7 @@ STR16 zOptionsScreenHelpText[] = L"When ON, shows character progress towards gaining levels.", L"When ON, the strategic map will be colored differently based on exploration.", L"When ON, alternate bullet graphics will be shown when you shoot.", + L"When ON, mercenary body graphic can change along with equipped gear.", L"When ON, ranks will be displayed before merc names in the strategic view.", L"When ON, equipped face gear will be shown on the merc portraits.", L"When ON, icons for the equipped face gear will be shown on the merc portraits in the lower right corner.", @@ -6491,7 +6493,7 @@ STR16 zOptionsScreenHelpText[] = L"Allows debug options in release or mapeditor builds", // allow debugging in release or mapeditor L"Toggle to display debugging render options", // an example option that will show/hide other options L"Attempts to display slash-rects around mouse regions", // an example of a DEBUG build option - L"(text not rendered)TOPTION_DEBUG_MODE_OPTIONS_END", // an example options screen options divider (pure text) + L"(text not rendered)TOPTION_DEBUG_MODE_OPTIONS_END", // an example options screen options divider (pure text) // this is THE LAST option that exists (debug the options screen, doesnt do anything, except exist) L"TOPTION_LAST_OPTION", @@ -6509,7 +6511,7 @@ STR16 gzGIOScreenText[] = L"Game Style", L"Realistic", L"Sci Fi", -#endif +#endif L"Platinum", L"Available Arsenal", // changed by SANDRO L"Tons of Guns", @@ -6557,7 +6559,7 @@ STR16 gzGIOScreenText[] = L"Number of Terrorists", L"Random", L"All", -#endif +#endif L"Secret Weapon Caches", L"Random", L"All", @@ -6571,7 +6573,7 @@ STR16 gzGIOScreenText[] = L"Old / Old", L"New / Old", L"New / New", - + // Squad Size L"Max. Squad Size", L"6", @@ -6579,7 +6581,7 @@ STR16 gzGIOScreenText[] = L"10", //L"Faster Bobby Ray Shipments", L"Inventory Manipulation Costs AP", - + L"New Chance to Hit System", L"Improved Interrupt System", L"Merc Story Backgrounds", @@ -6608,7 +6610,7 @@ STR16 gzMPJScreenText[] = L"Ping", L"You must enter a player name.", L"You must enter a valid server IP address. For example: 84.114.195.239", - L"You must enter a valid Server Port between 1 and 65535.", + L"You must enter a valid Server Port between 1 and 65535.", }; STR16 gzMPJHelpText[] = @@ -6621,7 +6623,7 @@ STR16 gzMPJHelpText[] = L"Be sure that the Port (UDP, TCP) is forwarded on your Router. For more information see: http://portforward.com", L"You have to send (via IRC, ICQ, etc) your external IP (http://www.whatismyip.com) and the Port number to the other players.", L"Click on 'Host' to host a new Multiplayer Game.", - + L"JOIN", L"The host has to send (via IRC, ICQ, etc) you the external IP and the Port number.", L"Enter the external IP and the Port number from the host.", @@ -6706,7 +6708,7 @@ STR16 gzMPHScreenText[] = STR16 pDeliveryLocationStrings[] = { - L"Austin", //Austin, Texas, USA + L"Austin", //Austin, Texas, USA L"Baghdad", //Baghdad, Iraq (Suddam Hussein's home) L"Drassen", //The main place in JA2 that you can receive items. The other towns are dummy names... L"Hong Kong", //Hong Kong, Hong Kong @@ -6749,7 +6751,7 @@ STR16 pIMPFinishStrings[ ]= // the strings for imp voices screen STR16 pIMPVoicesStrings[] = { - L"Voice", + L"Voice", }; STR16 pDepartedMercPortraitStrings[ ]= @@ -6814,7 +6816,7 @@ STR16 pMessageStrings[] = L"Opened", L"Closed", L"You are running low on disk space. You only have %sMB free and Jagged Alliance 2 v1.13 requires %sMB.", - L"Hired %s from AIM", + L"Hired %s from AIM", L"%s has caught %s.", //'Merc name' has caught 'item' -- let SirTech know if name comes after item. L"%s has taken %s.", //'Merc name' has taken 'item name' L"%s has no medical skill",//40 'Merc name' has no medical skill. @@ -6825,7 +6827,7 @@ STR16 pMessageStrings[] = //When firing heavier weapons in close quarters, you may not have enough room to do so. L"There is no room to fire from here.", - + //Can't change stance due to objects in the way... L"Cannot change stance at this time.", @@ -6851,13 +6853,13 @@ STR16 pMessageStrings[] = L"%s on stealth mode.", L"%s off stealth mode.", - //Wireframes are shown through buildings to reveal doors and windows that can't otherwise be seen in + //Wireframes are shown through buildings to reveal doors and windows that can't otherwise be seen in //an isometric engine. You can toggle this mode freely in the game. L"Extra Wireframes On", L"Extra Wireframes Off", //These are used in the cheat modes for changing levels in the game. Going from a basement level to - //an upper level, etc. + //an upper level, etc. L"Can't go up from this level...", L"There are no lower levels...", // 60 L"Entering basement level %d...", @@ -6892,7 +6894,7 @@ STR16 pMessageStrings[] = L"..\\SavedGames\\MP_SavedGames", //The name of the directory where games are saved L"Client", L"You cannot use the Old Inventory and the New Attachment System at the same time.", // 90 - + L"Auto Save #", //91 // Text des Auto Saves im Load Screen mit ID L"This slot is reserved for Auto Saves, which can be enabled/disabled (AUTO_SAVE_EVERY_N_HOURS) in the ja2_options.ini.", //92 // The text, when the user clicks on the save screen on an auto save L"Empty Auto Save Slot #", //93 // The text, when the auto save slot (1 - 5) is empty (not saved yet) @@ -6954,7 +6956,7 @@ STR16 pMapScreenJustStartedHelpText[] = #endif }; -STR16 pAntiHackerString[] = +STR16 pAntiHackerString[] = { L"Error. Missing or corrupted file(s). Game will exit now.", }; @@ -6998,7 +7000,7 @@ STR16 gzLaptopHelpText[] = STR16 gzHelpScreenText[] = { - L"Exit help screen", + L"Exit help screen", }; STR16 gzNonPersistantPBIText[] = @@ -7024,13 +7026,13 @@ STR16 gzMiscString[] = L"You have lost a refueling site.", }; -STR16 gzIntroScreen[] = +STR16 gzIntroScreen[] = { L"Cannot find intro video", }; // These strings are combined with a merc name, a volume string (from pNoiseVolStr), -// and a direction (either "above", "below", or a string from pDirectionStr) to +// and a direction (either "above", "below", or a string from pDirectionStr) to // report a noise. // e.g. "Sidney hears a loud sound of MOVEMENT coming from the SOUTH." STR16 pNewNoiseStr[] = @@ -7068,14 +7070,14 @@ STR16 wMapScreenSortButtonHelpText[] = -STR16 BrokenLinkText[] = +STR16 BrokenLinkText[] = { L"Error 404", L"Site not found.", }; -STR16 gzBobbyRShipmentText[] = +STR16 gzBobbyRShipmentText[] = { L"Recent Shipments", L"Order #", @@ -7171,7 +7173,7 @@ STR16 gzLateLocalizedString[] = L"The robot cannot leave this sector when nobody is using the controller.", //This message comes up if you have pending bombs waiting to explode in tactical. - L"You can't compress time right now. Wait for the fireworks!", + L"You can't compress time right now. Wait for the fireworks!", //'Name' refuses to move. L"%s refuses to move.", @@ -7211,7 +7213,7 @@ STR16 gzLateLocalizedString[] = //In autoresolve if there were 5 mercs fighting 8 enemies the text would be "5 vs. 8" //"vs." is the abbreviation of versus. L"%d vs. %d", - + L"The %s is full!", //(ex "The ice cream truck is full") L"%s does not need immediate first aid or bandaging but rather more serious medical attention and/or rest.", @@ -7222,7 +7224,7 @@ STR16 gzLateLocalizedString[] = //Name can't speak right now. L"%s can't speak right now.", - //22-24 plural versions + //22-24 plural versions L"%d green militia have been promoted to veteran militia.", L"%d green militia have been promoted to regular militia.", L"%d regular militia have been promoted to veteran militia.", @@ -7239,7 +7241,7 @@ STR16 gzLateLocalizedString[] = L"It is currently unsafe to compress time because you have mercs in sector %s.", L"It is currently unsafe to compress time when mercs are in the creature infested mines.", - //29-31 singular versions + //29-31 singular versions L"1 green militia has been promoted to a veteran militia.", L"1 green militia has been promoted to a regular militia.", L"1 regular militia has been promoted to a veteran militia.", @@ -7288,23 +7290,23 @@ STR16 gzLateLocalizedString[] = L"Continue Time Compression (|S|p|a|c|e)", L"Stop Time Compression (|E|s|c)", - //53-54 "Magic has unjammed the Glock 18" or "Magic has unjammed Raven's H&K G11" + //53-54 "Magic has unjammed the Glock 18" or "Magic has unjammed Raven's H&K G11" L"%s has unjammed the %s", L"%s has unjammed %s's %s", - //55 + //55 L"Can't compress time while viewing sector inventory.", L"The Jagged Alliance 2 v1.13 PLAY DISK was not found. Program will now exit.", L"Items successfully combined.", - + //58 //Displayed with the version information when cheats are enabled. L"Current/Max Progress: %d%%/%d%%", L"Escort John and Mary?", - + // 60 L"Switch Activated.", @@ -7313,12 +7315,12 @@ STR16 gzLateLocalizedString[] = L"%s fires one more round than intended!", L"You need to close the item description box first!", - + L"Cannot compress time - hostile civilians and/or bloodcats are in this sector.", // 65 }; // HEADROCK HAM 3.5: Added sector name -STR16 gzCWStrings[] = +STR16 gzCWStrings[] = { L"Call reinforcements to %s from adjacent sectors?", }; @@ -7369,10 +7371,10 @@ STR16 gzTooltipStrings[] = L"no Helmet", L"no Vest", L"no Leggings", - L"|Armor: %s\n", + L"|Armor: %s\n", // Added - SANDRO L"%s|Skill 1: %s\n", - L"%s|Skill 2: %s\n", + L"%s|Skill 2: %s\n", L"%s|Skill 3: %s\n", // Additional suppression effects - sevenfm L"%s|A|Ps lost due to |S|uppression: %d\n", @@ -7388,7 +7390,7 @@ STR16 New113Message[] = L"Rain started.", L"Rain ended.", L"Watch out for snipers...", - L"Suppression fire!", + L"Suppression fire!", L"BRST", L"AUTO", L"GL", @@ -7436,7 +7438,7 @@ STR16 New113Message[] = L"%s is hit at the groin and falls down in pain!", ////////////////////////////////////////////////////////////////////////////////////// L"Warning: enemy corpse found!!!", - L"%s [%d rnds]\n%s %1.1f %s", + L"%s [%d rnds]\n%s %1.1f %s", L"Insufficient AP Points! Cost %d, you have %d.", L"Hint: %s", L"Player strength: %d - Enemy strength: %6.0f", // Surrender values to be printed, if DISPLAY_SURRENDER_VALUES = TRUE @@ -7467,7 +7469,7 @@ STR16 New113Message[] = L"No", }; -STR16 New113HAMMessage[] = +STR16 New113HAMMessage[] = { // 0 - 5 L"%s cowers in fear!", @@ -7475,7 +7477,7 @@ STR16 New113HAMMessage[] = L"%s fires more rounds than intended!", L"You cannot train militia in this sector.", L"Militia picks up %s.", - L"Cannot train militia with enemies present!", + L"Cannot train militia with enemies present!", // 6 - 10 L"%s lacks sufficient Leadership score to train militia.", L"No more than %d Mobile Militia trainers are permitted in this sector.", @@ -7502,7 +7504,7 @@ STR16 New113HAMMessage[] = }; // HEADROCK HAM 5: Text dealing exclusively with Item Transformations. -STR16 gzTransformationMessage[] = +STR16 gzTransformationMessage[] = { L"No available adjustments", L"%s was split into several parts.", @@ -7530,7 +7532,7 @@ STR16 New113MERCMercMailTexts[] = // Gaston: Text from Line 39 in Email.edt L"Hereby be informed that due to Gastons's past performance his fees for services rendered have undergone an increase. Personally, I'm not surprised. ± ± Speck T. Kline ± ", // Stogie: Text from Line 43 in Email.edt - L"Please be advised that, as of this moment, Stogies's fees for services rendered have increased to coincide with the increase in his abilities. ± ± Speck T. Kline ± ", + L"Please be advised that, as of this moment, Stogies's fees for services rendered have increased to coincide with the increase in his abilities. ± ± Speck T. Kline ± ", // Tex: Text from Line 45 in Email.edt L"Please be advised that Tex's experience entitles him to more equitable compensation. He's fees have therefore been increased to more accurately reflect his worth. ± ± Speck T. Kline ± ", // Biggens: Text from Line 49 in Email.edt @@ -7589,9 +7591,9 @@ STR16 MissingIMPSkillsDescriptions[] = // SANDRO - new strings for new traits added // MINTY - Altered the texts for more natural English, and added a little flavour too // Ranger - L"Ranger: Those amateurs from Texas have nothing on you! ± ", + L"Ranger: Those amateurs from Texas have nothing on you! ± ", // Gunslinger - L"Gunslinger: With one handgun or two, you can be as lethal as Billy the Kid! ± ", + L"Gunslinger: With one handgun or two, you can be as lethal as Billy the Kid! ± ", // Squadleader L"Squadleader: A natural leader, your squadmates look to you for inspiration! ± ", // Technician @@ -7614,7 +7616,7 @@ STR16 MissingIMPSkillsDescriptions[] = L"Survival: Nature is a second home to you. ± ", }; -STR16 NewInvMessage[] = +STR16 NewInvMessage[] = { L"Cannot pickup backpack at this time", L"No place to put backpack", @@ -7655,7 +7657,7 @@ STR16 MPServerMessage[] = STR16 MPClientMessage[] = { // 0 - L"Initiating RakNet client...", + L"Initiating RakNet client...", L"Connecting to IP: %S ...", L"Received game settings:", L"You are already connected.", @@ -7682,7 +7684,7 @@ STR16 MPClientMessage[] = L"X: %d, Y: %d", L"Grid number: %d", L"Server only feature", - L"Choose server manual override stage: ('1' - Enable laptop/hiring) ('2' - Launch/load level) ('3' - Unlock UI) ('4' - Finish placement)", + L"Choose server manual override stage: ('1' - Enable laptop/hiring) ('2' - Launch/load level) ('3' - Unlock UI) ('4' - Finish placement)", L"Sector=%s, Max. clients=%d, Max. mercs=%d, Game type=%d, Same merc=%d, Damage multiplier=%f, Timed turns=%d, Secs/Tic=%d, Disable Bobby Ray=%d, Disable Aim/Merc Equipment=%d, Disable Morale=%d, Testing=%d.", // 25 L"", //not used any more @@ -7836,7 +7838,7 @@ STR16 pSkillTraitBeginIMPStrings[] = L"No more then %d choices altogether are possible. This means that if you choose no major traits, you can choose %d minor traits. If you choose two major traits (or one enhanced), you can then choose only %d minor trait(s)...", }; -STR16 sgAttributeSelectionText[] = +STR16 sgAttributeSelectionText[] = { L"Please adjust your physical attributes according to your true abilities. You cannot raise any score above", L"I.M.P. Attributes and skills review.", @@ -7889,7 +7891,7 @@ STR16 gzIMPCharacterTraitText[]= L"I.M.P. Character Traits", }; -STR16 gzIMPColorChoosingText[] = +STR16 gzIMPColorChoosingText[] = { L"I.M.P. Colors and Body Type", L"I.M.P. Colors", @@ -8075,12 +8077,12 @@ STR16 Additional113Text[]= { L"Jagged Alliance 2 v1.13 windowed mode requires a color depth of 16bpp.", L"Jagged Alliance 2 v1.13 fullscreen mode (%d x %d) is not supported by your primary screen.\nPlease either change the game resolution or use 16 bpp windowed mode.", - L"Internal error in reading %s slots from Savegame: Number of slots in Savegame (%d) differs from defined slots in ja2_options.ini settings (%d)", + L"Internal error in reading %s slots from Savegame: Number of slots in Savegame (%d) differs from defined slots in ja2_options.ini settings (%d)", // WANNE: Savegame slots validation against INI file - L"Mercenary (MAX_NUMBER_PLAYER_MERCS) / Vehicle (MAX_NUMBER_PLAYER_VEHICLES)", - L"Enemy (MAX_NUMBER_ENEMIES_IN_TACTICAL)", - L"Creature (MAX_NUMBER_CREATURES_IN_TACTICAL)", - L"Militia (MAX_NUMBER_MILITIA_IN_TACTICAL)", + L"Mercenary (MAX_NUMBER_PLAYER_MERCS) / Vehicle (MAX_NUMBER_PLAYER_VEHICLES)", + L"Enemy (MAX_NUMBER_ENEMIES_IN_TACTICAL)", + L"Creature (MAX_NUMBER_CREATURES_IN_TACTICAL)", + L"Militia (MAX_NUMBER_MILITIA_IN_TACTICAL)", L"Civilian (MAX_NUMBER_CIVS_IN_TACTICAL)", }; @@ -8400,7 +8402,7 @@ STR16 szUDBGenExplosiveStatsExplanationsTooltipText[]= L"\n \nThis value represents a chance (out of 100) for this\nexplosive to spontaneously explode whenever it is damaged\n(for instance, when other explosions go off nearby).\n \nCarrying highly-volatile explosives into combat\nis therefore extremely risky and should be avoided.\n \nScale: 0-100.\nLower is better.", L"\n \nDetermines how difficult it is to repair these explosives.\n \ngreen = Anybody can repair them.\n \nred = This item can't be repaired.\n \nHigher is better.", }; - + STR16 szUDBGenCommonStatsTooltipText[]= { L"|R|e|p|a|i|r |E|a|s|e", @@ -8737,7 +8739,7 @@ STR16 gzMapInventorySortingMessage[] = L"Finished sorting ammo into crates in sector %c%d.", L"Finished removing attachments from items in sector %c%d.", L"Finished ejecting ammo from weapons in sector %c%d.", - L"Finished stacking and merging all items in sector %c%d.", + L"Finished stacking and merging all items in sector %c%d.", // Bob: new strings for emptying LBE items L"Finished emptying LBE items in sector %c%d.", L"Dropped %i item(s) from %s", // Bunch of stuff removed from LBE item %s @@ -8821,7 +8823,7 @@ STR16 gFoodDesc[] = L"." }; -CHAR16* ranks[] = +CHAR16* ranks[] = { L"", //ExpLevel 0 L"Pvt. ", //ExpLevel 1 L"Pfc. ", //ExpLevel 2 @@ -8869,7 +8871,7 @@ STR16 zNewTacticalMessages[]= L"You have selected the campaign %S. This campaign is a player-modified version of the original Unfinished Business campaign. Are you sure you wish to play the %S campaign?", // @@@ new text L"In order to use the editor, please select a campaign other than the default.", ///@@new // anv: extra iron man modes - L"This is a SOFT IRON MAN game and you cannot save during turn-based combat.", + L"This is a SOFT IRON MAN game and you cannot save during turn-based combat.", L"This is an EXTREME IRON MAN game and you can only save once per day, at %02d:00.", }; @@ -9016,7 +9018,7 @@ STR16 szBackgroundText_Flags[]= STR16 szBackgroundText_Value[]= { L" %s%d%% APs in polar sectors\n", - L" %s%d%% APs in desert sectors\n", + L" %s%d%% APs in desert sectors\n", L" %s%d%% APs in swamp sectors\n", L" %s%d%% APs in urban sectors\n", L" %s%d%% APs in forest sectors\n", @@ -9031,7 +9033,7 @@ STR16 szBackgroundText_Value[]= L" %s%d%% strength stat\n", L" %s%d%% leadership stat\n", L" %s%d%% marksmanship stat\n", - L" %s%d%% mechanical stat\n", + L" %s%d%% mechanical stat\n", L" %s%d%% explosives stat\n", L" %s%d%% medical stat\n", L" %s%d%% wisdom stat\n", @@ -9043,7 +9045,7 @@ STR16 szBackgroundText_Value[]= L" %s%d%% APs needed to access inventory\n", L" looks in other direction on airdrops\n %s%d%% APs after airdrop\n", L" %s%d%% APs on first turn when assaulting a sector\n", - + L" %s%d%% travel speed on foot\n", L" %s%d%% travel speed on land vehicles\n", L" %s%d%% travel speed on air vehicles\n", @@ -9067,7 +9069,7 @@ STR16 szBackgroundText_Value[]= L" %s%d%% food consumption\n", L" %s%d%% water consumption\n", L" %s%d need for sleep\n", - L" %s%d%% melee damage\n", + L" %s%d%% melee damage\n", L" %s%d%% cth with blades\n", L" %s%d%% camo effectiveness\n", L" %s%d%% stealth\n", @@ -9099,16 +9101,16 @@ STR16 szBackgroundText_Value[]= L" %s%d%% building speed\n", L" hacking skill: %s%d ", L" %s%d%% burial speed\n", - L" %s%d%% administration effectiveness\n", + L" %s%d%% administration effectiveness\n", }; -STR16 szBackgroundTitleText[] = +STR16 szBackgroundTitleText[] = { L"I.M.P. Background", }; // Flugente: personality -STR16 szPersonalityTitleText[] = +STR16 szPersonalityTitleText[] = { L"I.M.P. Prejudices", }; @@ -9417,7 +9419,7 @@ STR16 szCampaignHistoryWebSite[]= L"A collection of press sources from %s", L"We are a neutral source of information. We collect different news articles from %s. We do not judge these sources - we merely publish them, so you can judge yourself. We post articles from various sources, among them", - + L"Conflict Summary", L"Battle reports", L"News", @@ -9434,7 +9436,7 @@ STR16 szCampaignHistoryDetail[]= L"attacked", L"ambushed", L"airdropped", - + L"The attack came from %s.", L"%s were reinforced from %s.", L"The attack came from %s, %s were reinforced from %s.", @@ -9500,7 +9502,7 @@ STR16 szCampaignHistoryResultString[]= L"The rebels had losses but defeated the royalists. Unverified information says several soldiers might have been taken prisoner.", L"In a phyrric victory, the rebels defeated the royalists but had severe casualties of their own. Whether they will be able to hold this position against continued attacks is doubtful.", - + L"The army's superiority in numbers came into full play. The rebels never had a chance and had to either retreat or be killed or captured.", L"Despite the high number of rebels in this sector, the army easily dispatched them.", @@ -9509,7 +9511,7 @@ STR16 szCampaignHistoryResultString[]= L"Fierce fighting saw significant losses on both sides, but in the end, the army's higher number of bodies decided the battle. The rebel force was destroyed. There might have been survivors, but we cannot verify this at this point.", L"In an intense firefight, the superior training of the armed forces tipped the scales. The rebels had to retreat.", - + L"Neither side was willing to yield. While the army ultimately removed the rebel threat in the area, the staggering losses have resulted in the army unit continuing to exist in name only. But it is clear the rebels will soon be out of men and women if the army can keep on this rate of attrition.", }; @@ -9932,13 +9934,13 @@ STR16 szMercCompareWebSite[] = L"Analyse a team", L"Pairwise comparison", L"Personalities", - L"Customer voices", - + L"Customer voices", + L"If your business provides innovative solutions for critical applications with realtime demands, perhaps some of these observations sound familiar to you:", L"Your team struggles with itself.", L"Your employees waste time working against each other.", L"Your workforce experiences a high fluctuation rate.", - L"You constantly receive low marks on workplace satisfaction ratings.", + L"You constantly receive low marks on workplace satisfaction ratings.", L"If you can say 'yes' to one or more of these statements, then you might have a problem in your business. Your employees likely won't work at peak perfection. Thanks to our patented, easy-to-understand MeLoDY system, you can bring productivity back up in no time, and a happy smile on the faces all your staff!", // customer quotes @@ -10075,7 +10077,7 @@ STR16 szPMCWebSite[] = L"You can also hire an entire security team. In the 'Team Contracts' page, you can select how many of our personnel you want to hire, and where you require their services. Due to regrettable incidents in the past, we have to insist that the landing zone be under your control prior to debarkation.", L"Our team can deploy by air, in which case, of course, an airport is required. Depending on the country our services are required in, insertion via harbours or border posts is also possible.", L"An advance payment is required. After that, the daily fee for our personnel will be deducted from your account.", - + // militia contract page L"You can select the type and number of personnel you want to hire here:", L"Initial deployment", @@ -10151,7 +10153,7 @@ STR16 szTacticalCoverDialogString[]= STR16 szTacticalCoverDialogPrintString[]= { - + L"Turning off cover/traps display", L"Showing danger zones", L"Showing merc view", @@ -10821,7 +10823,7 @@ STR16 szDynamicDialogueText[40][17] = L"", L"", L"", - + // OPINIONEVENT_BESTCOMMANDEREVER L"Yeah! Take that, losers! That was a mighty fine strategy, $CAUSE$!", L"", @@ -10993,7 +10995,7 @@ STR16 szDynamicDialogueText_DOST_VICTIM_TO_INTERJECTOR_AGREE[] = L"Yep", L"Yes.", - L"Indeed.", + L"Indeed.", L"True.", L"Ha!", L"See?", @@ -11102,7 +11104,7 @@ STR16 szDiseaseText[] = }; STR16 szSpyText[] = -{ +{ L"Hide", L"Get Intel", }; @@ -11139,14 +11141,14 @@ STR16 szIMPGearDropDownText[] = L"Select LBE combat pack", L"Select LBE backpack", L"Select LBE holster", - L"Select LBE holster", - + L"Select LBE holster", + L"Select main gun", L"Select ammo", L"Select sidearm", L"Select additional ammo", L"Select melee weapon", - + L"Select helmet", L"Select vest", L"Select pants", @@ -11168,14 +11170,14 @@ STR16 szIMPGearDropDownNoneText[] = L"No LBE combat pack", L"No LBE backpack", L"No LBE holster", - L"No LBE holster", - + L"No LBE holster", + L"No gun", L"No ammo", L"No gun", L"No ammo", L"No weapon", - + L"No helmet", L"No vest", L"No pants", @@ -11245,7 +11247,7 @@ STR16 szIndividualMilitiaBattleReportText[] = L"Recruited on Day %d, %d:%02d in %s", L"Promoted on Day %d, %d:%02d", L"KIA, Operation %s", - + L"Lightly wounded during Operation %s", L"Heavily wounded during Operation %s", L"Critically wounded during Operation %s", diff --git a/Utils/_FrenchText.cpp b/Utils/_FrenchText.cpp index 0e0ca354..d31758de 100644 --- a/Utils/_FrenchText.cpp +++ b/Utils/_FrenchText.cpp @@ -6364,6 +6364,7 @@ STR16 zOptionsToggleText[] = L"Afficher la progression", // Show progress towards stat increase L"Couleur alternative carte", // Change color scheme of Strategic Map L"Montrer tirs alternatifs", // Show alternate bullet graphics (tracers) + L"Use Logical Bodytypes", L"Afficher grade du mercenaire", // shows mercs ranks L"Afficher équip. sur portrait", L"Afficher icônes sur portrait", @@ -6478,6 +6479,7 @@ STR16 zOptionsScreenHelpText[] = L"Si activé, affiche une barre de progression sur chaque compétence", L"Si activé, la carte stratégique sera colorée différemment selon l'exploration.", L"Si activé, le graphisme des tirs alternatifs sera affiché quand vous tirerez.", + L"When ON, mercenary body graphic can change along with equipped gear.", // TODO.Translate L"Si activée, le grade sera affiché devant le nom du merc. dans la carte stratégique.", L"Si activé, vous verrez l'équipement du mercenaire à travers son portrait.", L"Si activé, vous verrez les icônes correspondant à l'équipement porté en bas à droite du portrait.", diff --git a/Utils/_GermanText.cpp b/Utils/_GermanText.cpp index d43d1665..bd944873 100644 --- a/Utils/_GermanText.cpp +++ b/Utils/_GermanText.cpp @@ -6203,6 +6203,7 @@ STR16 zOptionsToggleText[] = L"Status Trainingsfortschritt", // Show progress towards stat increase L"Alternatives Kartenfarbschema", // Change color scheme of Strategic Map L"Alternative Projektil-Grafik", // Show alternate bullet graphics (tracers) + L"Use Logical Bodytypes", L"Söldnerrang anzeigen.", // shows mercs ranks L"Gesichtsequipment-Grafiken", L"Gesichtsequipment-Icons", @@ -6317,6 +6318,7 @@ STR16 zOptionsScreenHelpText[] = L"Wenn diese Funktion aktiviert ist, werden die Söldnerwerte visuell mit ihrem Trainingsfortschritt unterlegt.", L"Wenn diese Funktion aktiviert ist, wird die Strategische Karte entsprechend Ihres Erkundungsfortschrittes unterschiedlich eingefärbt.", L"Wenn diese Funktion aktiviert ist, werden geschossene Projektile visuell mit Tracer-Effekten dargestellt.", + L"When ON, mercenary body graphic can change along with equipped gear.", // TODO.Translate L"Wenn diese Funktion aktiviert ist, werden die Ränge der Söldner in der Strategischen Karte vor dem Namen angezeigt.", L"Wenn diese Funktion aktiviert ist, sehen sie das Gesichtsequipment Ihrer Söldner direkt auf dem Portrait.", L"Wenn diese Funktion aktiviert ist, sehen sie Icons für das Gesichtsequipment in der rechten unteren Ecke des Portraits.", diff --git a/Utils/_ItalianText.cpp b/Utils/_ItalianText.cpp index 7f8dfde4..59221120 100644 --- a/Utils/_ItalianText.cpp +++ b/Utils/_ItalianText.cpp @@ -6342,6 +6342,7 @@ STR16 zOptionsToggleText[] = L"Stat Progress Bars", // Show progress towards stat increase // TODO.Translate L"Alternate Strategy-Map Colors", // Change color scheme of Strategic Map L"Alternate bullet graphics", // Show alternate bullet graphics (tracers) // TODO.Translate + L"Use Logical Bodytypes", L"Show Merc Ranks", // shows mercs ranks // TODO.Translate L"Show Face gear graphics", // TODO.Translate L"Show Face gear icons", @@ -6456,6 +6457,7 @@ STR16 zOptionsScreenHelpText[] = L"When ON, shows character progress towards gaining levels.", // TODO.Translate L"When ON, the Strategic Map will be colored differently based on exploration.", L"When ON, alternate bullet graphics will be shown when you shoot.", // TODO.Translate + L"When ON, mercenary body graphic can change along with equipped gear.", // TODO.Translate L"When ON, ranks will be displayed before merc names in the strategic view.", // TODO.Translate L"When ON, you will see the equipped face gear on the merc portraits.", // TODO.Translate L"When ON, you will see icons for the equipped face gear on the merc portraits in the lower right corner.", diff --git a/Utils/_PolishText.cpp b/Utils/_PolishText.cpp index 9fcade65..789eeebb 100644 --- a/Utils/_PolishText.cpp +++ b/Utils/_PolishText.cpp @@ -6361,6 +6361,7 @@ STR16 zOptionsToggleText[] = L"Alternate Strategy-Map Colors", // Change color scheme of Strategic Map L"Alternate bullet graphics", // Show alternate bullet graphics (tracers) // TODO.Translate L"Show Merc Ranks", // shows mercs ranks // TODO.Translate + L"Use Logical Bodytypes", L"Show Face gear graphics", // TODO.Translate L"Show Face gear icons", L"Disable Cursor Swap", // Disable Cursor Swap // TODO.Translate @@ -6475,6 +6476,7 @@ STR16 zOptionsScreenHelpText[] = L"Jeśli WŁĄCZONE, pokazuje postęp w doświadczeniu postaci.", L"When ON, the Strategic Map will be colored differently based on exploration.", L"Jeśli WŁĄCZONE, zastępuje starą animację pocisku nową.", + L"When ON, mercenary body graphic can change along with equipped gear.", // TODO.Translate L"When ON, ranks will be displayed before merc names in the strategic view.", // TODO.Translate L"When ON, you will see the equipped face gear on the merc portraits.", // TODO.Translate L"When ON, you will see icons for the equipped face gear on the merc portraits in the lower right corner.", diff --git a/Utils/_RussianText.cpp b/Utils/_RussianText.cpp index c49a148a..cf20fcc6 100644 --- a/Utils/_RussianText.cpp +++ b/Utils/_RussianText.cpp @@ -6352,6 +6352,7 @@ STR16 zOptionsToggleText[] = L"Подсветить навык к повышению", //Stat Progress Bars // Show progress towards stat increase L"Новая расцветка стратег. карты", //Alternate Strategy-Map Colors //Change color scheme of Strategic Map L"Заметная летящая пуля", // Show alternate bullet graphics (tracers) + L"Использовать LOBOT", L"Показать ранг бойца", // shows mercs ranks L"Показать снаряжение на голове", //Show Face gear graphics L"Показать иконки снаряжения", @@ -6466,6 +6467,7 @@ STR16 zOptionsScreenHelpText[] = L"Если включено, навык,\nкоторый вскоре повысится, будет подсвечен.", L"Если включено, необследованные сектора\nна стратегической карте будут чёрно-белыми.", L"Если включено, летящая пуля\nбудет более заметной.", + L"Если включено, анимация наемника будет отображать используемое оружие и экипировку.", // TODO.Translate L"Если включено, на стратегическом экране\nбудет подписан ранг бойца перед его именем.", L"Если включено, на портрете наёмника\nбудет отображено надетое головное снаряжение.", L"Если включено, в правом нижнем углу\nна портрете наёмника будут отображены иконки\nнадетого головного снаряжения.",