diff --git a/Console/Console.vcproj b/Console/Console.vcproj index 043fa706..d37d348f 100644 --- a/Console/Console.vcproj +++ b/Console/Console.vcproj @@ -19,7 +19,7 @@ uiFlags &= (~BUTTON_CLICKED_ON ); + if(!is_networked) + { //if the user doesnt have IRON MAN mode selected if( !DisplayMessageToUserAboutIronManMode() ) { //Confirm the difficulty setting DisplayMessageToUserAboutGameDifficulty(); } + } + else + { + gubGameOptionScreenHandler = GIO_EXIT; + } InvalidateRegion(btn->Area.RegionTopLeftX, btn->Area.RegionTopLeftY, btn->Area.RegionBottomRightX, btn->Area.RegionBottomRightY); @@ -1158,6 +1215,46 @@ void BtnGIOCancelCallback(GUI_BUTTON *btn,INT32 reason) } + + + +void MPBtnGIOCancelCallback(GUI_BUTTON *btn,INT32 reason) +{ + if(reason & MSYS_CALLBACK_REASON_LBUTTON_DWN ) + { + btn->uiFlags |= BUTTON_CLICKED_ON; + InvalidateRegion(btn->Area.RegionTopLeftX, btn->Area.RegionTopLeftY, btn->Area.RegionBottomRightX, btn->Area.RegionBottomRightY); + } + if(reason & MSYS_CALLBACK_REASON_LBUTTON_UP ) + { + btn->uiFlags &= (~BUTTON_CLICKED_ON ); + + //gubGameOptionScreenHandler = GIO_CANCEL; + + //// Select the game which is to be restored + //guiPreviousOptionScreen = guiCurrentScreen; + //guiMainMenuExitScreen = SAVE_LOAD_SCREEN; + //gbHandledMainMenu = 0; + //gfSaveGame = FALSE; + //gfMainMenuScreenExit = TRUE; + + /* guiPreviousOptionScreen = guiCurrentScreen; + SetPendingNewScreen( SAVE_LOAD_SCREEN ); + gubGameOptionScreenHandler = GIO_EXIT; + + gubGIOExitScreen = MAINMENU_SCREEN; + gfGIOScreenExit = TRUE; + fInterfacePanelDirty = DIRTYLEVEL2;*/ + + gubGameOptionScreenHandler = MP_LOAD; + + + + InvalidateRegion(btn->Area.RegionTopLeftX, btn->Area.RegionTopLeftY, btn->Area.RegionBottomRightX, btn->Area.RegionBottomRightY); + } +} + + UINT8 GetCurrentDifficultyButtonSetting() { UINT8 cnt; @@ -1236,7 +1333,7 @@ UINT8 GetCurrentGunButtonSetting() } // JA2 Gold: no timed turns -/* + UINT8 GetCurrentTimedTurnsButtonSetting() { UINT8 cnt; @@ -1250,7 +1347,7 @@ UINT8 GetCurrentTimedTurnsButtonSetting() } return( 0 ); } -*/ +//hayden : re-enabled UINT8 GetCurrentGameSaveButtonSetting() { @@ -1348,7 +1445,13 @@ void DoneFadeOutForExitGameInitOptionScreen( void ) gGameOptions.ubGameStyle = GetCurrentGameStyleButtonSetting(); gGameOptions.ubDifficultyLevel = GetCurrentDifficultyButtonSetting() + 1; // JA2Gold: no more timed turns setting - //gGameOptions.fTurnTimeLimit = GetCurrentTimedTurnsButtonSetting(); + //gGameOptions.fTurnTimeLimit = GetCurrentTimedTurnsButtonSetting();//hayden : re-enabled + + if (is_networked) + gGameOptions.fTurnTimeLimit = TRUE; + else + gGameOptions.fTurnTimeLimit = FALSE; + // JA2Gold: iron man gGameOptions.fIronManMode = GetCurrentGameSaveButtonSetting(); diff --git a/GameSettings.cpp b/GameSettings.cpp index 289bbe5a..21cc05be 100644 --- a/GameSettings.cpp +++ b/GameSettings.cpp @@ -35,7 +35,8 @@ #include "Game Clock.h" #endif -#include "Text.h" +#include "Text.h" +#include "connect.h" #define GAME_SETTINGS_FILE "Ja2.set" @@ -55,6 +56,7 @@ extern CHAR8 gzErrorMsg[256]; void InitGameSettings(); + BOOLEAN GetCdromLocationFromIniFile( STR pRootOfCdromDrive ); extern BOOLEAN DoJA2FilesExistsOnDrive( CHAR8 *zCdLocation ); @@ -94,6 +96,7 @@ BOOLEAN IsNIVModeValid(bool checkRes) return( TRUE ); } + BOOLEAN LoadGameSettings() { HWFILE hFile; @@ -316,17 +319,31 @@ void InitGameOptions() memset( &gGameOptions, 0, sizeof( GAME_OPTIONS ) ); //Init the game options - gGameOptions.ubBobbyRay = BR_GOOD; + + if (is_networked) + gGameOptions.ubBobbyRay = BR_AWESOME;// hayden, was BR_GOOD; + else + gGameOptions.ubBobbyRay = BR_GOOD; + gGameOptions.fGunNut = TRUE; gGameOptions.fAirStrikes = FALSE; - gGameOptions.ubGameStyle = STYLE_SCIFI; + + if (is_networked) + gGameOptions.ubGameStyle = STYLE_REALISTIC;//hayden, was STYLE_SCIFI; + else + gGameOptions.ubGameStyle = STYLE_SCIFI; + gGameOptions.ubDifficultyLevel = DIF_LEVEL_MEDIUM; //CHRISL: override default inventory mode when in low res if(IsNIVModeValid() == FALSE) gGameOptions.ubInventorySystem = INVENTORY_OLD; else gGameOptions.ubInventorySystem = INVENTORY_NEW; - //gGameOptions.fTurnTimeLimit = FALSE; + + if (is_networked) + gGameOptions.fTurnTimeLimit = TRUE;//hayden + else + gGameOptions.fTurnTimeLimit = FALSE; gGameOptions.fIronManMode = FALSE; } @@ -545,6 +562,7 @@ void LoadGameExternalOptions() gGameExternalOptions.iStartingCashExpert = iniReader.ReadInteger("JA2 Gameplay Settings", "EXPERT_CASH",30000); gGameExternalOptions.iStartingCashInsane = iniReader.ReadInteger("JA2 Gameplay Settings", "INSANE_CASH",15000); + //Lalien: Game starting time gGameExternalOptions.iGameStartingTime = iniReader.ReadInteger("JA2 Gameplay Settings", "GAME_STARTING_TIME", NUM_SEC_IN_HOUR); @@ -558,7 +576,7 @@ void LoadGameExternalOptions() { gGameExternalOptions.iGameStartingTime += NUM_SEC_IN_DAY; } - + gGameExternalOptions.iFirstArrivalDelay = iniReader.ReadInteger("JA2 Gameplay Settings", "FIRST_ARRIVAL_DELAY", 6 * NUM_SEC_IN_HOUR); //################# Settings valid on game start only end ################## @@ -753,6 +771,10 @@ void LoadGameExternalOptions() // CHRISL: Setting to turn off the description and stack popup options from the sector inventory panel gGameExternalOptions.fSectorDesc = iniReader.ReadBoolean("JA2 Gameplay Settings","ALLOW_SECTOR_DESCRIPTION_WINDOW",TRUE); + + + //afp - use bullet tracers? + gGameExternalOptions.gbBulletTracer = false; } @@ -1087,14 +1109,17 @@ void DisplayGameSettings( ) //Sci fi option ScreenMsg( FONT_MCOLOR_LTYELLOW, MSG_INTERFACE, L"%s: %s", gzGIOScreenText[ GIO_GAME_STYLE_TEXT ], gzGIOScreenText[ GIO_REALISTIC_TEXT + gGameOptions.ubGameStyle ] ); - //Timed Turns option - // JA2Gold: no timed turns + ////Timed Turns option + //// JA2Gold: no timed turns //ScreenMsg( FONT_MCOLOR_LTYELLOW, MSG_INTERFACE, L"%s: %s", gzGIOScreenText[ GIO_TIMED_TURN_TITLE_TEXT ], gzGIOScreenText[ GIO_NO_TIMED_TURNS_TEXT + gGameOptions.fTurnTimeLimit ] ); - //if( CHEATER_CHEAT_LEVEL() ) - { + if (!is_networked) ScreenMsg( FONT_MCOLOR_LTYELLOW, MSG_INTERFACE, gzLateLocalizedString[58], CurrentPlayerProgressPercentage(), HighestPlayerProgressPercentage() ); - } + + ////if( CHEATER_CHEAT_LEVEL() ) + //{ + // ScreenMsg( FONT_MCOLOR_LTYELLOW, MSG_INTERFACE, gzLateLocalizedString[58], CurrentPlayerProgressPercentage(), HighestPlayerProgressPercentage() ); + //} } BOOLEAN MeanwhileSceneSeen( UINT8 ubMeanwhile ) diff --git a/GameSettings.h b/GameSettings.h index 58ab2ea5..c55b1a8b 100644 --- a/GameSettings.h +++ b/GameSettings.h @@ -438,6 +438,9 @@ typedef struct // Lesh: slow enemy items choice progress BOOLEAN fSlowProgressForEnemyItemsChoice; +//afp - use bullet tracers +BOOLEAN gbBulletTracer; + // CHRISL: option to allow Slay to remain as a hired PC BOOLEAN fEnableSlayForever; @@ -446,7 +449,6 @@ typedef struct // CHRISL: New setting to determine AP multiplier when reloading with wrong sized clip FLOAT ubWrongMagMult; - // CHRISL: Setting to turn off the description and stack popup options from the sector inventory panel BOOLEAN fSectorDesc; } GAME_EXTERNAL_OPTIONS; @@ -468,6 +470,7 @@ void FreeGameExternalOptions(); void InitGameOptions(); +void InitGameSettings(); BOOLEAN GetCDLocation( ); diff --git a/GameVersion.cpp b/GameVersion.cpp index 560b9431..80174df0 100644 --- a/GameVersion.cpp +++ b/GameVersion.cpp @@ -13,12 +13,12 @@ #ifdef JA2EDITOR //MAP EDITOR BUILD VERSION -CHAR16 zVersionLabel[256] = { L"Map Editor v1.13.2112" }; +CHAR16 zVersionLabel[256] = { L"Map Editor v1.13.2118" }; #elif defined JA2BETAVERSION //BETA/TEST BUILD VERSION -CHAR16 zVersionLabel[256] = { L"Debug v1.13.2112" }; +CHAR16 zVersionLabel[256] = { L"Debug v1.13.2118" }; #elif defined CRIPPLED_VERSION @@ -28,11 +28,11 @@ CHAR16 zVersionLabel[256] = { L"Beta v. 0.98" }; #else //RELEASE BUILD VERSION - CHAR16 zVersionLabel[256] = { L"Release v1.13.2112" }; + CHAR16 zVersionLabel[256] = { L"Release v1.13.2118" }; #endif -CHAR8 czVersionNumber[16] = { "Build 08.05.07" }; //YY.MM.DD +CHAR8 czVersionNumber[16] = { "Build 08.05.08" }; //YY.MM.DD CHAR16 zTrackingNumber[16] = { L"Z" }; diff --git a/JA2.sln b/JA2.sln index 6d17adf9..a3723512 100644 --- a/JA2.sln +++ b/JA2.sln @@ -55,192 +55,54 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Console", "Console\Console. EndProject Global GlobalSection(SolutionConfiguration) = preSolution - Bounds Checker = Bounds Checker Debug = Debug - Debug Demo = Debug Demo - Demo Bounds Checker = Demo Bounds Checker - Demo Release with Debug Info = Demo Release with Debug Info Release = Release - Release Demo = Release Demo - Release with Debug Info = Release with Debug Info EndGlobalSection GlobalSection(ProjectConfiguration) = postSolution - {33CD085A-A03E-4D2C-970A-D69CD5466806}.Bounds Checker.ActiveCfg = Bounds Checker|Win32 - {33CD085A-A03E-4D2C-970A-D69CD5466806}.Bounds Checker.Build.0 = Bounds Checker|Win32 {33CD085A-A03E-4D2C-970A-D69CD5466806}.Debug.ActiveCfg = Debug|Win32 {33CD085A-A03E-4D2C-970A-D69CD5466806}.Debug.Build.0 = Debug|Win32 - {33CD085A-A03E-4D2C-970A-D69CD5466806}.Debug Demo.ActiveCfg = Debug Demo|Win32 - {33CD085A-A03E-4D2C-970A-D69CD5466806}.Debug Demo.Build.0 = Debug Demo|Win32 - {33CD085A-A03E-4D2C-970A-D69CD5466806}.Demo Bounds Checker.ActiveCfg = Demo Bounds Checker|Win32 - {33CD085A-A03E-4D2C-970A-D69CD5466806}.Demo Bounds Checker.Build.0 = Demo Bounds Checker|Win32 - {33CD085A-A03E-4D2C-970A-D69CD5466806}.Demo Release with Debug Info.ActiveCfg = Demo Release with Debug Info|Win32 - {33CD085A-A03E-4D2C-970A-D69CD5466806}.Demo Release with Debug Info.Build.0 = Demo Release with Debug Info|Win32 {33CD085A-A03E-4D2C-970A-D69CD5466806}.Release.ActiveCfg = Release|Win32 {33CD085A-A03E-4D2C-970A-D69CD5466806}.Release.Build.0 = Release|Win32 - {33CD085A-A03E-4D2C-970A-D69CD5466806}.Release Demo.ActiveCfg = Release Demo|Win32 - {33CD085A-A03E-4D2C-970A-D69CD5466806}.Release Demo.Build.0 = Release Demo|Win32 - {33CD085A-A03E-4D2C-970A-D69CD5466806}.Release with Debug Info.ActiveCfg = Release with Debug Info|Win32 - {33CD085A-A03E-4D2C-970A-D69CD5466806}.Release with Debug Info.Build.0 = Release with Debug Info|Win32 - {E0E16C88-C352-4C37-AC27-BFF3FDF18E82}.Bounds Checker.ActiveCfg = Bounds Checker|Win32 - {E0E16C88-C352-4C37-AC27-BFF3FDF18E82}.Bounds Checker.Build.0 = Bounds Checker|Win32 {E0E16C88-C352-4C37-AC27-BFF3FDF18E82}.Debug.ActiveCfg = Debug|Win32 {E0E16C88-C352-4C37-AC27-BFF3FDF18E82}.Debug.Build.0 = Debug|Win32 - {E0E16C88-C352-4C37-AC27-BFF3FDF18E82}.Debug Demo.ActiveCfg = Debug Demo|Win32 - {E0E16C88-C352-4C37-AC27-BFF3FDF18E82}.Debug Demo.Build.0 = Debug Demo|Win32 - {E0E16C88-C352-4C37-AC27-BFF3FDF18E82}.Demo Bounds Checker.ActiveCfg = Demo Bounds Checker|Win32 - {E0E16C88-C352-4C37-AC27-BFF3FDF18E82}.Demo Bounds Checker.Build.0 = Demo Bounds Checker|Win32 - {E0E16C88-C352-4C37-AC27-BFF3FDF18E82}.Demo Release with Debug Info.ActiveCfg = Demo Release with Debug Info|Win32 - {E0E16C88-C352-4C37-AC27-BFF3FDF18E82}.Demo Release with Debug Info.Build.0 = Demo Release with Debug Info|Win32 {E0E16C88-C352-4C37-AC27-BFF3FDF18E82}.Release.ActiveCfg = Release|Win32 {E0E16C88-C352-4C37-AC27-BFF3FDF18E82}.Release.Build.0 = Release|Win32 - {E0E16C88-C352-4C37-AC27-BFF3FDF18E82}.Release Demo.ActiveCfg = Release Demo|Win32 - {E0E16C88-C352-4C37-AC27-BFF3FDF18E82}.Release Demo.Build.0 = Release Demo|Win32 - {E0E16C88-C352-4C37-AC27-BFF3FDF18E82}.Release with Debug Info.ActiveCfg = Release with Debug Info|Win32 - {E0E16C88-C352-4C37-AC27-BFF3FDF18E82}.Release with Debug Info.Build.0 = Release with Debug Info|Win32 - {1D052886-AE6B-437A-BE0C-D074CA940818}.Bounds Checker.ActiveCfg = Bounds Checker|Win32 - {1D052886-AE6B-437A-BE0C-D074CA940818}.Bounds Checker.Build.0 = Bounds Checker|Win32 {1D052886-AE6B-437A-BE0C-D074CA940818}.Debug.ActiveCfg = Debug|Win32 {1D052886-AE6B-437A-BE0C-D074CA940818}.Debug.Build.0 = Debug|Win32 - {1D052886-AE6B-437A-BE0C-D074CA940818}.Debug Demo.ActiveCfg = Debug Demo|Win32 - {1D052886-AE6B-437A-BE0C-D074CA940818}.Debug Demo.Build.0 = Debug Demo|Win32 - {1D052886-AE6B-437A-BE0C-D074CA940818}.Demo Bounds Checker.ActiveCfg = Bounds Checker|Win32 - {1D052886-AE6B-437A-BE0C-D074CA940818}.Demo Bounds Checker.Build.0 = Bounds Checker|Win32 - {1D052886-AE6B-437A-BE0C-D074CA940818}.Demo Release with Debug Info.ActiveCfg = Demo Release with Debug Info|Win32 - {1D052886-AE6B-437A-BE0C-D074CA940818}.Demo Release with Debug Info.Build.0 = Demo Release with Debug Info|Win32 {1D052886-AE6B-437A-BE0C-D074CA940818}.Release.ActiveCfg = Release|Win32 {1D052886-AE6B-437A-BE0C-D074CA940818}.Release.Build.0 = Release|Win32 - {1D052886-AE6B-437A-BE0C-D074CA940818}.Release Demo.ActiveCfg = Release Demo|Win32 - {1D052886-AE6B-437A-BE0C-D074CA940818}.Release Demo.Build.0 = Release Demo|Win32 - {1D052886-AE6B-437A-BE0C-D074CA940818}.Release with Debug Info.ActiveCfg = Release with Debug Info|Win32 - {1D052886-AE6B-437A-BE0C-D074CA940818}.Release with Debug Info.Build.0 = Release with Debug Info|Win32 - {F10032C4-A6E5-44F7-A9BC-B76C46BA72D5}.Bounds Checker.ActiveCfg = Bounds Checker|Win32 - {F10032C4-A6E5-44F7-A9BC-B76C46BA72D5}.Bounds Checker.Build.0 = Bounds Checker|Win32 {F10032C4-A6E5-44F7-A9BC-B76C46BA72D5}.Debug.ActiveCfg = Debug|Win32 {F10032C4-A6E5-44F7-A9BC-B76C46BA72D5}.Debug.Build.0 = Debug|Win32 - {F10032C4-A6E5-44F7-A9BC-B76C46BA72D5}.Debug Demo.ActiveCfg = Debug Demo|Win32 - {F10032C4-A6E5-44F7-A9BC-B76C46BA72D5}.Debug Demo.Build.0 = Debug Demo|Win32 - {F10032C4-A6E5-44F7-A9BC-B76C46BA72D5}.Demo Bounds Checker.ActiveCfg = Demo Bounds Checker|Win32 - {F10032C4-A6E5-44F7-A9BC-B76C46BA72D5}.Demo Bounds Checker.Build.0 = Demo Bounds Checker|Win32 - {F10032C4-A6E5-44F7-A9BC-B76C46BA72D5}.Demo Release with Debug Info.ActiveCfg = Demo Release with Debug Info|Win32 - {F10032C4-A6E5-44F7-A9BC-B76C46BA72D5}.Demo Release with Debug Info.Build.0 = Demo Release with Debug Info|Win32 {F10032C4-A6E5-44F7-A9BC-B76C46BA72D5}.Release.ActiveCfg = Release|Win32 {F10032C4-A6E5-44F7-A9BC-B76C46BA72D5}.Release.Build.0 = Release|Win32 - {F10032C4-A6E5-44F7-A9BC-B76C46BA72D5}.Release Demo.ActiveCfg = Release Demo|Win32 - {F10032C4-A6E5-44F7-A9BC-B76C46BA72D5}.Release Demo.Build.0 = Release Demo|Win32 - {F10032C4-A6E5-44F7-A9BC-B76C46BA72D5}.Release with Debug Info.ActiveCfg = Release with Debug Info|Win32 - {F10032C4-A6E5-44F7-A9BC-B76C46BA72D5}.Release with Debug Info.Build.0 = Release with Debug Info|Win32 - {2124B612-013E-492D-911C-B5737D60EEDF}.Bounds Checker.ActiveCfg = Bounds Checker|Win32 - {2124B612-013E-492D-911C-B5737D60EEDF}.Bounds Checker.Build.0 = Bounds Checker|Win32 {2124B612-013E-492D-911C-B5737D60EEDF}.Debug.ActiveCfg = Debug|Win32 {2124B612-013E-492D-911C-B5737D60EEDF}.Debug.Build.0 = Debug|Win32 - {2124B612-013E-492D-911C-B5737D60EEDF}.Debug Demo.ActiveCfg = Debug Demo|Win32 - {2124B612-013E-492D-911C-B5737D60EEDF}.Debug Demo.Build.0 = Debug Demo|Win32 - {2124B612-013E-492D-911C-B5737D60EEDF}.Demo Bounds Checker.ActiveCfg = Demo Bounds Checker|Win32 - {2124B612-013E-492D-911C-B5737D60EEDF}.Demo Bounds Checker.Build.0 = Demo Bounds Checker|Win32 - {2124B612-013E-492D-911C-B5737D60EEDF}.Demo Release with Debug Info.ActiveCfg = Demo Release with Debug Info|Win32 - {2124B612-013E-492D-911C-B5737D60EEDF}.Demo Release with Debug Info.Build.0 = Demo Release with Debug Info|Win32 {2124B612-013E-492D-911C-B5737D60EEDF}.Release.ActiveCfg = Release|Win32 {2124B612-013E-492D-911C-B5737D60EEDF}.Release.Build.0 = Release|Win32 - {2124B612-013E-492D-911C-B5737D60EEDF}.Release Demo.ActiveCfg = Release Demo|Win32 - {2124B612-013E-492D-911C-B5737D60EEDF}.Release Demo.Build.0 = Release Demo|Win32 - {2124B612-013E-492D-911C-B5737D60EEDF}.Release with Debug Info.ActiveCfg = Release with Debug Info|Win32 - {2124B612-013E-492D-911C-B5737D60EEDF}.Release with Debug Info.Build.0 = Release with Debug Info|Win32 - {D76119D7-B5EB-4F61-BFB9-F582B06F889B}.Bounds Checker.ActiveCfg = Bounds Checker|Win32 - {D76119D7-B5EB-4F61-BFB9-F582B06F889B}.Bounds Checker.Build.0 = Bounds Checker|Win32 {D76119D7-B5EB-4F61-BFB9-F582B06F889B}.Debug.ActiveCfg = Debug|Win32 {D76119D7-B5EB-4F61-BFB9-F582B06F889B}.Debug.Build.0 = Debug|Win32 - {D76119D7-B5EB-4F61-BFB9-F582B06F889B}.Debug Demo.ActiveCfg = Debug Demo|Win32 - {D76119D7-B5EB-4F61-BFB9-F582B06F889B}.Debug Demo.Build.0 = Debug Demo|Win32 - {D76119D7-B5EB-4F61-BFB9-F582B06F889B}.Demo Bounds Checker.ActiveCfg = Demo Bounds Checker|Win32 - {D76119D7-B5EB-4F61-BFB9-F582B06F889B}.Demo Bounds Checker.Build.0 = Demo Bounds Checker|Win32 - {D76119D7-B5EB-4F61-BFB9-F582B06F889B}.Demo Release with Debug Info.ActiveCfg = Demo Release with Debug Info|Win32 - {D76119D7-B5EB-4F61-BFB9-F582B06F889B}.Demo Release with Debug Info.Build.0 = Demo Release with Debug Info|Win32 {D76119D7-B5EB-4F61-BFB9-F582B06F889B}.Release.ActiveCfg = Release|Win32 {D76119D7-B5EB-4F61-BFB9-F582B06F889B}.Release.Build.0 = Release|Win32 - {D76119D7-B5EB-4F61-BFB9-F582B06F889B}.Release Demo.ActiveCfg = Release Demo|Win32 - {D76119D7-B5EB-4F61-BFB9-F582B06F889B}.Release Demo.Build.0 = Release Demo|Win32 - {D76119D7-B5EB-4F61-BFB9-F582B06F889B}.Release with Debug Info.ActiveCfg = Release with Debug Info|Win32 - {D76119D7-B5EB-4F61-BFB9-F582B06F889B}.Release with Debug Info.Build.0 = Release with Debug Info|Win32 - {97E691B8-7A39-4E86-B69A-BD6BD5C31F32}.Bounds Checker.ActiveCfg = Bounds Checker|Win32 - {97E691B8-7A39-4E86-B69A-BD6BD5C31F32}.Bounds Checker.Build.0 = Bounds Checker|Win32 {97E691B8-7A39-4E86-B69A-BD6BD5C31F32}.Debug.ActiveCfg = Debug|Win32 {97E691B8-7A39-4E86-B69A-BD6BD5C31F32}.Debug.Build.0 = Debug|Win32 - {97E691B8-7A39-4E86-B69A-BD6BD5C31F32}.Debug Demo.ActiveCfg = Debug Demo|Win32 - {97E691B8-7A39-4E86-B69A-BD6BD5C31F32}.Debug Demo.Build.0 = Debug Demo|Win32 - {97E691B8-7A39-4E86-B69A-BD6BD5C31F32}.Demo Bounds Checker.ActiveCfg = Demo Bounds Checker|Win32 - {97E691B8-7A39-4E86-B69A-BD6BD5C31F32}.Demo Bounds Checker.Build.0 = Demo Bounds Checker|Win32 - {97E691B8-7A39-4E86-B69A-BD6BD5C31F32}.Demo Release with Debug Info.ActiveCfg = Demo Release with Debug Info|Win32 - {97E691B8-7A39-4E86-B69A-BD6BD5C31F32}.Demo Release with Debug Info.Build.0 = Demo Release with Debug Info|Win32 {97E691B8-7A39-4E86-B69A-BD6BD5C31F32}.Release.ActiveCfg = Release|Win32 {97E691B8-7A39-4E86-B69A-BD6BD5C31F32}.Release.Build.0 = Release|Win32 - {97E691B8-7A39-4E86-B69A-BD6BD5C31F32}.Release Demo.ActiveCfg = Release Demo|Win32 - {97E691B8-7A39-4E86-B69A-BD6BD5C31F32}.Release Demo.Build.0 = Release Demo|Win32 - {97E691B8-7A39-4E86-B69A-BD6BD5C31F32}.Release with Debug Info.ActiveCfg = Release with Debug Info|Win32 - {97E691B8-7A39-4E86-B69A-BD6BD5C31F32}.Release with Debug Info.Build.0 = Release with Debug Info|Win32 - {4D4A4AF3-63D1-4C4B-81B5-3EFB3BD574F2}.Bounds Checker.ActiveCfg = Bounds Checker|Win32 - {4D4A4AF3-63D1-4C4B-81B5-3EFB3BD574F2}.Bounds Checker.Build.0 = Bounds Checker|Win32 {4D4A4AF3-63D1-4C4B-81B5-3EFB3BD574F2}.Debug.ActiveCfg = Debug|Win32 {4D4A4AF3-63D1-4C4B-81B5-3EFB3BD574F2}.Debug.Build.0 = Debug|Win32 - {4D4A4AF3-63D1-4C4B-81B5-3EFB3BD574F2}.Debug Demo.ActiveCfg = Debug Demo|Win32 - {4D4A4AF3-63D1-4C4B-81B5-3EFB3BD574F2}.Debug Demo.Build.0 = Debug Demo|Win32 - {4D4A4AF3-63D1-4C4B-81B5-3EFB3BD574F2}.Demo Bounds Checker.ActiveCfg = Demo Bounds Checker|Win32 - {4D4A4AF3-63D1-4C4B-81B5-3EFB3BD574F2}.Demo Bounds Checker.Build.0 = Demo Bounds Checker|Win32 - {4D4A4AF3-63D1-4C4B-81B5-3EFB3BD574F2}.Demo Release with Debug Info.ActiveCfg = Demo Release with Debug Info|Win32 - {4D4A4AF3-63D1-4C4B-81B5-3EFB3BD574F2}.Demo Release with Debug Info.Build.0 = Demo Release with Debug Info|Win32 {4D4A4AF3-63D1-4C4B-81B5-3EFB3BD574F2}.Release.ActiveCfg = Release|Win32 {4D4A4AF3-63D1-4C4B-81B5-3EFB3BD574F2}.Release.Build.0 = Release|Win32 - {4D4A4AF3-63D1-4C4B-81B5-3EFB3BD574F2}.Release Demo.ActiveCfg = Release Demo|Win32 - {4D4A4AF3-63D1-4C4B-81B5-3EFB3BD574F2}.Release Demo.Build.0 = Release Demo|Win32 - {4D4A4AF3-63D1-4C4B-81B5-3EFB3BD574F2}.Release with Debug Info.ActiveCfg = Release with Debug Info|Win32 - {4D4A4AF3-63D1-4C4B-81B5-3EFB3BD574F2}.Release with Debug Info.Build.0 = Release with Debug Info|Win32 - {095CC13E-F2F8-4070-AC7A-70926A0ADF37}.Bounds Checker.ActiveCfg = Release|Win32 - {095CC13E-F2F8-4070-AC7A-70926A0ADF37}.Bounds Checker.Build.0 = Release|Win32 {095CC13E-F2F8-4070-AC7A-70926A0ADF37}.Debug.ActiveCfg = Debug|Win32 {095CC13E-F2F8-4070-AC7A-70926A0ADF37}.Debug.Build.0 = Debug|Win32 - {095CC13E-F2F8-4070-AC7A-70926A0ADF37}.Debug Demo.ActiveCfg = Debug|Win32 - {095CC13E-F2F8-4070-AC7A-70926A0ADF37}.Debug Demo.Build.0 = Debug|Win32 - {095CC13E-F2F8-4070-AC7A-70926A0ADF37}.Demo Bounds Checker.ActiveCfg = Debug|Win32 - {095CC13E-F2F8-4070-AC7A-70926A0ADF37}.Demo Bounds Checker.Build.0 = Debug|Win32 - {095CC13E-F2F8-4070-AC7A-70926A0ADF37}.Demo Release with Debug Info.ActiveCfg = Release|Win32 - {095CC13E-F2F8-4070-AC7A-70926A0ADF37}.Demo Release with Debug Info.Build.0 = Release|Win32 {095CC13E-F2F8-4070-AC7A-70926A0ADF37}.Release.ActiveCfg = Release|Win32 {095CC13E-F2F8-4070-AC7A-70926A0ADF37}.Release.Build.0 = Release|Win32 - {095CC13E-F2F8-4070-AC7A-70926A0ADF37}.Release Demo.ActiveCfg = Release|Win32 - {095CC13E-F2F8-4070-AC7A-70926A0ADF37}.Release Demo.Build.0 = Release|Win32 - {095CC13E-F2F8-4070-AC7A-70926A0ADF37}.Release with Debug Info.ActiveCfg = Release|Win32 - {095CC13E-F2F8-4070-AC7A-70926A0ADF37}.Release with Debug Info.Build.0 = Release|Win32 - {32A550A8-FEBD-4F8D-8D62-6F97C63F83DA}.Bounds Checker.ActiveCfg = Bounds Checker|Win32 - {32A550A8-FEBD-4F8D-8D62-6F97C63F83DA}.Bounds Checker.Build.0 = Bounds Checker|Win32 {32A550A8-FEBD-4F8D-8D62-6F97C63F83DA}.Debug.ActiveCfg = Debug|Win32 {32A550A8-FEBD-4F8D-8D62-6F97C63F83DA}.Debug.Build.0 = Debug|Win32 - {32A550A8-FEBD-4F8D-8D62-6F97C63F83DA}.Debug Demo.ActiveCfg = Debug Demo|Win32 - {32A550A8-FEBD-4F8D-8D62-6F97C63F83DA}.Debug Demo.Build.0 = Debug Demo|Win32 - {32A550A8-FEBD-4F8D-8D62-6F97C63F83DA}.Demo Bounds Checker.ActiveCfg = Demo Bounds Checker|Win32 - {32A550A8-FEBD-4F8D-8D62-6F97C63F83DA}.Demo Bounds Checker.Build.0 = Demo Bounds Checker|Win32 - {32A550A8-FEBD-4F8D-8D62-6F97C63F83DA}.Demo Release with Debug Info.ActiveCfg = Demo Release with Debug Info|Win32 - {32A550A8-FEBD-4F8D-8D62-6F97C63F83DA}.Demo Release with Debug Info.Build.0 = Demo Release with Debug Info|Win32 {32A550A8-FEBD-4F8D-8D62-6F97C63F83DA}.Release.ActiveCfg = Release|Win32 {32A550A8-FEBD-4F8D-8D62-6F97C63F83DA}.Release.Build.0 = Release|Win32 - {32A550A8-FEBD-4F8D-8D62-6F97C63F83DA}.Release Demo.ActiveCfg = Release Demo|Win32 - {32A550A8-FEBD-4F8D-8D62-6F97C63F83DA}.Release Demo.Build.0 = Release Demo|Win32 - {32A550A8-FEBD-4F8D-8D62-6F97C63F83DA}.Release with Debug Info.ActiveCfg = Release with Debug Info|Win32 - {32A550A8-FEBD-4F8D-8D62-6F97C63F83DA}.Release with Debug Info.Build.0 = Release with Debug Info|Win32 - {286FCC0E-C6E1-4E29-8642-588D7358966F}.Bounds Checker.ActiveCfg = Release|Win32 - {286FCC0E-C6E1-4E29-8642-588D7358966F}.Bounds Checker.Build.0 = Release|Win32 {286FCC0E-C6E1-4E29-8642-588D7358966F}.Debug.ActiveCfg = Debug|Win32 {286FCC0E-C6E1-4E29-8642-588D7358966F}.Debug.Build.0 = Debug|Win32 - {286FCC0E-C6E1-4E29-8642-588D7358966F}.Debug Demo.ActiveCfg = Debug|Win32 - {286FCC0E-C6E1-4E29-8642-588D7358966F}.Debug Demo.Build.0 = Debug|Win32 - {286FCC0E-C6E1-4E29-8642-588D7358966F}.Demo Bounds Checker.ActiveCfg = Debug|Win32 - {286FCC0E-C6E1-4E29-8642-588D7358966F}.Demo Bounds Checker.Build.0 = Debug|Win32 - {286FCC0E-C6E1-4E29-8642-588D7358966F}.Demo Release with Debug Info.ActiveCfg = Release|Win32 - {286FCC0E-C6E1-4E29-8642-588D7358966F}.Demo Release with Debug Info.Build.0 = Release|Win32 {286FCC0E-C6E1-4E29-8642-588D7358966F}.Release.ActiveCfg = Release|Win32 {286FCC0E-C6E1-4E29-8642-588D7358966F}.Release.Build.0 = Release|Win32 - {286FCC0E-C6E1-4E29-8642-588D7358966F}.Release Demo.ActiveCfg = Release|Win32 - {286FCC0E-C6E1-4E29-8642-588D7358966F}.Release Demo.Build.0 = Release|Win32 - {286FCC0E-C6E1-4E29-8642-588D7358966F}.Release with Debug Info.ActiveCfg = Release|Win32 - {286FCC0E-C6E1-4E29-8642-588D7358966F}.Release with Debug Info.Build.0 = Release|Win32 EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution EndGlobalSection diff --git a/JA2.vcproj b/JA2.vcproj index 252a0ea0..a7424dd7 100644 --- a/JA2.vcproj +++ b/JA2.vcproj @@ -23,7 +23,7 @@ + + + + + + + + + + + + + + + + + + + + diff --git a/Laptop/AimMembers.cpp b/Laptop/AimMembers.cpp index efc9ebfd..d0c66fdb 100644 --- a/Laptop/AimMembers.cpp +++ b/Laptop/AimMembers.cpp @@ -47,7 +47,7 @@ #endif #include "Strategic Town Loyalty.h" - +#include "connect.h" // //****** Defines ****** @@ -1817,7 +1817,7 @@ INT8 AimMemberHireMerc() } //add an entry in the history page for the hiring of the merc - AddHistoryToPlayersLog(HISTORY_HIRED_MERC_FROM_AIM, ubCurrentSoldier, GetWorldTotalMin(), -1, -1 ); + if(!is_client)AddHistoryToPlayersLog(HISTORY_HIRED_MERC_FROM_AIM, ubCurrentSoldier, GetWorldTotalMin(), -1, -1 ); return(TRUE); } @@ -1994,7 +1994,7 @@ UINT32 DisplayMercChargeAmount() // if there is a medical deposit, add it in if( gMercProfiles[ gbCurrentSoldier ].bMedicalDeposit ) { - giContractAmount += gMercProfiles[gbCurrentSoldier].sMedicalDepositAmount; + if(!is_client)giContractAmount += gMercProfiles[gbCurrentSoldier].sMedicalDepositAmount;//hayden } //If hired with the equipment, add it in aswell @@ -3206,7 +3206,11 @@ BOOLEAN InitDeleteVideoConferencePopUp( ) { gubVideoConferencingPreviousMode = gubVideoConferencingMode; gubMercAttitudeLevel = 0; - gubContractLength = AIM_CONTRACT_LENGTH_ONE_WEEK; + + if (is_networked) + gubContractLength = AIM_CONTRACT_LENGTH_ONE_DAY; + else + gubContractLength = AIM_CONTRACT_LENGTH_ONE_WEEK; if( gMercProfiles[gbCurrentSoldier].usOptionalGearCost == 0 ) gfBuyEquipment = FALSE; @@ -3290,6 +3294,11 @@ BOOLEAN InitDeleteVideoConferencePopUp( ) usPosY += AIM_MEMBER_BUY_EQUIPMENT_GAP; } + if(is_client)//hayden : only needed for 1 day... + { + DisableButton( giContractLengthButton[1] ); + DisableButton( giContractLengthButton[2] ); + } // BuyEquipment button usPosY = AIM_MEMBER_BUY_CONTRACT_LENGTH_Y; for(i=0; i<2; i++) @@ -3310,6 +3319,12 @@ BOOLEAN InitDeleteVideoConferencePopUp( ) if( gMercProfiles[gbCurrentSoldier].usOptionalGearCost == 0 ) DisableButton( giBuyEquipmentButton[1] ); + if(!ALLOW_EQUIP && is_networked) + { + gfBuyEquipment = FALSE; + DisableButton( giBuyEquipmentButton[0] ); + DisableButton( giBuyEquipmentButton[1] ); + } // Authorize button usPosX = AIM_MEMBER_AUTHORIZE_PAY_X; @@ -4372,6 +4387,8 @@ void DisplayPopUpBoxExplainingMercArrivalLocationAndTime( ) if( LaptopSaveInfo.sLastHiredMerc.fHaveDisplayedPopUpInLaptop ) return; + if(is_client) + return; pSoldier = FindSoldierByProfileID( (UINT8)LaptopSaveInfo.sLastHiredMerc.iIdOfMerc, TRUE ); if( pSoldier == NULL ) diff --git a/Laptop/BobbyRMailOrder.cpp b/Laptop/BobbyRMailOrder.cpp index dea50a0e..407554ba 100644 --- a/Laptop/BobbyRMailOrder.cpp +++ b/Laptop/BobbyRMailOrder.cpp @@ -25,6 +25,8 @@ #include "strategicmap.h" #endif +#include "Strategic Event Handler.h" +#include "connect.h" typedef struct { @@ -341,7 +343,10 @@ void ShutDownBobbyRNewMailOrders(); void GameInitBobbyRMailOrder() { - gubSelectedLight = 0; + if (is_networked) + gubSelectedLight = 2; //hayden + else + gubSelectedLight = 0; gpNewBobbyrShipments = NULL; giNumberOfNewBobbyRShipment = 0; @@ -778,7 +783,7 @@ void BtnBobbyRAcceptOrderCallback(GUI_BUTTON *btn,INT32 reason) CHAR16 zTemp[ 128 ]; //if the city is Drassen, and the airport sector is player controlled - if( gbSelectedCity == BR_DRASSEN && !StrategicMap[ SECTOR_INFO_TO_STRATEGIC_INDEX( SEC_B13 ) ].fEnemyControlled ) + if( gbSelectedCity == BR_DRASSEN && !StrategicMap[ SECTOR_INFO_TO_STRATEGIC_INDEX( SEC_B13 ) ].fEnemyControlled || is_client ) { //Quick hack to bypass the confirmation box ConfirmBobbyRPurchaseMessageBoxCallBack( MSG_BOX_RETURN_YES ); @@ -1393,6 +1398,7 @@ BOOLEAN CreateDestroyBobbyRDropDown( UINT8 ubDropDownAction ) { UINT8 i; UINT16 usPosY, usPosX; + UINT16 usFontHeight = GetFontHeight( BOBBYR_DROPDOWN_FONT ); HVOBJECT hImageHandle; HVOBJECT hArrowHandle; @@ -2158,9 +2164,19 @@ void ConfirmBobbyRPurchaseMessageBoxCallBack( UINT8 bExitValue ) void EnterInitBobbyRayOrder() { memset(&BobbyRayPurchases, 0, sizeof(BobbyRayPurchaseStruct) * MAX_PURCHASE_AMOUNT); - gubSelectedLight = 0; + + if (is_networked) + gubSelectedLight = 2; //hayden + else + gubSelectedLight = 0; + gfReDrawBobbyOrder = TRUE; - gbSelectedCity = -1; + + if (is_networked) + gbSelectedCity = 2; //hayden , was -1 + else + gbSelectedCity = -1; + gubCityAtTopOfList = 0; //Get rid of the city drop dowm, if it is being displayed @@ -2345,7 +2361,15 @@ BOOLEAN AddNewBobbyRShipment( BobbyRayPurchaseStruct *pPurchaseStruct, UINT8 ubD //AddStrategicEvent( EVENT_BOBBYRAY_PURCHASE, uiResetTimeSec, cnt); + if(is_client) + { + BobbyRayPurchaseEventCallback( iFoundSpot); //hayden - instant delivery ? + //AddStrategicEventUsingSeconds( EVENT_BOBBYRAY_PURCHASE, GetWorldDayInSeconds() + 10, iFoundSpot ); + } + else + { AddFutureDayStrategicEvent( EVENT_BOBBYRAY_PURCHASE, (8 + Random(4) ) * 60, iFoundSpot, bDaysAhead ); + } return( TRUE ); } diff --git a/Laptop/IMP Confirm.cpp b/Laptop/IMP Confirm.cpp index af781e3c..cfe0a227 100644 --- a/Laptop/IMP Confirm.cpp +++ b/Laptop/IMP Confirm.cpp @@ -1238,7 +1238,6 @@ BOOLEAN LoadImpCharacter( STR nickName ) HWFILE hFile; UINT32 uiBytesRead = 0; - // WANNE: Enlarged the array from 13 characters to 32. char zFileName[32]; //ADB first try to load the new kind diff --git a/Laptop/Laptop.vcproj b/Laptop/Laptop.vcproj index 8c7afb78..fae00d20 100644 --- a/Laptop/Laptop.vcproj +++ b/Laptop/Laptop.vcproj @@ -339,7 +339,7 @@ FavorSizeOrSpeed="1" OptimizeForProcessor="3" OptimizeForWindowsApplication="TRUE" - AdditionalIncludeDirectories=""..\Standard Gaming Platform";..\TileEngine;..\;..\Tactical;..\Utils;..\tacticalai;..\Editor;..\strategic;.\" + AdditionalIncludeDirectories="..\Multiplayer;"..\Standard Gaming Platform";..\TileEngine;..\;..\Tactical;..\Utils;..\tacticalai;..\Editor;..\strategic;.\" PreprocessorDefinitions="PRECOMPILEDHEADERS;NDEBUG;WIN32;_WINDOWS;JA2;XML_STATIC;CINTERFACE" StringPooling="TRUE" RuntimeLibrary="0" @@ -390,7 +390,7 @@ uiFlags &= (~BUTTON_CLICKED_ON ); } @@ -554,6 +656,7 @@ BOOLEAN CreateDestroyMainMenuButtons( BOOLEAN fCreate ) static BOOLEAN fButtonsCreated = FALSE; INT32 cnt; SGPFILENAME filename; + SGPFILENAME filenameMP; INT16 sSlot; #ifndef _DEBUG CHAR16 zText[512]; @@ -569,11 +672,18 @@ BOOLEAN CreateDestroyMainMenuButtons( BOOLEAN fCreate ) gfLoadGameUponEntry = FALSE; // Load button images - GetMLGFilename( filename, MLG_TITLETEXT ); + GetMLGFilename( filename, MLG_TITLETEXT ); + GetMLGFilename( filenameMP, MLG_TITLETEXT_MP ); iMenuImages[ NEW_GAME ] = LoadButtonImage( filename, 0,0, 1, 2 ,-1 ); + + iMenuImages[ NEW_MP_GAME ] = LoadButtonImage( filenameMP, 0, 0, 1, 2, -1 ); + sSlot = 0; iMenuImages[ LOAD_GAME ] = UseLoadedButtonImage( iMenuImages[ NEW_GAME ] ,6,3,4,5,-1 ); + + //iMenuImages[ LOAD_MP_GAME ] = UseLoadedButtonImage( iMenuImages[ NEW_MP_GAME ], 3, 3, 4, 5, -1 ); + iMenuImages[ PREFERENCES ] = UseLoadedButtonImage( iMenuImages[ NEW_GAME ] ,7,7,8,9,-1 ); iMenuImages[ CREDITS ] = UseLoadedButtonImage( iMenuImages[ NEW_GAME ] ,13,10,11,12,-1 ); iMenuImages[ QUIT ] = UseLoadedButtonImage( iMenuImages[ NEW_GAME ] ,14,14,15,16,-1 ); @@ -583,7 +693,9 @@ BOOLEAN CreateDestroyMainMenuButtons( BOOLEAN fCreate ) switch( cnt ) { case NEW_GAME: gusMainMenuButtonWidths[cnt] = GetWidthOfButtonPic( (UINT16)iMenuImages[cnt], sSlot ); break; + case NEW_MP_GAME: gusMainMenuButtonWidths[cnt] = GetWidthOfButtonPic( (UINT16)iMenuImages[cnt], 0); break; case LOAD_GAME: gusMainMenuButtonWidths[cnt] = GetWidthOfButtonPic( (UINT16)iMenuImages[cnt], 3 ); break; +// case LOAD_MP_GAME: gusMainMenuButtonWidths[cnt] = GetWidthOfButtonPic( (UINT16)iMenuImages[cnt], 3); break; case PREFERENCES: gusMainMenuButtonWidths[cnt] = GetWidthOfButtonPic( (UINT16)iMenuImages[cnt], 7 ); break; case CREDITS: gusMainMenuButtonWidths[cnt] = GetWidthOfButtonPic( (UINT16)iMenuImages[cnt], 10 ); break; case QUIT: gusMainMenuButtonWidths[cnt] = GetWidthOfButtonPic( (UINT16)iMenuImages[cnt], 15 ); break; @@ -607,6 +719,8 @@ BOOLEAN CreateDestroyMainMenuButtons( BOOLEAN fCreate ) } ButtonList[ iMenuButtons[ cnt ] ]->UserData[0] = cnt; + // WANNE: Removed this, because in Release version it always crashes! + /* #ifndef _DEBUG //load up some info from the 'mainmenu.edt' file. This makes sure the file is present. The file is // 'marked' with a code that identifies the testers @@ -623,7 +737,7 @@ BOOLEAN CreateDestroyMainMenuButtons( BOOLEAN fCreate ) } } #endif - + */ } diff --git a/Multiplayer/client.cpp b/Multiplayer/client.cpp new file mode 100644 index 00000000..5ea161ff --- /dev/null +++ b/Multiplayer/client.cpp @@ -0,0 +1,2849 @@ +#ifdef PRECOMPILEDHEADERS + #include "Tactical All.h" + #include "strategic.h" +#else + #include "builddefines.h" + #include "bullets.h" + #include + #include + #include "wcheck.h" + #include "stdlib.h" + #include "debug.h" + #include "math.h" + #include "worlddef.h" + #include "worldman.h" + #include "renderworld.h" + #include "Assignments.h" + #include "Soldier Control.h" + #include "Animation Control.h" + #include "Animation Data.h" + #include "Isometric Utils.h" + #include "Event Pump.h" + #include "Timer Control.h" + #include "Render Fun.h" + #include "Render Dirty.h" + #include "mousesystem.h" + #include "interface.h" + #include "sysutil.h" + #include "FileMan.h" + #include "points.h" + #include "Random.h" + #include "ai.h" + #include "Interactive Tiles.h" + #include "soldier ani.h" + #include "english.h" + #include "overhead.h" + #include "Soldier Profile.h" + #include "Game Clock.h" + #include "soldier create.h" + #include "Merc Hiring.h" + #include "Game Event Hook.h" + #include "message.h" + #include "strategicmap.h" + #include "strategic.h" + #include "items.h" + #include "Soldier Add.h" + #include "History.h" + #include "Squads.h" + #include "Strategic Merc Handler.h" + #include "Dialogue Control.h" + #include "Map Screen Interface.h" + #include "Map Screen Interface Map.h" + #include "screenids.h" + #include "jascreens.h" + #include "text.h" + #include "Merc Contract.h" + #include "LaptopSave.h" + #include "personnel.h" + #include "Auto Resolve.h" + #include "Map Screen Interface Bottom.h" + #include "Quests.h" + #include "GameSettings.h" + #include "Mercs.h" + #include "Handle Doors.h" + #include "Campaign Types.h" + #include "Tactical Save.h" + #include "BobbyRMailOrder.h" + #include "Finances.h" + #include "TeamTurns.h" +#endif + +#include "MessageIdentifiers.h" +#include "RakNetworkFactory.h" +#include "RakPeerInterface.h" +#include "RakNetStatistics.h" +#include "RakNetTypes.h" + +#include "BitStream.h" +#include +#include +#include +#include +#include "music control.h" +#include "map edgepoints.h" + +#include "fresh_header.h" +#include "network.h" +#include "opplist.h" + +#include "tactical placement gui.h" +#include "prebattle interface.h" + +unsigned char GetPacketIdentifier(Packet *p); +unsigned char packetIdentifier; + +#include "messagebox.h" + +#pragma pack(1) + +#include "new.h" +#include "Types.h" +#include "connect.h" +#include "message.h" +#include "Event pump.h" +#include "Soldier Init List.h" +#include "Overhead.h" +#include "weapons.h" +#include "Merc Hiring.h" +#include "soldier profile.h" +#include "environment.h" +#include "lighting.h" + +#include "laptop.h" +#include "test_space.h" + + + +extern INT8 SquadMovementGroups[ ]; +RakPeerInterface *client; + +typedef struct +{ + UINT8 ubProfileID; + int team; + BOOLEAN fCopyProfileItemsOver; + INT8 bTeam; + +} send_hire_struct; + +typedef struct +{ + UINT8 usSoldierID; + FLOAT dNewXPos; + FLOAT dNewYPos; + +} gui_pos; + +typedef struct +{ + UINT8 usSoldierID; + INT16 usNewDirection; + +} gui_dir; + +typedef struct +{ + UINT8 tsnetbTeam; + UINT8 tsubNextTeam; +} turn_struct; + + +typedef struct + { + + SOLDIERCREATE_STRUCT standard_data; + + OBJECTTYPE slot0; + OBJECTTYPE slot1; + OBJECTTYPE slot2; + OBJECTTYPE slot3; + OBJECTTYPE slot4; + OBJECTTYPE slot5; + OBJECTTYPE slot6; + OBJECTTYPE slot7; + OBJECTTYPE slot8; + OBJECTTYPE slot9; + OBJECTTYPE slot10; + OBJECTTYPE slot11; + OBJECTTYPE slot12; + OBJECTTYPE slot13; + OBJECTTYPE slot14; + OBJECTTYPE slot15; + OBJECTTYPE slot16; + OBJECTTYPE slot17; + OBJECTTYPE slot18; + } AI_STRUCT; + +typedef struct +{ + BULLET net_bullet; + UINT16 usHandItem; + +}netb_struct; + +typedef struct +{ + UINT8 ubID; + INT8 bTeam; + UINT8 gubOutOfTurnPersons; + UINT8 gubOutOfTurnOrder[MAXMERCS]; + BOOLEAN fMarkInterruptOccurred; + UINT8 Interrupted; +} INT_STRUCT; + +typedef struct +{ + UINT8 client_num; + bool status; + UINT8 ready_stage; + +} ready_struct; + +typedef struct +{ + INT32 remote_id; + INT32 local_id; + +}bullets_table; + +typedef struct + { + UINT8 ubResult; + }kickR; + +bullets_table bTable[11][50]; + +char client_names[4][30]; + +INT32 MAX_MERCS; + +int TEAM; +//int OP_TEAM_2; +//int OP_TEAM_3; +//int OP_TEAM_4; + + + +UINT8 netbTeam; +UINT8 ubID_prefix; + + bool is_connected=false; + bool is_connecting=false; + bool is_client=false; + bool is_server=false; + bool is_networked=false; + + bool requested=false; + +int tcount; +int kit[20]; +bool DISABLE_MORALE; + int TESTING; + bool allowlaptop=false; + + bool recieved_settings=false; + + bool getReal=false; + + //char CLIENT_NUM[30]; + int CLIENT_NUM; + char SECT_EDGE[30]; +char ckbag[100]; + char CLIENT_NAME[30]; + + char SERVER_IP[30] ; + char SERVER_PORT[30]; + + int REPORT_NAME; + int WEAPON_READIED_BONUS; + + int ENEMY_ENABLED; + int CREATURE_ENABLED; + int MILITIA_ENABLED; + int CIV_ENABLED; + + int ALLOW_EQUIP; + + int SAME_MERC; + int PLAYER_BSIDE; + +int START_TEAM_TURN; + + bool goahead = 0; + int numready = 0; + int readystage = 0; + bool status = 0; + + bool lockedgui = 0; + +FLOAT DAMAGE_MULTIPLIER; + +//int INTERRUPTS; +int MAX_CLIENTS; + +UINT16 crate_usMapPos; + +INT16 crate_sGridX, crate_sGridY; + +void overide_callback( UINT8 ubResult ); +void kick_callback( UINT8 ubResult ); +void turn_callback (UINT8 ubResult); + + +//***************** +//RPC sends and recieves: +//******************** + + +void send_path ( SOLDIERTYPE *pSoldier, UINT16 sDestGridNo, UINT16 usMovementAnim, BOOLEAN fFromUI, BOOLEAN fForceRestartAnim ) +{ + if(pSoldier->ubID < 120) + { + //ScreenMsg( FONT_LTGREEN, MSG_CHAT, L"Sending new path" ); + + + EV_S_SENDPATHTONETWORK SNetPath; + + if(pSoldier->ubID < 20) + SNetPath.usSoldierID = (pSoldier->ubID)+ubID_prefix; + else + SNetPath.usSoldierID = pSoldier->ubID; + + SNetPath.sAtGridNo=pSoldier->sGridNo; + + + SNetPath.ubNewState=usMovementAnim; + //if(fFromUI==255)SNetPath.ubNewState=255; + + SNetPath.usCurrentPathIndex=pSoldier->pathing.usPathIndex; + memcpy(SNetPath.usPathData, pSoldier->pathing.usPathingData, sizeof(UINT16)*30); + SNetPath.usPathDataSize=pSoldier->pathing.usPathDataSize; + SNetPath.sDestGridNo=sDestGridNo; + +//this stops soldier from advancing further than one square,and requests "clearance" for another after that... :) + //if(pSoldier->flags.fIsSoldierDelayed==FALSE) + //{ + // pSoldier->flags.fIsSoldierDelayed=TRUE; + // request_ovh(pSoldier->ubID); + //} + + + client->RPC("sendPATH",(const char*)&SNetPath, (int)sizeof(EV_S_SENDPATHTONETWORK)*8, HIGH_PRIORITY, RELIABLE, 0, UNASSIGNED_SYSTEM_ADDRESS, true, 0, UNASSIGNED_NETWORK_ID,0); + } + +} + +void recievePATH(RPCParameters *rpcParameters) +{ + + //ScreenMsg( FONT_LTGREEN, MSG_CHAT, L"Recieving new path," ); + + EV_S_SENDPATHTONETWORK* SNetPath = (EV_S_SENDPATHTONETWORK*)rpcParameters->input; + + SOLDIERTYPE *pSoldier = MercPtrs[ SNetPath->usSoldierID ]; + + + memcpy(pSoldier->pathing.usPathingData, SNetPath->usPathData,sizeof(UINT16)*30); + + pSoldier->pathing.sDestination = SNetPath->sDestGridNo; + pSoldier->pathing.sFinalDestination = SNetPath->sDestGridNo; + pSoldier->pathing.usPathIndex=SNetPath->usCurrentPathIndex; + pSoldier->pathing.usPathDataSize=SNetPath->usPathDataSize; + + SendGetNewSoldierPathEvent( pSoldier, SNetPath->sDestGridNo, SNetPath->ubNewState ); + + INT16 sCellX, sCellY; + + + sCellX = CenterX( SNetPath->sAtGridNo ); + sCellY = CenterY( SNetPath->sAtGridNo ); + + //if ( !( ( gAnimControl[ pSoldier->usAnimState ].uiFlags & ( ANIM_MOVING | ANIM_SPECIALMOVE ) ) && pSoldier->fNoAPToFinishMove ) && !pSoldier->fPauseAllAnimation ) + if (( gAnimControl[ pSoldier->usAnimState ].uiFlags & ( ANIM_MOVING | ANIM_SPECIALMOVE ) ) && !(pSoldier->flags.fNoAPToFinishMove ) ) + { + } + else + { + pSoldier->EVENT_InternalSetSoldierPosition( sCellX, sCellY ,FALSE, FALSE, FALSE ); + + } + + pSoldier->EVENT_InitNewSoldierAnim( SNetPath->ubNewState, 0, FALSE ); + /* if(SNetPath->ubNewState !=255 ) + { + EVENT_InitNewSoldierAnim( pSoldier, SNetPath->ubNewState, 0, FALSE ); + + }*/ + ////ScreenMsg( FONT_LTGREEN, MSG_CHAT, L"state: %d",SNetPath->ubNewState ); + + //if(pSoldier->flags.fIsSoldierDelayed==FALSE) + //{ + // pSoldier->flags.fIsSoldierDelayed=TRUE; + // request_ovh(pSoldier->ubID); + //} + + +} + + +void send_stance ( SOLDIERTYPE *pSoldier, UINT8 ubDesiredStance ) + +{ + if(pSoldier->ubID < 120) + { + EV_S_CHANGESTANCE SChangeStance; + + SChangeStance.ubNewStance = ubDesiredStance; + //SChangeStance.usSoldierID = pSoldier->ubID; + + + if(pSoldier->ubID < 20) + SChangeStance.usSoldierID = (pSoldier->ubID)+ubID_prefix; + else + SChangeStance.usSoldierID = pSoldier->ubID; + + + SChangeStance.sXPos = pSoldier->sX; + SChangeStance.sYPos = pSoldier->sY; + SChangeStance.uiUniqueId = pSoldier -> uiUniqueSoldierIdValue; + //ScreenMsg( FONT_LTGREEN, MSG_CHAT, L"change stance: %d",ubDesiredStance ); + + client->RPC("sendSTANCE",(const char*)&SChangeStance, (int)sizeof(EV_S_CHANGESTANCE)*8, HIGH_PRIORITY, RELIABLE, 0, UNASSIGNED_SYSTEM_ADDRESS, true, 0, UNASSIGNED_NETWORK_ID,0); + } +} + + +void recieveSTANCE(RPCParameters *rpcParameters) +{ + + + EV_S_CHANGESTANCE* SChangeStance = (EV_S_CHANGESTANCE*)rpcParameters->input; + + SOLDIERTYPE *pSoldier = MercPtrs[ SChangeStance->usSoldierID ]; + + pSoldier->ChangeSoldierStance( SChangeStance->ubNewStance ); + + //SendChangeSoldierStanceEvent( pSoldier, SChangeStance->ubNewStance ); + //AddGameEvent( S_CHANGESTANCE, 0, &SChangeStance ); + //********* implemented using event pump system ... :) +} + + + +void send_dir ( SOLDIERTYPE *pSoldier, UINT16 usDesiredDirection ) + +{ + if((is_server && pSoldier->ubID < 120) || (!is_server && pSoldier->ubID < 20)) + { + + EV_S_SETDESIREDDIRECTION SSetDesiredDirection; + + //SSetDesiredDirection.usSoldierID = pSoldier->ubID; + + + if(pSoldier->ubID < 20) + SSetDesiredDirection.usSoldierID = (pSoldier->ubID)+ubID_prefix; + else + SSetDesiredDirection.usSoldierID = pSoldier->ubID; + + + + SSetDesiredDirection.usDesiredDirection = usDesiredDirection; + SSetDesiredDirection.uiUniqueId = pSoldier -> uiUniqueSoldierIdValue; + + client->RPC("sendDIR",(const char*)&SSetDesiredDirection, (int)sizeof(EV_S_SETDESIREDDIRECTION)*8, HIGH_PRIORITY, RELIABLE, 0, UNASSIGNED_SYSTEM_ADDRESS, true, 0, UNASSIGNED_NETWORK_ID,0); + } +} + + +void recieveDIR(RPCParameters *rpcParameters) +{ + + EV_S_SETDESIREDDIRECTION* SSetDesiredDirection = (EV_S_SETDESIREDDIRECTION*)rpcParameters->input; + + + SOLDIERTYPE *pSoldier = MercPtrs[ SSetDesiredDirection->usSoldierID ]; + + pSoldier->EVENT_SetSoldierDesiredDirection( SSetDesiredDirection->usDesiredDirection ); + + //AddGameEvent( S_SETDESIREDDIRECTION, 0, &SSetDesiredDirection ); + //********* implemented using event pump system ... :) +} + +void send_fire( SOLDIERTYPE *pSoldier, INT16 sTargetGridNo ) +{ + if(pSoldier->ubID < 120) + { + + EV_S_BEGINFIREWEAPON SBeginFireWeapon; + + + + + if(pSoldier->ubID < 20) + SBeginFireWeapon.usSoldierID = (pSoldier->ubID)+ubID_prefix; + else + SBeginFireWeapon.usSoldierID = pSoldier->ubID; + + + SBeginFireWeapon.sTargetGridNo = sTargetGridNo; + SBeginFireWeapon.bTargetLevel = pSoldier->bTargetLevel; + SBeginFireWeapon.bTargetCubeLevel = pSoldier->bTargetCubeLevel; + SBeginFireWeapon.uiUniqueId = pSoldier->usAttackingWeapon; + + + client->RPC("sendFIRE",(const char*)&SBeginFireWeapon, (int)sizeof(EV_S_BEGINFIREWEAPON)*8, HIGH_PRIORITY, RELIABLE, 0, UNASSIGNED_SYSTEM_ADDRESS, true, 0, UNASSIGNED_NETWORK_ID,0); + } +} + +void recieveFIRE(RPCParameters *rpcParameters) +{ + + EV_S_BEGINFIREWEAPON* SBeginFireWeapon = (EV_S_BEGINFIREWEAPON*)rpcParameters->input; + //ScreenMsg( FONT_MCOLOR_LTYELLOW, MSG_INTERFACE, L"SendBeginFireWeaponEvent" ); + + SOLDIERTYPE *pSoldier = MercPtrs[ SBeginFireWeapon->usSoldierID ]; + + pSoldier->sTargetGridNo = SBeginFireWeapon->sTargetGridNo; + pSoldier->bTargetLevel = SBeginFireWeapon->bTargetLevel; + pSoldier->bTargetCubeLevel = SBeginFireWeapon->bTargetCubeLevel; + pSoldier->usAttackingWeapon = SBeginFireWeapon->uiUniqueId; //cheap hack to pass wep id. + + + SendBeginFireWeaponEvent( pSoldier, SBeginFireWeapon->sTargetGridNo ); +} + + + +void send_hit( EV_S_WEAPONHIT *SWeaponHit ) +{ + + //ScreenMsg( FONT_MCOLOR_LTYELLOW, MSG_INTERFACE, L"sendHIT" ); + //EV_S_WEAPONHIT* pWeaponHit = (EV_S_WEAPONHIT*)pEventData; + //SOLDIERTYPE *pSoldier = MercPtrs[ usSoldierID ]; + + EV_S_WEAPONHIT weaphit_struct; + + memcpy( &weaphit_struct , SWeaponHit, sizeof( EV_S_WEAPONHIT )); + + UINT16 usSoldierID=weaphit_struct.usSoldierID; + + if(SWeaponHit->usSoldierID < 20)weaphit_struct.usSoldierID = weaphit_struct.usSoldierID+ubID_prefix; + if(SWeaponHit->ubAttackerID < 20)weaphit_struct.ubAttackerID = weaphit_struct.ubAttackerID+ubID_prefix; + + + client->RPC("sendHIT",(const char*)&weaphit_struct, (int)sizeof(EV_S_WEAPONHIT)*8, HIGH_PRIORITY, RELIABLE, 0, UNASSIGNED_SYSTEM_ADDRESS, true, 0, UNASSIGNED_NETWORK_ID,0); + +} + +void recieveHIT(RPCParameters *rpcParameters) +{ + + EV_S_WEAPONHIT* SWeaponHit = (EV_S_WEAPONHIT*)rpcParameters->input; + //ScreenMsg( FONT_MCOLOR_LTYELLOW, MSG_INTERFACE, L"recieveHIT" ); + + SOLDIERTYPE *pSoldier = MercPtrs[ SWeaponHit->usSoldierID ]; + UINT16 usSoldierID; + UINT8 ubAttackerID; + + if((SWeaponHit->usSoldierID >= ubID_prefix) && (SWeaponHit->usSoldierID < (ubID_prefix+7))) // within our netbTeam range... + usSoldierID = (SWeaponHit->usSoldierID - ubID_prefix); + else + usSoldierID = SWeaponHit->usSoldierID; + + if((SWeaponHit->ubAttackerID >= ubID_prefix) && (SWeaponHit->ubAttackerID < (ubID_prefix+7))) + ubAttackerID = (SWeaponHit->ubAttackerID - ubID_prefix); + else + ubAttackerID = SWeaponHit->ubAttackerID; + + + + //AddGameEvent( S_WEAPONHIT, 0, &SWeaponHit ); + WeaponHit( usSoldierID, SWeaponHit->usWeaponIndex, SWeaponHit->sDamage, SWeaponHit->sBreathLoss, SWeaponHit->usDirection, SWeaponHit->sXPos, SWeaponHit->sYPos, SWeaponHit->sZPos, SWeaponHit->sRange, ubAttackerID, SWeaponHit->fHit, SWeaponHit->ubSpecial, SWeaponHit->ubLocation ); + + if(SWeaponHit->fStopped) + { + INT8 bTeam=pSoldier->bTeam; + INT32 iBullet = bTable[bTeam][SWeaponHit->iBullet].local_id; + + RemoveBullet(iBullet); + //ScreenMsg( FONT_MCOLOR_LTYELLOW, MSG_INTERFACE, L"removed bullet" ); + + + } + +} + +void send_hire( UINT8 iNewIndex, UINT8 ubCurrentSoldier, INT16 iTotalContractLength, BOOLEAN fCopyProfileItemsOver) +{ + + { + + send_hire_struct sHireMerc; + + sHireMerc.ubProfileID=ubCurrentSoldier; + //sHireMerc.iTotalContractLength=iTotalContractLength; + sHireMerc.team=TEAM; + sHireMerc.fCopyProfileItemsOver=fCopyProfileItemsOver; + + + sHireMerc.bTeam=netbTeam; + + SOLDIERTYPE *pSoldier = MercPtrs[ iNewIndex ]; + pSoldier->ubStrategicInsertionCode=(atoi(SECT_EDGE)); // this sets the param read from the ini for your starting sector edge... + + ScreenMsg( FONT_LTGREEN, MSG_CHAT, MPClientMessage[44], pSoldier->name); + + + AddCharacterToAnySquad( pSoldier ); + AddSoldierToSector( pSoldier->ubID ); //add g\hired merc to sector so can access sector inv. + + //add recruited flag + gMercProfiles[ pSoldier->ubProfile ].ubMiscFlags |= PROFILE_MISC_FLAG_RECRUITED; + + OBJECTTYPE Object; + int cnt; + for (cnt=0; cnt<20;cnt++) + { + int item=kit[cnt]; + + if(item != 0) + { + CreateItem( item, 100, &Object ); + AutoPlaceObject( pSoldier, &Object, TRUE ); + } + } + + + + + //if (pSoldier->ubID==0) + //{ + // ///create crate apon first hire + ////crate_usMapPos = MAPROWCOLTOPOS( crate_sGridY, crate_sGridX ); + //crate_usMapPos = ChooseMapEdgepoint(pSoldier->ubStrategicInsertionCode); + + ////crate_usMapPos = ChooseMapEdgepoint(atoi(SECT_EDGE)); + //AddStructToUnLoadedMapTempFile( crate_usMapPos, SECONDOSTRUCT3, gsMercArriveSectorX, gsMercArriveSectorY, 0 ); + //} + + + + + + client->RPC("sendHIRE",(const char*)&sHireMerc, (int)sizeof(send_hire_struct)*8, HIGH_PRIORITY, RELIABLE, 0, UNASSIGNED_SYSTEM_ADDRESS, true, 0, UNASSIGNED_NETWORK_ID,0); + } +} + +void recieveHIRE(RPCParameters *rpcParameters) +{ + + send_hire_struct* sHireMerc = (send_hire_struct*)rpcParameters->input; + + + + SOLDIERTYPE *pSoldier; + UINT8 iNewIndex; + UINT8 ubCount=0; + + + SOLDIERCREATE_STRUCT MercCreateStruct; + BOOLEAN fReturn = FALSE; + + + + memset( &MercCreateStruct, 0, sizeof( MercCreateStruct ) ); + MercCreateStruct.ubProfile = sHireMerc->ubProfileID; + MercCreateStruct.fPlayerMerc = 0; + MercCreateStruct.sSectorX = gsMercArriveSectorX; + MercCreateStruct.sSectorY = gsMercArriveSectorY; + MercCreateStruct.bSectorZ = 0; + MercCreateStruct.bTeam = sHireMerc->bTeam; + MercCreateStruct.fCopyProfileItemsOver = sHireMerc->fCopyProfileItemsOver; + + + + TacticalCreateSoldier( &MercCreateStruct, &iNewIndex ) ; + + pSoldier = &Menptr[iNewIndex]; + pSoldier->flags.uiStatusFlags |= SOLDIER_PC; + if(!SAME_MERC)gMercProfiles[ pSoldier->ubProfile ].bMercStatus = MERC_WORKING_ELSEWHERE; + pSoldier->bSide=0; //default coop only + if(PLAYER_BSIDE==0)//all vs all only + { + pSoldier->bSide=1; + //if(MercCreateStruct.bTeam==6)pSoldier->bSide=OP_TEAM_1; + // if(MercCreateStruct.bTeam==7)pSoldier->bSide=OP_TEAM_2; + // if(MercCreateStruct.bTeam==8)pSoldier->bSide=OP_TEAM_3; + // if(MercCreateStruct.bTeam==9)pSoldier->bSide=OP_TEAM_4; + + } + if(PLAYER_BSIDE==1) //allow teams + { + if(sHireMerc->team != TEAM)pSoldier->bSide=1; + + } + + + AddSoldierToSector( iNewIndex ); + + + if(REPORT_NAME==1) + { + ScreenMsg( FONT_LTGREEN, MSG_CHAT, MPClientMessage[5],MercCreateStruct.bTeam-5,client_names[MercCreateStruct.bTeam-6],pSoldier->name ); + } + else + { + ScreenMsg( FONT_LTGREEN, MSG_CHAT, MPClientMessage[6],MercCreateStruct.bTeam-5,client_names[MercCreateStruct.bTeam-6] ); + } + + +} + +void send_gui_pos(SOLDIERTYPE *pSoldier, FLOAT dNewXPos, FLOAT dNewYPos) +{ + + { + + gui_pos gnPOS; + + + + + gnPOS.usSoldierID = (pSoldier->ubID)+ubID_prefix; + + gnPOS.dNewXPos = dNewXPos; + gnPOS.dNewYPos = dNewYPos; + //ScreenMsg( FONT_MCOLOR_LTYELLOW, MSG_INTERFACE, L"guiPOS: %f , %f", dNewXPos,dNewYPos); + + + client->RPC("sendguiPOS",(const char*)&gnPOS, (int)sizeof(gui_pos)*8, HIGH_PRIORITY, RELIABLE, 0, UNASSIGNED_SYSTEM_ADDRESS, true, 0, UNASSIGNED_NETWORK_ID,0); + } + +} +void recieveguiPOS(RPCParameters *rpcParameters) +{ + //ScreenMsg( FONT_MCOLOR_LTYELLOW, MSG_INTERFACE, L"recieveguiPOS" ); + gui_pos* gnPOS = (gui_pos*)rpcParameters->input; + + SOLDIERTYPE *pSoldier = MercPtrs[ gnPOS->usSoldierID ]; + + //ScreenMsg( FONT_MCOLOR_LTYELLOW, MSG_INTERFACE, L"guiPOS: %f , %f", gnPOS->dNewXPos,gnPOS->dNewYPos); + + INT16 sNewGridNo; + + sNewGridNo = GETWORLDINDEXFROMWORLDCOORDS(gnPOS->dNewXPos, gnPOS->dNewYPos ); + pSoldier->usStrategicInsertionData=sNewGridNo; + pSoldier->ubStrategicInsertionCode=INSERTION_CODE_GRIDNO; + pSoldier->sInsertionGridNo = pSoldier->usStrategicInsertionData; + + + pSoldier->EVENT_SetSoldierPosition( gnPOS->dNewXPos, gnPOS->dNewYPos ); + +} + +void send_gui_dir(SOLDIERTYPE *pSoldier, UINT16 usNewDirection) +{ + + { + + gui_dir gnDIR; + + + + gnDIR.usSoldierID = (pSoldier->ubID)+ubID_prefix; + gnDIR.usNewDirection = usNewDirection; + + + + client->RPC("sendguiDIR",(const char*)&gnDIR, (int)sizeof(gui_dir)*8, HIGH_PRIORITY, RELIABLE, 0, UNASSIGNED_SYSTEM_ADDRESS, true, 0, UNASSIGNED_NETWORK_ID,0); + } + +} + +void recieveguiDIR(RPCParameters *rpcParameters) +{ + //ScreenMsg( FONT_MCOLOR_LTYELLOW, MSG_INTERFACE, L"recieveguiDIR" ); + gui_dir* gnDIR = (gui_dir*)rpcParameters->input; + + SOLDIERTYPE *pSoldier = MercPtrs[ gnDIR->usSoldierID ]; + + pSoldier->EVENT_SetSoldierDirection( gnDIR->usNewDirection ); + //pSoldier->ubInsertionDirection = pSoldier->bDirection; +} + + + + +void send_EndTurn( UINT8 ubNextTeam ) +{ + + { + //ScreenMsg( FONT_MCOLOR_LTYELLOW, MSG_INTERFACE, L"sendEndTurn" ); + + if(ubNextTeam==0) + { + ubNextTeam=netbTeam; + } + + + turn_struct tStruct; + + tStruct.tsnetbTeam = netbTeam; + tStruct.tsubNextTeam = ubNextTeam; + + client->RPC("sendEndTurn",(const char*)&tStruct, (int)sizeof(turn_struct)*8, HIGH_PRIORITY, RELIABLE, 0, UNASSIGNED_SYSTEM_ADDRESS, true, 0, UNASSIGNED_NETWORK_ID,0); + } + + +} + +void recieveEndTurn(RPCParameters *rpcParameters) +{ + turn_struct* tStruct = (turn_struct*)rpcParameters->input; + //ScreenMsg( FONT_MCOLOR_LTYELLOW, MSG_INTERFACE, L"recieveEndTurn" ); + UINT8 sender_bTeam; + UINT8 ubTeam; + sender_bTeam=tStruct->tsnetbTeam; + ubTeam=tStruct->tsubNextTeam; + + if(is_server || sender_bTeam==6) + { + if (!is_server && !(gTacticalStatus.uiFlags & INCOMBAT)) + { + EnterCombatMode(0); + } + + + if(ubTeam==netbTeam)ubTeam=0; + { + if(!is_server && is_client) + EndTurnEvents(); + } + + if(!is_server && is_client) + EndTurn( ubTeam ); + requested=false ;//request for realtime made or not + BeginTeamTurn( ubTeam ); + } +} + + +UINT8 numenemyLAN( UINT8 ubSectorX, UINT8 ubSectorY ) +{ + + SOLDIERTYPE *pSoldier; + UINT8 cnt ; //first posible lan player + UINT8 ubNumEnemies = 0; + + + for ( cnt=120 ; cnt <= 155; cnt++ ) + { + pSoldier = MercPtrs[cnt]; + if ( pSoldier->bActive && pSoldier->bInSector && pSoldier->stats.bLife > 0 ) + { + + if ( !pSoldier->aiData.bNeutral && (pSoldier->bSide != 0 ) ) + { + ubNumEnemies++; + } + } + + } + return ubNumEnemies; + +} + +void send_AI( SOLDIERCREATE_STRUCT *pCreateStruct, UINT8 *pubID ) +{ + //ScreenMsg( FONT_LTGREEN, MSG_CHAT, L"send_AI" ); + + //SOLDIERCREATE_STRUCT aaa = *pCreateStruct; + + AI_STRUCT send_inv; + + send_inv.standard_data = *pCreateStruct; + + send_inv.slot0 = pCreateStruct->Inv[ 0 ]; + send_inv.slot1 = pCreateStruct->Inv[ 1 ]; + send_inv.slot2 = pCreateStruct->Inv[ 2]; + send_inv.slot3 = pCreateStruct->Inv[ 3 ]; + send_inv.slot4 = pCreateStruct->Inv[ 4 ]; + send_inv.slot5 = pCreateStruct->Inv[ 5 ]; + send_inv.slot6 = pCreateStruct->Inv[ 6 ]; + send_inv.slot7 = pCreateStruct->Inv[ 7 ]; + send_inv.slot8 = pCreateStruct->Inv[ 8 ]; + send_inv.slot9 = pCreateStruct->Inv[ 9 ]; + send_inv.slot10 = pCreateStruct->Inv[ 10 ]; + send_inv.slot11 = pCreateStruct->Inv[ 11 ]; + send_inv.slot12 = pCreateStruct->Inv[ 12 ]; + send_inv.slot13 = pCreateStruct->Inv[ 13 ]; + send_inv.slot14 = pCreateStruct->Inv[ 14 ]; + send_inv.slot15 = pCreateStruct->Inv[ 15 ]; + send_inv.slot16 = pCreateStruct->Inv[ 16 ]; + send_inv.slot17 = pCreateStruct->Inv[ 17 ]; + send_inv.slot18 = pCreateStruct->Inv[ 18 ]; + + + + client->RPC("sendAI",(const char*)&send_inv, (int)sizeof(AI_STRUCT)*8, HIGH_PRIORITY, RELIABLE, 0, UNASSIGNED_SYSTEM_ADDRESS, true, 0, UNASSIGNED_NETWORK_ID,0); + +} + +void recieveAI (RPCParameters *rpcParameters) +{ + UINT8 iNewIndex; + SOLDIERTYPE *pSoldier; + + + AI_STRUCT* send_inv = (AI_STRUCT*)rpcParameters->input; + + SOLDIERCREATE_STRUCT new_standard_data; //as originally my soldiercreate_struct would get its INV mangled through the RPC, so i send it packaged with it, then create a new struct and add in the bits that are still ok from the original struct, along with the packaged INV components... + + + new_standard_data.bAgility = send_inv->standard_data.bAgility; + new_standard_data.bAIMorale = send_inv->standard_data.bAIMorale; + new_standard_data.bAttitude = send_inv->standard_data.bAttitude; + new_standard_data.bBodyType = send_inv->standard_data.bBodyType; + new_standard_data.bDexterity = send_inv->standard_data.bDexterity; + new_standard_data.ubDirection = send_inv->standard_data.ubDirection; + new_standard_data.bExpLevel = send_inv->standard_data.bExpLevel; + new_standard_data.bExplosive = send_inv->standard_data.bExplosive; + new_standard_data.bLeadership = send_inv->standard_data.bLeadership; + new_standard_data.bLife = send_inv->standard_data.bLife; + new_standard_data.bLifeMax = send_inv->standard_data.bLifeMax; + new_standard_data.bMarksmanship = send_inv->standard_data.bMarksmanship; + new_standard_data.bMechanical = send_inv->standard_data.bMechanical; + new_standard_data.bMedical = send_inv->standard_data.bMedical; + new_standard_data.bMorale = send_inv->standard_data.bMorale; + new_standard_data.bOrders = send_inv->standard_data.bOrders; + memcpy( new_standard_data.PADDINGSLOTS, send_inv->standard_data.PADDINGSLOTS, sizeof( INT8 ) * 14 ); + new_standard_data.bPatrolCnt = send_inv->standard_data.bPatrolCnt; + new_standard_data.bSectorZ = send_inv->standard_data.bSectorZ; + new_standard_data.bStrength = send_inv->standard_data.bStrength; + new_standard_data.bTeam = send_inv->standard_data.bTeam; + new_standard_data.bUseGivenVehicleID = send_inv->standard_data.bUseGivenVehicleID; + new_standard_data.bWisdom = send_inv->standard_data.bWisdom; + //new_standard_data.ef1 = send_inv->standard_data.ef1; + //new_standard_data.ef2 = send_inv->standard_data.ef2; + new_standard_data.endOfPOD = send_inv->standard_data.endOfPOD; + new_standard_data.fCopyProfileItemsOver = send_inv->standard_data.fCopyProfileItemsOver; + new_standard_data.fHasKeys = send_inv->standard_data.fHasKeys; + new_standard_data.fKillSlotIfOwnerDies = send_inv->standard_data.fKillSlotIfOwnerDies; + new_standard_data.fOnRoof = send_inv->standard_data.fOnRoof; + new_standard_data.fPlayerMerc = send_inv->standard_data.fPlayerMerc; + new_standard_data.fPlayerPlan = send_inv->standard_data.fPlayerPlan; + new_standard_data.fStatic = send_inv->standard_data.fStatic; + new_standard_data.fUseExistingSoldier = send_inv->standard_data.fUseExistingSoldier; + new_standard_data.fUseGivenVehicle = send_inv->standard_data.fUseGivenVehicle; + new_standard_data.fVisible = send_inv->standard_data.fVisible; + memcpy( new_standard_data.HeadPal , send_inv->standard_data.HeadPal, sizeof( PaletteRepID )); + memcpy( new_standard_data.MiscPal , send_inv->standard_data.MiscPal, sizeof( PaletteRepID )); + memcpy( new_standard_data.name , send_inv->standard_data.name, sizeof( CHAR16 ) * 10 ); + memcpy( new_standard_data.PantsPal , send_inv->standard_data.PantsPal, sizeof( PaletteRepID )); + new_standard_data.pExistingSoldier = send_inv->standard_data.pExistingSoldier; + new_standard_data.sInsertionGridNo = send_inv->standard_data.sInsertionGridNo; + memcpy( new_standard_data.SkinPal , send_inv->standard_data.SkinPal, sizeof( PaletteRepID )); + memcpy( new_standard_data.sPatrolGrid, send_inv->standard_data.sPatrolGrid, sizeof( INT16 ) * MAXPATROLGRIDS ); + new_standard_data.sSectorX = send_inv->standard_data.sSectorX; + new_standard_data.sSectorY = send_inv->standard_data.sSectorY; + new_standard_data.ubCivilianGroup = send_inv->standard_data.ubCivilianGroup; + new_standard_data.ubProfile = send_inv->standard_data.ubProfile; + new_standard_data.ubScheduleID = send_inv->standard_data.ubScheduleID; + new_standard_data.ubSoldierClass = send_inv->standard_data.ubSoldierClass; + memcpy( new_standard_data.VestPal , send_inv->standard_data.VestPal, sizeof( PaletteRepID )); + + + new_standard_data.Inv[0] = send_inv->slot0; + new_standard_data.Inv[1] = send_inv->slot1; + new_standard_data.Inv[2] = send_inv->slot2; + new_standard_data.Inv[3] = send_inv->slot3; + new_standard_data.Inv[4] = send_inv->slot4; + new_standard_data.Inv[5] = send_inv->slot5; + new_standard_data.Inv[6] = send_inv->slot6; + new_standard_data.Inv[7] = send_inv->slot7; + new_standard_data.Inv[8] = send_inv->slot8; + new_standard_data.Inv[9] = send_inv->slot9; + new_standard_data.Inv[10] = send_inv->slot10; + new_standard_data.Inv[11] = send_inv->slot11; + new_standard_data.Inv[12] = send_inv->slot12; + new_standard_data.Inv[13] = send_inv->slot13; + new_standard_data.Inv[14] = send_inv->slot14; + new_standard_data.Inv[15] = send_inv->slot15; + new_standard_data.Inv[16] = send_inv->slot16; + new_standard_data.Inv[17] = send_inv->slot17; + new_standard_data.Inv[18] = send_inv->slot18; + + new_standard_data.fPlayerPlan=1; + + + TacticalCreateSoldier( &new_standard_data, &iNewIndex ); + pSoldier = &Menptr[iNewIndex]; + pSoldier->flags.uiStatusFlags |= SOLDIER_PC; + + AddSoldierToSector( iNewIndex ); + //ScreenMsg( FONT_LTGREEN, MSG_INTERFACE, L"recieveAI" ); + + + +} + +void send_ready ( void ) +{ + ready_struct info; + info.client_num = CLIENT_NUM; + + if(readystage==0) + { + + info.ready_stage = 0; + if(status==0) + { + info.status = 1; + status=1; + numready = numready+1; + ScreenMsg( FONT_LTGREEN, MSG_CHAT, MPClientMessage[7],numready,MAX_CLIENTS ); + } + else + { + info.status = 0; + status=0; + numready = numready-1; + ScreenMsg( FONT_LTGREEN, MSG_CHAT, MPClientMessage[8],numready,MAX_CLIENTS ); + } + } + + + + if(is_server && numready == MAX_CLIENTS) //all ready. and server tells all to load... + { + ScreenMsg( FONT_LTGREEN, MSG_CHAT, MPClientMessage[9] ); + + goahead=1; + readystage=1; + + info.ready_stage = 1; + info.status = 1; + } + + + + client->RPC("sendREADY",(const char*)&info, (int)sizeof(ready_struct)*8, HIGH_PRIORITY, RELIABLE, 0, UNASSIGNED_SYSTEM_ADDRESS, true, 0, UNASSIGNED_NETWORK_ID,0); + + if(is_server && numready == MAX_CLIENTS) + { + + status=0;//reset + numready=0; + start_battle();//server loads + } +} + +void recieveREADY (RPCParameters *rpcParameters) +{ + ready_struct* info = (ready_struct*)rpcParameters->input; + + if(info->ready_stage==1)//recived ok for go ahead from server for level load + { + numready++; + ScreenMsg( FONT_LTGREEN, MSG_CHAT, MPClientMessage[10], info->client_num,client_names[info->client_num-1],numready,MAX_CLIENTS ); + ScreenMsg( FONT_LTGREEN, MSG_CHAT, MPClientMessage[9] ); + status=0;//reset + numready=0; + goahead=1; + start_battle(); + } + else if (info->ready_stage != 36) // recieved status update from client + { + if (info->status==1) + { + numready = numready+1; + ScreenMsg( FONT_LTGREEN, MSG_CHAT, MPClientMessage[10], info->client_num,client_names[info->client_num-1],numready,MAX_CLIENTS ); + + } + else + { + numready = numready-1; + ScreenMsg( FONT_LTGREEN, MSG_CHAT, MPClientMessage[11], info->client_num,client_names[info->client_num-1],numready,MAX_CLIENTS ); + + } + + if(is_server && numready == MAX_CLIENTS) //all ready. and server tells all to load...and loads himself + { + goahead=1; + readystage=1; + send_ready(); + start_battle(); + + } + } + else if(info->ready_stage==36)//server allows laptop access + { + ScreenMsg( FONT_LTGREEN, MSG_CHAT, MPClientMessage[36] ); + allowlaptop=1; + } + +} + +void send_loaded (void) +{ + ready_struct info; + info.client_num = CLIENT_NUM; + info.ready_stage = 1;//done loading level + info.status=1; + + numready++; + if(numready==MAX_CLIENTS && is_server) + { + lockui(1);//unlock ui + readystage=0; + numready=0; + + info.ready_stage = 2;//done placing mercs + info.status=1; + + //client->RPC("sendGUI",(const char*)&info, (int)sizeof(ready_struct)*8, HIGH_PRIORITY, RELIABLE, 0, UNASSIGNED_SYSTEM_ADDRESS, true, 0, UNASSIGNED_NETWORK_ID,0); + } + + client->RPC("sendGUI",(const char*)&info, (int)sizeof(ready_struct)*8, HIGH_PRIORITY, RELIABLE, 0, UNASSIGNED_SYSTEM_ADDRESS, true, 0, UNASSIGNED_NETWORK_ID,0); + +} + +void send_donegui ( UINT8 ubResult ) +{ + if(ubResult==1 && status==0)return;//avoid double remove callback response from final message box removal + ready_struct info; + info.client_num = CLIENT_NUM; + if(ubResult==1)DialogRemoved(1);//cleanup msgbox after not ready + if(status==0)//now ready + { + status=1; + numready++; + info.ready_stage = 3;//done placing mercs + info.status=1; + + SGPRect CenterRect = { 100, 100, SCREEN_WIDTH - 100, 300 }; + DoMessageBox( MSG_BOX_BASIC_STYLE, MPClientMessage[12], guiCurrentScreen, MSG_BOX_FLAG_OK | MSG_BOX_FLAG_USE_CENTERING_RECT, send_donegui, &CenterRect ); + + + if(numready==MAX_CLIENTS && is_server)//all done + { + + numready=0; + status=0; + info.ready_stage = 4;//done placing mercs + info.status=1; + gMsgBox.bHandled = MSG_BOX_RETURN_OK; + KillTacticalPlacementGUI(); //send and kill + ScreenMsg( FONT_LTBLUE, MSG_CHAT, MPClientMessage[13]); + } + } + else if(status==1)//was ready + { + status=0; + numready--; + info.ready_stage = 3;//not done placing mercs + info.status=0; + } + + + + client->RPC("sendGUI",(const char*)&info, (int)sizeof(ready_struct)*8, HIGH_PRIORITY, RELIABLE, 0, UNASSIGNED_SYSTEM_ADDRESS, true, 0, UNASSIGNED_NETWORK_ID,0); +} + +void recieveGUI (RPCParameters *rpcParameters) +{ + + + ready_struct* info = (ready_struct*)rpcParameters->input; + + if(info->ready_stage==1 && info->status==1) + { + numready++; + if(numready==MAX_CLIENTS && is_server) + { + lockui(1);//unlock ui + readystage=0; + numready=0; + + ready_struct info; + info.client_num = CLIENT_NUM; + info.ready_stage = 2;//done placing mercs + info.status=1; + + client->RPC("sendGUI",(const char*)&info, (int)sizeof(ready_struct)*8, HIGH_PRIORITY, RELIABLE, 0, UNASSIGNED_SYSTEM_ADDRESS, true, 0, UNASSIGNED_NETWORK_ID,0); + } + + } + if(info->ready_stage==2 && info->status ==1) + { + lockui(1);//unlock ui + readystage=0; + numready=0; + + } + + if(info->ready_stage==3 && info->status==1)//recieved client done placement + { + numready++; + if(numready==MAX_CLIENTS && is_server)//all done + { + numready=0; + + ready_struct info; + info.client_num = CLIENT_NUM; + info.ready_stage = 4;//all done placing mercs, kill all + info.status=1; + gMsgBox.bHandled = MSG_BOX_RETURN_OK; + status=0; + KillTacticalPlacementGUI(); + ScreenMsg( FONT_LTBLUE, MSG_CHAT, MPClientMessage[13]); + + client->RPC("sendGUI",(const char*)&info, (int)sizeof(ready_struct)*8, HIGH_PRIORITY, RELIABLE, 0, UNASSIGNED_SYSTEM_ADDRESS, true, 0, UNASSIGNED_NETWORK_ID,0); + } + } + + + if(info->ready_stage==3 && info->status==0)//recieved client retracted place ready... + { + numready--; + } + + if(info->ready_stage==4 && info->status==1) + { + gMsgBox.bHandled = MSG_BOX_RETURN_OK; + KillTacticalPlacementGUI(); + ScreenMsg( FONT_LTBLUE, MSG_CHAT, MPClientMessage[13]); + numready=0; + status=0; + } + +} +void allowlaptop_callback ( UINT8 ubResult ) +{ + + if(ubResult==2) + { + ScreenMsg( FONT_LTGREEN, MSG_CHAT, MPClientMessage[36] ); + allowlaptop=1; + + ready_struct info; + info.client_num = CLIENT_NUM; + info.ready_stage=36; + info.status=1; + + client->RPC("sendREADY",(const char*)&info, (int)sizeof(ready_struct)*8, HIGH_PRIORITY, RELIABLE, 0, UNASSIGNED_SYSTEM_ADDRESS, true, 0, UNASSIGNED_NETWORK_ID,0); + + } +} + + +void start_battle ( void ) +{ +if(!is_client) +{ +ScreenMsg( FONT_LTGREEN, MSG_CHAT, MPClientMessage[14] ); +} +else if(!allowlaptop && is_server) +{ + SGPRect CenterRect = { 100, 100, SCREEN_WIDTH - 100, 300 }; + DoMessageBox( MSG_BOX_BASIC_STYLE, MPClientMessage[35], guiCurrentScreen, MSG_BOX_FLAG_YESNO | MSG_BOX_FLAG_USE_CENTERING_RECT, allowlaptop_callback, &CenterRect ); + +} +else if(allowlaptop) +{ + + if ( NumberOfMercsOnPlayerTeam() ==0) + { + ScreenMsg( FONT_LTGREEN, MSG_CHAT, MPClientMessage[15] ); + } + else if(goahead==1) + { + goahead=0; + status=0;//reset + numready=0; + SOLDIERTYPE *pSoldier = MercPtrs[ 0 ]; + UINT8 ubGroupID = pSoldier->ubGroupID; + + GROUP *pGroup; + pGroup = GetGroup( ubGroupID ); + gpBattleGroup = pGroup; + gubPBSectorX = gpBattleGroup->ubSectorX; + gubPBSectorY = gpBattleGroup->ubSectorY; + gubPBSectorZ = gpBattleGroup->ubSectorZ; + + gfEnterTacticalPlacementGUI = 1; + + UINT32 i; + for(i=0; i<4;i++) + { + CHAR16 name[255]; + int nm = mbstowcs( name, client_names[i], sizeof (char)*30 ); + //copy in client specified name for the player turn bar :) + if(nm) + { + CHAR16 string[255]; + memcpy(string,TeamTurnString[ (i+6) ], sizeof( CHAR16) * 255 ); + + + CHAR16 full[255]; + swprintf(full, L"%s - '%s'",string,name); + + memcpy( TeamTurnString[ (i+6) ] , full, sizeof( CHAR16) * 255 ); + } + } + + SetCurrentWorldSector( gubPBSectorX, gubPBSectorY, gubPBSectorZ ); + } + else + { + send_ready(); + } +} +else if(!allowlaptop && is_client && !is_server) +{ + ScreenMsg( FONT_LTGREEN, MSG_CHAT, MPClientMessage[16] ); +} + +} + +void DropOffItemsInSector( UINT8 ubOrderNum ) +{ + BOOLEAN fSectorLoaded = FALSE; + OBJECTTYPE Object; + UINT32 uiCount = 0; + OBJECTTYPE *pObject=NULL; + UINT16 usNumberOfItems=0, usItem; + UINT8 ubItemsDelivered, ubTempNumItems; + UINT32 i; + + + + // determine if the sector is loaded + if( ( gWorldSectorX == gsMercArriveSectorX ) && ( gWorldSectorY == gsMercArriveSectorY ) && ( gbWorldSectorZ == 0 ) ) + fSectorLoaded = TRUE; + else + fSectorLoaded = FALSE; + + SetSectorFlag( gsMercArriveSectorX, gsMercArriveSectorY, 0, SF_ALREADY_VISITED);//allows update of item count + + + + for(i=0; iubNumberPurchases; i++) + { + ubItemsDelivered = gpNewBobbyrShipments[ ubOrderNum ].BobbyRayPurchase[i].ubNumberPurchased; + usItem = gpNewBobbyrShipments[ ubOrderNum ].BobbyRayPurchase[i].usItemIndex; + + while ( ubItemsDelivered ) + { + // treat 0s as 1s :-) + ubTempNumItems = __min( ubItemsDelivered, __max( 1, Item[ usItem ].ubPerPocket ) ); + CreateItems( usItem, gpNewBobbyrShipments[ ubOrderNum ].BobbyRayPurchase[i].bItemQuality, ubTempNumItems, &Object ); + + // stack as many as possible + if( fSectorLoaded ) + { + AddItemToPool( 12880, &Object, 1, 0, WOLRD_ITEM_FIND_SWEETSPOT_FROM_GRIDNO | WORLD_ITEM_REACHABLE, 0 ); + } + else + { + memcpy( &pObject[ uiCount ], &Object, sizeof( OBJECTTYPE ) ); + uiCount++; + } + + ubItemsDelivered -= ubTempNumItems; + } + } + + //if the sector WASNT loaded + if( !fSectorLoaded ) + { + //add all the items from the array that was built above + + //The item are to be added to the Top part of Drassen, grid loc's 10112, 9950 + if( !AddItemsToUnLoadedSector( gsMercArriveSectorX, gsMercArriveSectorY, 0, 12880, uiCount, pObject, 0, WOLRD_ITEM_FIND_SWEETSPOT_FROM_GRIDNO | WORLD_ITEM_REACHABLE, 0, 1, FALSE ) ) + { + //error + Assert( 0 ); + } + MemFree( pObject ); + pObject = NULL; + } + + //mark that the shipment has arrived + gpNewBobbyrShipments[ ubOrderNum ].fActive = FALSE; +} + + +void send_stop (EV_S_STOP_MERC *SStopMerc) // used to stop a merc when he spots new enemies... +{ + EV_S_STOP_MERC stop_struct; + if(SStopMerc->usSoldierID < 120) + { + //ScreenMsg( FONT_LTGREEN, MSG_INTERFACE, L"send_stop" ); + if(SStopMerc->usSoldierID < 20) + { + stop_struct.usSoldierID = (SStopMerc->usSoldierID)+ubID_prefix; + } + else + stop_struct.usSoldierID = SStopMerc->usSoldierID; + + stop_struct.sGridNo=SStopMerc->sGridNo; + stop_struct.ubDirection=SStopMerc->ubDirection; + stop_struct.fset=SStopMerc->fset; + if(stop_struct.fset==FALSE) + { + //ScreenMsg( FONT_LTGREEN, MSG_INTERFACE, L"skipped" ); + return; + } + stop_struct.sXPos=SStopMerc->sXPos; + stop_struct.sYPos=SStopMerc->sYPos; + client->RPC("sendSTOP",(const char*)&stop_struct, (int)sizeof(EV_S_STOP_MERC)*8, HIGH_PRIORITY, RELIABLE, 0, UNASSIGNED_SYSTEM_ADDRESS, true, 0, UNASSIGNED_NETWORK_ID,0); + } +} + +void recieveSTOP (RPCParameters *rpcParameters) +{ + //ScreenMsg( FONT_LTGREEN, MSG_INTERFACE, L"recieve_stop" ); + + EV_S_STOP_MERC* SStopMerc =(EV_S_STOP_MERC*)rpcParameters->input; + + SOLDIERTYPE *pSoldier = MercPtrs[ SStopMerc->usSoldierID ]; + + //INT16 sCellX, sCellY; + //sCellX = CenterX( SStopMerc->sGridNo ); + //sCellY = CenterY( SStopMerc->sGridNo ); + + + pSoldier->EVENT_InternalSetSoldierPosition( SStopMerc->sXPos, SStopMerc->sYPos,FALSE, FALSE, FALSE ); + pSoldier->EVENT_SetSoldierDirection( SStopMerc->ubDirection ); + //pSoldier->HaultSoldierFromSighting(TRUE); + pSoldier->AdjustNoAPToFinishMove( SStopMerc->fset ); + //EVENT_StopMerc( pSoldier, SStopMerc->sGridNo, SStopMerc->bDirection ); + //pSoldier->AdjustNoAPToFinishMove( TRUE ); + + pSoldier->flags.bTurningFromPronePosition = FALSE; + + + +} + +void send_interrupt (SOLDIERTYPE *pSoldier) +{ + + + INT_STRUCT INT; + + INT.ubID = pSoldier->ubID; + INT.bTeam = pSoldier->bTeam; + memcpy(INT.gubOutOfTurnOrder, gubOutOfTurnOrder, sizeof(UINT8) * MAXMERCS); + INT.gubOutOfTurnPersons = gubOutOfTurnPersons; + + INT.Interrupted=gusSelectedSoldier+ubID_prefix; + + + if(INT.bTeam==0) + { + INT.bTeam=netbTeam; + INT.ubID=INT.ubID+ubID_prefix; + } + + for(int i=0; i <= INT.gubOutOfTurnPersons; i++) + { + if(INT.gubOutOfTurnOrder[i] < 20) + { + INT.gubOutOfTurnOrder[i]=INT.gubOutOfTurnOrder[i]+ubID_prefix; + } + } + + //if(gubOutOfTurnPersons>0)ScreenMsg( FONT_MCOLOR_LTYELLOW, MSG_INTERFACE, L"Sent Int: bTeam-%d ubID-%d", INT.bTeam,INT.ubID ); + + gTacticalStatus.ubCurrentTeam=INT.bTeam; + + client->RPC("sendINTERRUPT",(const char*)&INT, (int)sizeof(INT_STRUCT)*8, HIGH_PRIORITY, RELIABLE, 0, UNASSIGNED_SYSTEM_ADDRESS, true, 0, UNASSIGNED_NETWORK_ID,0); + + +} + +void recieveINTERRUPT (RPCParameters *rpcParameters) +{ + INT_STRUCT* INT = (INT_STRUCT*)rpcParameters->input; + + + if(INT->bTeam==netbTeam) + { + INT->bTeam=0; + INT->ubID=INT->ubID - ubID_prefix; + + for(int i=0; i <= INT->gubOutOfTurnPersons; i++) + { + if((INT->gubOutOfTurnOrder[i] >= ubID_prefix) && (INT->gubOutOfTurnOrder[i] < (ubID_prefix+5))) + { + INT->gubOutOfTurnOrder[i]=INT->gubOutOfTurnOrder[i]-ubID_prefix; + } + } + memcpy(gubOutOfTurnOrder,INT->gubOutOfTurnOrder, sizeof(UINT8) * MAXMERCS); + gubOutOfTurnPersons = INT->gubOutOfTurnPersons; + + } + + if( INT->bTeam !=0) + { + ScreenMsg( FONT_MCOLOR_LTYELLOW, MSG_INTERFACE, MPClientMessage[17] ); + //stop moving merc who was interrupted and init UI bar + SOLDIERTYPE* pMerc = MercPtrs[ INT->ubID ]; + //AdjustNoAPToFinishMove( pMerc, TRUE ); + pMerc->HaultSoldierFromSighting(TRUE); + //pMerc->fTurningFromPronePosition = FALSE;// hmmm ?? + FreezeInterfaceForEnemyTurn(); + InitEnemyUIBar( 0, 0 ); + fInterfacePanelDirty = DIRTYLEVEL2; + AddTopMessage( COMPUTER_TURN_MESSAGE, TeamTurnString[ INT->bTeam ] ); + gTacticalStatus.fInterruptOccurred = TRUE; + + } + else + { + //it for us ! :) + if(INT->gubOutOfTurnPersons==0)//indicates finished interrupt maybe can just call end interrupt + { + ScreenMsg( FONT_MCOLOR_LTYELLOW, MSG_INTERFACE, L"old int finish" ); + //prob never get here again, and can be removed later + + } + else //start our interrupt turn + { + ScreenMsg( FONT_MCOLOR_LTYELLOW, MSG_INTERFACE, MPClientMessage[37] ); + + SOLDIERTYPE* pSoldier = MercPtrs[ INT->ubID ]; + SOLDIERTYPE* pOpponent = MercPtrs[ INT->Interrupted]; + ManSeesMan(pSoldier,pOpponent,pOpponent->sGridNo,pOpponent->pathing.bLevel,2,1); + StartInterrupt(); + } + } + + + //if(INT->gubOutOfTurnPersons > 0)ScreenMsg( FONT_MCOLOR_LTYELLOW, MSG_INTERFACE, L"Recieved Int: bTeam-%d ubID-%d", INT->bTeam,INT->ubID ); +} + +void end_interrupt ( BOOLEAN fMarkInterruptOccurred ) +{ + + + SOLDIERTYPE * pSoldier = MercPtrs[(gubOutOfTurnOrder[gubOutOfTurnPersons])]; + + + INT_STRUCT INT; + + INT.ubID = pSoldier->ubID; + INT.bTeam = pSoldier->bTeam; + memcpy(INT.gubOutOfTurnOrder, gubOutOfTurnOrder, sizeof(UINT8) * MAXMERCS); + INT.gubOutOfTurnPersons = gubOutOfTurnPersons; + INT.fMarkInterruptOccurred=fMarkInterruptOccurred; + + if(INT.bTeam==0) + { + INT.bTeam=netbTeam; + INT.ubID=INT.ubID+ubID_prefix; + } + + for(int i=0; i <= INT.gubOutOfTurnPersons; i++) + { + if(INT.gubOutOfTurnOrder[i] < 20) + { + INT.gubOutOfTurnOrder[i]=INT.gubOutOfTurnOrder[i]+ubID_prefix; + } + } + + + + client->RPC("endINTERRUPT",(const char*)&INT, (int)sizeof(INT_STRUCT)*8, HIGH_PRIORITY, RELIABLE, 0, UNASSIGNED_SYSTEM_ADDRESS, true, 0, UNASSIGNED_NETWORK_ID,0); + + +} + +void resume_turn(RPCParameters *rpcParameters) +{ + INT_STRUCT* INT = (INT_STRUCT*)rpcParameters->input; + + if(INT->bTeam==netbTeam)//may need working + { + ScreenMsg( FONT_MCOLOR_LTYELLOW, MSG_INTERFACE, MPClientMessage[18] ); + + for(int i=0; i <= INT->gubOutOfTurnPersons; i++) + { + if((INT->gubOutOfTurnOrder[i] >= ubID_prefix) && (INT->gubOutOfTurnOrder[i] < (ubID_prefix+5))) + { + INT->gubOutOfTurnOrder[i]=INT->gubOutOfTurnOrder[i]-ubID_prefix; + } + } + + memcpy(gubOutOfTurnOrder,INT->gubOutOfTurnOrder, sizeof(UINT8) * MAXMERCS); + gubOutOfTurnPersons = INT->gubOutOfTurnPersons; + + + + EndInterrupt( INT->fMarkInterruptOccurred ); + } +} + +void grid_display ( void ) //print mouse coordinates, helpfull for crate placement. +{ + INT16 sGridX, sGridY; + UINT16 usMapPos; + + GetMouseXY( &sGridX, &sGridY ); + usMapPos = MAPROWCOLTOPOS( sGridY, sGridX ); + + ScreenMsg( FONT_MCOLOR_LTYELLOW, MSG_INTERFACE, MPClientMessage[19] ); + ScreenMsg( FONT_MCOLOR_LTYELLOW, MSG_INTERFACE, MPClientMessage[20], sGridX, sGridY ); + ScreenMsg( FONT_MCOLOR_LTYELLOW, MSG_INTERFACE, MPClientMessage[21], usMapPos ); +} + +void mp_help(void) +{ + ScreenMsg( MSG_FONT_WHITE, MSG_CHAT, L" "); + ScreenMsg( MSG_FONT_WHITE, MSG_CHAT, MPHelp[2]); + ScreenMsg( MSG_FONT_WHITE, MSG_CHAT, MPHelp[3]); + ScreenMsg( MSG_FONT_WHITE, MSG_CHAT, L" "); + ScreenMsg( MSG_FONT_WHITE, MSG_CHAT, MPHelp[4]); + ScreenMsg( MSG_FONT_WHITE, MSG_CHAT, MPHelp[5]); + ScreenMsg( MSG_FONT_WHITE, MSG_CHAT, MPHelp[6]); + ScreenMsg( MSG_FONT_WHITE, MSG_CHAT, MPHelp[7]); + ScreenMsg( MSG_FONT_WHITE, MSG_CHAT, MPHelp[8]); + ScreenMsg( MSG_FONT_WHITE, MSG_CHAT, MPHelp[9]); + ScreenMsg( MSG_FONT_WHITE, MSG_CHAT, MPHelp[10]); + ScreenMsg( MSG_FONT_WHITE, MSG_CHAT, L" "); + ScreenMsg( MSG_FONT_WHITE, MSG_CHAT, MPHelp[11]); + + + +} + +void mp_help2(void) +{ + ScreenMsg( MSG_FONT_WHITE, MSG_CHAT, L" "); + ScreenMsg( MSG_FONT_WHITE, MSG_CHAT, MPHelp[12]); + ScreenMsg( MSG_FONT_WHITE, MSG_CHAT, L" "); + ScreenMsg( MSG_FONT_WHITE, MSG_CHAT, MPHelp[13]); + + ScreenMsg( MSG_FONT_WHITE, MSG_CHAT, MPHelp[14]); + + + ScreenMsg( MSG_FONT_WHITE, MSG_CHAT, MPHelp[15]); + + ScreenMsg( MSG_FONT_WHITE, MSG_CHAT, L" "); + ScreenMsg( MSG_FONT_WHITE, MSG_CHAT, MPHelp[16]); + ScreenMsg( MSG_FONT_WHITE, MSG_CHAT, MPHelp[11]); + +} + +void manual_overide (void)//now bound to "7" +{ + if(is_server) + { + //manual overide command for server + const STR16 msg = MPClientMessage[23]; + + SGPRect CenterRect = { 100, 100, SCREEN_WIDTH - 100, 300 }; + DoMessageBox( MSG_BOX_BASIC_STYLE, msg, guiCurrentScreen, MSG_BOX_FLAG_FOUR_NUMBERED_BUTTONS | MSG_BOX_FLAG_USE_CENTERING_RECT, overide_callback, &CenterRect ); + + } + else ScreenMsg( FONT_LTGREEN, MSG_INTERFACE, MPClientMessage[22] ); + +} + +void overide_callback( UINT8 ubResult ) +{ + if(is_server) + { + if(ubResult==1) + { + allowlaptop=true; + } + if(ubResult==2)//overide stop #1 (awaiting client ready for launch/load) + + + { + goahead=0; + status=0;//reset + numready=0; + SOLDIERTYPE *pSoldier = MercPtrs[ 0 ]; + UINT8 ubGroupID = pSoldier->ubGroupID; + + GROUP *pGroup; + pGroup = GetGroup( ubGroupID ); + gpBattleGroup = pGroup; + gubPBSectorX = gpBattleGroup->ubSectorX; + gubPBSectorY = gpBattleGroup->ubSectorY; + gubPBSectorZ = gpBattleGroup->ubSectorZ; + + gfEnterTacticalPlacementGUI = 1; + + + + goahead=1; + readystage=1; + ready_struct info; //send + info.client_num = CLIENT_NUM; + info.ready_stage = 1; + info.status = 1; + + + + + client->RPC("sendREADY",(const char*)&info, (int)sizeof(ready_struct)*8, HIGH_PRIORITY, RELIABLE, 0, UNASSIGNED_SYSTEM_ADDRESS, true, 0, UNASSIGNED_NETWORK_ID,0); + + status=0;//reset + numready=0; + + SetCurrentWorldSector( gubPBSectorX, gubPBSectorY, gubPBSectorZ ); //load + } + + + if(ubResult==3) + { + lockui(1);//unlock ui paused while wainting for loaders + + ready_struct info; + info.client_num = CLIENT_NUM; + readystage=0; + numready=0; + info.ready_stage = 2;//done placing mercs + info.status=1; + client->RPC("sendGUI",(const char*)&info, (int)sizeof(ready_struct)*8, HIGH_PRIORITY, RELIABLE, 0, UNASSIGNED_SYSTEM_ADDRESS, true, 0, UNASSIGNED_NETWORK_ID,0); + + } + if(ubResult==4) //overide waiting on merc placement + { + numready=0; + + ready_struct info; //send + info.client_num = CLIENT_NUM; + info.ready_stage = 4;//all done placing mercs, kill all + info.status=1; + gMsgBox.bHandled = MSG_BOX_RETURN_OK; + status=0; + KillTacticalPlacementGUI(); //kill + ScreenMsg( FONT_LTBLUE, MSG_CHAT, MPClientMessage[13]); + + client->RPC("sendGUI",(const char*)&info, (int)sizeof(ready_struct)*8, HIGH_PRIORITY, RELIABLE, 0, UNASSIGNED_SYSTEM_ADDRESS, true, 0, UNASSIGNED_NETWORK_ID,0); + + } + + + goahead = 0; + numready = 0; + readystage = 0; + status = 0; + + + + } +} + +void requestSETTINGS(void) +{ + client_info cl_name; + //cl_name.client_num=CLIENT_NUM; + strcpy(cl_name.client_name , CLIENT_NAME); + cl_name.team=TEAM; + //cl_name.cl_ops[1]=OP_TEAM_2; + //cl_name.cl_ops[2]=OP_TEAM_3; + //cl_name.cl_ops[3]=OP_TEAM_4; + cl_name.cl_edge=atoi(SECT_EDGE); + + + client->RPC("requestSETTINGS",(const char*)&cl_name, (int)sizeof(client_info)*8, HIGH_PRIORITY, RELIABLE, 0, UNASSIGNED_SYSTEM_ADDRESS, true, 0, UNASSIGNED_NETWORK_ID,0); + +} + + + + +void recieveSETTINGS (RPCParameters *rpcParameters) //recive settings from server +{ + + settings_struct* cl_lan = (settings_struct*)rpcParameters->input; + + char szDefault[30]; + sprintf(szDefault, "%s",cl_lan->client_name); + + if(!recieved_settings) + { + recieved_settings=1; + + CLIENT_NUM=cl_lan->client_num;//assign client number from server + + netbTeam = (CLIENT_NUM)+5; + ubID_prefix = gTacticalStatus.Team[ netbTeam ].bFirstID;//over here now + + memcpy( client_names , cl_lan->client_names, sizeof( char ) * 4 * 30 ); + + strcpy(client_names[cl_lan->client_num-1],szDefault); + + + ScreenMsg( FONT_LTGREEN, MSG_CHAT, MPClientMessage[2] ); + + + MAX_CLIENTS=cl_lan->max_clients; + memcpy( ckbag, cl_lan->kitbag, sizeof(char)*100); + + int cnt; + int numnum = 0; + int kitnum = 0; + char tempstring[4]; + memset( &kit, 0, sizeof( int )*20 ); + + for(cnt=0; cnt < 100; cnt++) + { + char tempc = ckbag[cnt]; + + if( _strnicmp(&tempc, "[",1) == 0) + { + + continue; + } + + else if( _strnicmp(&tempc, ",",1) == 0) + { + numnum=0; + + kit[kitnum]=atoi(tempstring); + + memset( &tempstring, 0, sizeof( char )*4 ); + + kitnum++; + continue; + } + + else if( _strnicmp(&tempc, "]",1) == 0) + { + kit[kitnum]=atoi(tempstring); + break; + } + else + { + strncpy(&tempstring[numnum],&tempc,1); + numnum++; + //temp = atoi(tempstring); + } + } + + + DAMAGE_MULTIPLIER=cl_lan->damage_multiplier; + SAME_MERC=cl_lan->same_merc; + + + gsMercArriveSectorX=cl_lan->gsMercArriveSectorX; + gsMercArriveSectorY=cl_lan->gsMercArriveSectorY; + + PLAYER_BSIDE=cl_lan->gsPLAYER_BSIDE; + DISABLE_MORALE=cl_lan->emorale; + ChangeSelectedMapSector( gsMercArriveSectorX, gsMercArriveSectorY, 0 ); + CHAR16 str[128]; + GetSectorIDString( gsMercArriveSectorX, gsMercArriveSectorY, 0, str, TRUE ); + //new --------- + gGameOptions.fTurnTimeLimit=cl_lan->sofTurnTimeLimit; + INT32 secs_per_tick=cl_lan->secs_per_tick; + PLAYER_TEAM_TIMER_SEC_PER_TICKS=secs_per_tick; + + INT32 clstarting_balance=cl_lan->starting_balance;//set starting balance + + if(LaptopSaveInfo.iCurrentBalancesofGunNut; + gGameOptions.ubGameStyle=cl_lan->soubGameStyle; + gGameOptions.ubDifficultyLevel=cl_lan->soubDifficultyLevel; + + gGameOptions.fIronManMode=cl_lan->sofIronManMode; + gGameOptions.ubBobbyRay=cl_lan->soubBobbyRay; + + gGameOptions.ubInventorySystem=cl_lan->sofNewInv; + + if(!cl_lan->soDis_Bobby)LaptopSaveInfo.fBobbyRSiteCanBeAccessed = TRUE; + + if(!cl_lan->soDis_Equip) + ALLOW_EQUIP=TRUE; + + MAX_MERCS=cl_lan->gsMAX_MERCS; + TESTING=cl_lan->TESTING; + REPORT_NAME=cl_lan->gsREPORT_NAME; + + ScreenMsg( FONT_YELLOW, MSG_CHAT, MPClientMessage[24],str,MAX_CLIENTS,MAX_MERCS,PLAYER_BSIDE,SAME_MERC,DAMAGE_MULTIPLIER,gGameOptions.fTurnTimeLimit,secs_per_tick,cl_lan->soDis_Bobby,cl_lan->soDis_Equip,DISABLE_MORALE,TESTING); + if(TESTING) ScreenMsg( FONT_WHITE, MSG_CHAT, MPClientMessage[25] ); + + // WANNE - MP: I just added the NUM_SEC_IN_DAY so the game starts at Day 1 instead of Day 0 + gGameExternalOptions.iGameStartingTime= NUM_SEC_IN_DAY + int(cl_lan->TIME*3600); + // WANNE - MP: In mulitplayer the hired merc arrive immediatly, so iFirstArrivalDelay must be set to 0 + // This also fixed the bug of the wrong hired hours! + gGameExternalOptions.iFirstArrivalDelay = 0; + + // WANNE: fix HOT DAY in night at arrival by night. + // Explanation: If game starting time + first arrival delay < 07:00 (111600) -> we arrive before the sun rises or + // if game starting time + first arrival delay >= 21:00 (162000) -> we arrive after the sun goes down + if( (gGameExternalOptions.iGameStartingTime + gGameExternalOptions. iFirstArrivalDelay) < 111600 || + (gGameExternalOptions.iGameStartingTime + gGameExternalOptions.iFirstArrivalDelay >= 162000)) + { + gubEnvLightValue = 12; + LightSetBaseLevel(gubEnvLightValue); + } + + InitNewGameClock( ); + + WEAPON_READIED_BONUS=cl_lan->WEAPON_READIED_BONUS; + + + ScreenMsg( FONT_LTGREEN, MSG_CHAT, MPClientMessage[26],cl_lan->client_num,szDefault,cl_lan->cl_edge,cl_lan->team ); +// if(PLAYER_BSIDE==0)ScreenMsg(FONT_LTGREEN,MSG_CHAT,MPClientMessage[27],cl_lan->cl_ops[0],cl_lan->cl_ops[1],cl_lan->cl_ops[2],cl_lan->cl_ops[3]); + //ScreenMsg(FONT_LTGREEN,MSG_CHAT,MPClientMessage[27],cl_lan->team); + + strcpy(client_names[cl_lan->client_num-1],szDefault); + + } + else + { + + + ScreenMsg( FONT_LTGREEN, MSG_CHAT, MPClientMessage[26],cl_lan->client_num,szDefault,cl_lan->cl_edge,cl_lan->team ); + // ScreenMsg(FONT_LTGREEN,MSG_CHAT,MPClientMessage[27],cl_lan->team); + strcpy(client_names[cl_lan->client_num-1],szDefault); + + } + +} + + +void send_bullet( BULLET * pBullet,UINT16 usHandItem ) +{ + netb_struct netb; + netb.net_bullet=*pBullet; + netb.usHandItem=usHandItem; + + //ScreenMsg( FONT_YELLOW, MSG_CHAT, L"Sent Bullet Id: %d",pBullet->iBullet); + + if(pBullet->ubTargetID < 20)netb.net_bullet.ubTargetID = netb.net_bullet.ubTargetID+ubID_prefix; + if(pBullet->ubFirerID < 20)netb.net_bullet.ubFirerID = netb.net_bullet.ubFirerID+ubID_prefix; + + + client->RPC("sendBULLET",(const char*)&netb, (int)sizeof(netb_struct)*8, HIGH_PRIORITY, RELIABLE, 0, UNASSIGNED_SYSTEM_ADDRESS, true, 0, UNASSIGNED_NETWORK_ID,0); + +} + +void recieveBULLET(RPCParameters *rpcParameters) +{ + netb_struct* netb = (netb_struct*)rpcParameters->input; + + INT32 net_iBullet=netb->net_bullet.iBullet; + + SOLDIERTYPE * pFirer=MercPtrs[ netb->net_bullet.ubFirerID ]; + + INT8 bTeam=pFirer->bTeam; + + INT32 iBullet; + BULLET * pBullet; + + iBullet = CreateBullet( netb->net_bullet.ubFirerID, 0, netb->net_bullet.usFlags,netb->usHandItem ); + if (iBullet == -1) + { + ScreenMsg( FONT_YELLOW, MSG_CHAT, L"Failed to create bullet"); + } +//add bullet to bullet table for translation + + bTable[bTeam][net_iBullet].remote_id = net_iBullet; + bTable[bTeam][net_iBullet].local_id = iBullet; + + pBullet = GetBulletPtr( iBullet ); + + //ScreenMsg( FONT_YELLOW, MSG_CHAT, L"Created Bullet Id: %d",iBullet); + + pBullet->fCheckForRoof=netb->net_bullet.fCheckForRoof; + pBullet->qIncrX=netb->net_bullet.qIncrX; + pBullet->qIncrY=netb->net_bullet.qIncrY; + pBullet->qIncrZ=netb->net_bullet.qIncrZ; + pBullet->sHitBy=netb->net_bullet.sHitBy; + pBullet->ddHorizAngle=netb->net_bullet.ddHorizAngle; + pBullet->fAimed=netb->net_bullet.fAimed; + pBullet->ubItemStatus=netb->net_bullet.ubItemStatus; + pBullet->qCurrX=netb->net_bullet.qCurrX; + pBullet->qCurrY=netb->net_bullet.qCurrY; + pBullet->qCurrZ=netb->net_bullet.qCurrZ; + pBullet->iImpact=netb->net_bullet.iImpact; + pBullet->iRange=netb->net_bullet.iRange; + pBullet->sTargetGridNo=netb->net_bullet.sTargetGridNo; + pBullet->bStartCubesAboveLevelZ=netb->net_bullet.bStartCubesAboveLevelZ; + pBullet->bEndCubesAboveLevelZ=netb->net_bullet.bEndCubesAboveLevelZ; + pBullet->iDistanceLimit=netb->net_bullet.iDistanceLimit; + + FireBullet( pFirer, pBullet, FALSE ); + +} + +void send_changestate (EV_S_CHANGESTATE * SChangeState) +{ + EV_S_CHANGESTATE new_state; + + memcpy( &new_state , SChangeState, sizeof( EV_S_CHANGESTATE )); + + if(new_state.usSoldierID < 20)new_state.usSoldierID = new_state.usSoldierID+ubID_prefix; + + + + client->RPC("sendSTATE",(const char*)&new_state, (int)sizeof(EV_S_CHANGESTATE)*8, HIGH_PRIORITY, RELIABLE, 0, UNASSIGNED_SYSTEM_ADDRESS, true, 0, UNASSIGNED_NETWORK_ID,0); + //ScreenMsg( FONT_YELLOW, MSG_CHAT, L"sent state"); + + +} + +void recieveSTATE(RPCParameters *rpcParameters) +{ + + EV_S_CHANGESTATE* new_state = (EV_S_CHANGESTATE*)rpcParameters->input; + + + //ScreenMsg( FONT_YELLOW, MSG_CHAT, L"recieved state"); + + + SOLDIERTYPE * pSoldier=MercPtrs[ new_state->usSoldierID ]; + + if(pSoldier->bActive) + pSoldier->EVENT_InitNewSoldierAnim( new_state->usNewState, new_state->usStartingAniCode, new_state->fForce ); +//AddGameEvent( S_CHANGESTATE, 0, &SChangeState ); + //someday ;) +} + +void send_death( SOLDIERTYPE *pSoldier ) +{ + death_struct nDeath; + nDeath.soldier_id=pSoldier->ubID; + nDeath.attacker_id=pSoldier->ubAttackerID; + if(pSoldier->ubAttackerID==NULL)nDeath.attacker_id=pSoldier->ubPreviousAttackerID; + if(pSoldier->ubID<20)nDeath.soldier_id=nDeath.soldier_id+ubID_prefix; + + client->RPC("sendDEATH",(const char*)&nDeath, (int)sizeof(death_struct)*8, HIGH_PRIORITY, RELIABLE, 0, UNASSIGNED_SYSTEM_ADDRESS, true, 0, UNASSIGNED_NETWORK_ID,0); + + SOLDIERTYPE * pAttacker=MercPtrs[ nDeath.attacker_id ]; + INT8 pA_bTeam; + CHAR16 pA_name[ 10 ]; + INT8 pS_bTeam; + CHAR16 pS_name[ 10 ]; + if(pAttacker) + { + pA_bTeam=pAttacker->bTeam; + memcpy(pA_name,pAttacker->name,sizeof(CHAR16)*10); + if(pA_bTeam>5)pA_bTeam=pA_bTeam-5; + if(pA_bTeam==0)pA_bTeam=CLIENT_NUM; + } + if(pSoldier) + { + pS_bTeam=pSoldier->bTeam; + memcpy(pS_name,pSoldier->name,sizeof(CHAR16)*10); + if(pS_bTeam>5)pS_bTeam=pS_bTeam-5; + if(pS_bTeam==0)pS_bTeam=CLIENT_NUM; + } + + ScreenMsg( FONT_LTGREEN, MSG_CHAT, MPClientMessage[28],pS_name,(pS_bTeam),client_names[(pS_bTeam-1)],pA_name,(pA_bTeam),client_names[(pA_bTeam-1)] ); + //ScreenMsg( FONT_LTGREEN, MSG_CHAT, MPClientMessage[28],(pS_bTeam), pS_name,client_names[(pS_bTeam-1)],pA_name,(pA_bTeam),client_names[(pA_bTeam-1)] ); + +} + +void recieveDEATH (RPCParameters *rpcParameters) +{ + + death_struct* nDeath = (death_struct*)rpcParameters->input; + SOLDIERTYPE * pSoldier=MercPtrs[ nDeath->soldier_id ]; + + UINT16 ubAttackerID; + if((nDeath->attacker_id >= ubID_prefix) && (nDeath->attacker_id < (ubID_prefix+5))) + ubAttackerID = (nDeath->attacker_id - ubID_prefix); + else + ubAttackerID = nDeath->attacker_id; + + SOLDIERTYPE * pAttacker=MercPtrs[ ubAttackerID ]; + INT8 pA_bTeam; + CHAR16 pA_name[ 10 ]; + INT8 pS_bTeam; + CHAR16 pS_name[ 10 ]; + + if(pAttacker) + { + pA_bTeam=pAttacker->bTeam; + memcpy(pA_name,pAttacker->name,sizeof(CHAR16)*10); + if(pA_bTeam>5)pA_bTeam=pA_bTeam-5; + if(pA_bTeam==0)pA_bTeam=CLIENT_NUM; + } + if(pSoldier) + { + pS_bTeam=pSoldier->bTeam; + memcpy(pS_name,pSoldier->name,sizeof(CHAR16)*10); + if(pS_bTeam>5)pS_bTeam=pS_bTeam-5; + if(pS_bTeam==0)pS_bTeam=CLIENT_NUM; + } + + + if(pSoldier->bActive) + { + pSoldier->usAnimState=50; + ScreenMsg( FONT_YELLOW, MSG_CHAT, L"made merc corpse/dead"); + TurnSoldierIntoCorpse( pSoldier, TRUE, TRUE ); + ScreenMsg( FONT_LTGREEN, MSG_CHAT, MPClientMessage[28],pS_name,(pS_bTeam),client_names[(pS_bTeam-1)],pA_name,(pA_bTeam),client_names[(pA_bTeam-1)] ); + //ScreenMsg( FONT_LTGREEN, MSG_CHAT, MPClientMessage[28],(pS_bTeam),pS_name,client_names[(pS_bTeam-1)],pA_name,(pA_bTeam),client_names[(pA_bTeam-1)] ); + + } + else + { + ScreenMsg( FONT_YELLOW, MSG_CHAT, L"merc allready corpse/dead"); + } + +} + +void send_hitstruct(EV_S_STRUCTUREHIT * SStructureHit) +{ + EV_S_STRUCTUREHIT struct_hit; + memcpy( &struct_hit , SStructureHit, sizeof( EV_S_STRUCTUREHIT )); + if(SStructureHit->ubAttackerID <20)struct_hit.ubAttackerID = struct_hit.ubAttackerID+ubID_prefix; + + + client->RPC("sendhitSTRUCT",(const char*)&struct_hit, (int)sizeof(EV_S_STRUCTUREHIT)*8, HIGH_PRIORITY, RELIABLE, 0, UNASSIGNED_SYSTEM_ADDRESS, true, 0, UNASSIGNED_NETWORK_ID,0); + +} + +void send_hitwindow(EV_S_WINDOWHIT * SWindowHit) +{ + EV_S_WINDOWHIT window_hit; + memcpy( &window_hit , SWindowHit, sizeof( EV_S_WINDOWHIT )); + if(SWindowHit->ubAttackerID <20)window_hit.ubAttackerID = window_hit.ubAttackerID+ubID_prefix; + + + client->RPC("sendhitWINDOW",(const char*)&window_hit, (int)sizeof(EV_S_WINDOWHIT)*8, HIGH_PRIORITY, RELIABLE, 0, UNASSIGNED_SYSTEM_ADDRESS, true, 0, UNASSIGNED_NETWORK_ID,0); +} + +void send_miss(EV_S_MISS * SMiss) +{ + + EV_S_MISS shot_miss; + memcpy( &shot_miss , SMiss, sizeof( EV_S_MISS )); + if(SMiss->ubAttackerID <20)shot_miss.ubAttackerID = shot_miss.ubAttackerID+ubID_prefix; + + + client->RPC("sendMISS",(const char*)&shot_miss, (int)sizeof(EV_S_MISS)*8, HIGH_PRIORITY, RELIABLE, 0, UNASSIGNED_SYSTEM_ADDRESS, true, 0, UNASSIGNED_NETWORK_ID,0); +} + +void recievehitSTRUCT (RPCParameters *rpcParameters) +{ + EV_S_STRUCTUREHIT* struct_hit = (EV_S_STRUCTUREHIT*)rpcParameters->input; + + SOLDIERTYPE *pSoldier = MercPtrs[ struct_hit->ubAttackerID ]; + INT8 bTeam=pSoldier->bTeam; + INT32 iBullet = bTable[bTeam][struct_hit->iBullet].local_id; + + StructureHit( iBullet, struct_hit->usWeaponIndex, struct_hit->bWeaponStatus, struct_hit->ubAttackerID, struct_hit->sXPos, struct_hit->sYPos, struct_hit->sZPos, struct_hit->usStructureID, struct_hit->iImpact, struct_hit->fStopped ); + if(struct_hit->fStopped)RemoveBullet(iBullet); + //ScreenMsg( FONT_YELLOW, MSG_CHAT, L"recieved structure hit"); +} +void recievehitWINDOW (RPCParameters *rpcParameters) +{ + EV_S_WINDOWHIT* window_hit = (EV_S_WINDOWHIT*)rpcParameters->input; + + + + WindowHit( window_hit->sGridNo, window_hit->usStructureID, window_hit->fBlowWindowSouth, window_hit->fLargeForce ); + + //ScreenMsg( FONT_YELLOW, MSG_CHAT, L"recieved window hit"); +} +void recieveMISS (RPCParameters *rpcParameters) +{ + EV_S_MISS* shot_miss = (EV_S_MISS*)rpcParameters->input; + + SOLDIERTYPE *pSoldier = MercPtrs[ shot_miss->ubAttackerID ]; + INT8 bTeam=pSoldier->bTeam; + INT32 iBullet = bTable[bTeam][shot_miss->iBullet].local_id; + + + ShotMiss( shot_miss->ubAttackerID, iBullet ); + //ScreenMsg( FONT_YELLOW, MSG_CHAT, L"recieved shot miss"); +} + +void cheat_func(void) +{ + if(TESTING) + { + ScreenMsg( FONT_YELLOW, MSG_CHAT, L"gTacticalStatus.uiFlags |= SHOW_ALL_MERCS"); + gTacticalStatus.uiFlags |= SHOW_ALL_MERCS; + } +} + +//void start_tt(void) +//{ +// if(is_server) +// { +// ScreenMsg( FONT_YELLOW, MSG_CHAT, L"manually starting turnbased mode..."); +// +// gTacticalStatus.uiFlags |= INCOMBAT; +// EndTurn (START_TEAM_TURN); +// } +// +//} + +//void unlock (void) +//{ +// +// ScreenMsg( FONT_YELLOW, MSG_CHAT, L"unlocking ui..."); +// guiPendingOverrideEvent = LU_ENDUILOCK; +// guiPendingOverrideEvent = LA_ENDUIOUTURNLOCK; +// +// +//} + +//void request_ovh(UINT8 ubID) +//{ +// ovh_struct rOvh; +// rOvh.clnum=atoi (CLIENT_NUM); +// rOvh.ubid=ubID; +// if(ubID < 20)rOvh.ubid=ubID+ubID_prefix; +// ++tcount; +// +// SOLDIERTYPE *pSoldier = MercPtrs[ ubID ]; +// //ScreenMsg( FONT_LTBLUE, MSG_CHAT, L"requesting: %d",pSoldier->sGridNo ); +// +// //ScreenMsg( FONT_YELLOW, MSG_CHAT, L"center: %d",tcount); +// if(tcount==10)tcount=0; +// +// client->RPC("rOVH",(const char*)&rOvh, (int)sizeof(ovh_struct)*8, HIGH_PRIORITY, RELIABLE, 0, UNASSIGNED_SYSTEM_ADDRESS, true, 0, UNASSIGNED_NETWORK_ID,0); +// +//} + +void UpdateSoldierToNetwork ( SOLDIERTYPE *pSoldier ) +{ + //this send stats to other clients at intervals + UINT8 id = pSoldier->ubID; + UINT32 time = GetJA2Clock(); + + if(id < 20 || (is_server && id <120)) + { + if(pSoldier->usLastUpdateTime==0) + { + pSoldier->usLastUpdateTime = time; + } + if((time - (pSoldier->usLastUpdateTime)) > 2000) + { + pSoldier->usLastUpdateTime = time; + //ScreenMsg( FONT_LTBLUE, MSG_CHAT, L"update: %d ",time ); + + + EV_S_UPDATENETWORKSOLDIER SUpdateNetworkSoldier; + + SUpdateNetworkSoldier.usSoldierID=pSoldier->ubID; + if(pSoldier->ubID < 20)SUpdateNetworkSoldier.usSoldierID=pSoldier->ubID+ubID_prefix; + + SUpdateNetworkSoldier.sAtGridNo=pSoldier->sGridNo; + SUpdateNetworkSoldier.bBreath=pSoldier->bBreath; + SUpdateNetworkSoldier.bLife=pSoldier->stats.bLife; + SUpdateNetworkSoldier.bBleeding=pSoldier->bBleeding; + SUpdateNetworkSoldier.ubDirection=pSoldier->ubDirection; + + if((gTacticalStatus.ubTopMessageType == PLAYER_TURN_MESSAGE ||gTacticalStatus.ubTopMessageType == PLAYER_INTERRUPT_MESSAGE) && (gTacticalStatus.uiFlags & TURNBASED) && (gTacticalStatus.uiFlags & INCOMBAT))//update progress bar, not supporting coop yet... + { + SUpdateNetworkSoldier.usTactialTurnLimitCounter = gTacticalStatus.usTactialTurnLimitCounter; + SUpdateNetworkSoldier.usTactialTurnLimitMax = gTacticalStatus.usTactialTurnLimitMax; + } + else + SUpdateNetworkSoldier.usTactialTurnLimitCounter = 9999; + + + client->RPC("updatenetworksoldier",(const char*)&SUpdateNetworkSoldier, (int)sizeof(EV_S_UPDATENETWORKSOLDIER)*8, HIGH_PRIORITY, RELIABLE, 0, UNASSIGNED_SYSTEM_ADDRESS, true, 0, UNASSIGNED_NETWORK_ID,0); + + } + } +} + +void UpdateSoldierFromNetwork (RPCParameters *rpcParameters) +{ + EV_S_UPDATENETWORKSOLDIER* SUpdateNetworkSoldier = (EV_S_UPDATENETWORKSOLDIER*)rpcParameters->input; + + SOLDIERTYPE *pSoldier = MercPtrs[ SUpdateNetworkSoldier->usSoldierID ]; + pSoldier->bBreath=SUpdateNetworkSoldier->bBreath; + pSoldier->stats.bLife=SUpdateNetworkSoldier->bLife; + + + INT16 sCellX, sCellY; + sCellX = CenterX( SUpdateNetworkSoldier->sAtGridNo ); + sCellY = CenterY( SUpdateNetworkSoldier->sAtGridNo ); + + if( pSoldier->sGridNo != SUpdateNetworkSoldier->sAtGridNo) + { + pSoldier->EVENT_InternalSetSoldierPosition( sCellX, sCellY ,FALSE, FALSE, FALSE );//new syncing call to correct network lag/drift + //ScreenMsg( FONT_LTBLUE, MSG_CHAT, L"sync to pos: %d",pSoldier->sGridNo ); + } + + if(pSoldier->ubDirection != SUpdateNetworkSoldier->ubDirection) + { + pSoldier->EVENT_SetSoldierDesiredDirection( SUpdateNetworkSoldier->ubDirection ); + } + + + pSoldier->bBleeding=SUpdateNetworkSoldier->bBleeding; + + if( SUpdateNetworkSoldier->usTactialTurnLimitCounter != 9999 && (gTacticalStatus.ubTopMessageType != PLAYER_TURN_MESSAGE || gTacticalStatus.ubTopMessageType != PLAYER_INTERRUPT_MESSAGE)) + { + gTacticalStatus.usTactialTurnLimitCounter = SUpdateNetworkSoldier->usTactialTurnLimitCounter; + gTacticalStatus.usTactialTurnLimitMax = SUpdateNetworkSoldier->usTactialTurnLimitMax; + } +} + +//void advance_ovh_frame (RPCParameters *rpcParameters) +//{ +// +// adv* aoh = (adv*)rpcParameters->input; +// UINT8 ryubid = aoh->ubid; +// +// if((ryubid >= ubID_prefix) && (ryubid < (ubID_prefix+7))) // within our netbTeam range... +// { +// ryubid = (ryubid - ubID_prefix); +// } +// SOLDIERTYPE *pSoldier = MercPtrs[ ryubid ]; +// //ScreenMsg( FONT_LTBLUE, MSG_CHAT, L"advancing: %d",pSoldier->sGridNo ); +// pSoldier->flags.fIsSoldierDelayed = false; +// //ovh_advance=true; +// +//} + +void kick_player (void) +{ + if(is_server) + { + //manual overide command for server + const STR16 msg = L"Choose Client Number to Kick:"; + + SGPRect CenterRect = { 100, 100, SCREEN_WIDTH - 100, 300 }; + DoMessageBox( MSG_BOX_BASIC_STYLE, msg, guiCurrentScreen, MSG_BOX_FLAG_FOUR_NUMBERED_BUTTONS | MSG_BOX_FLAG_USE_CENTERING_RECT, kick_callback, &CenterRect ); + + } + else ScreenMsg( FONT_LTGREEN, MSG_INTERFACE, MPClientMessage[22] ); + +} +void kick_callback (UINT8 ubResult) +{ + + kickR kick; + kick.ubResult=ubResult+5; + + //ScreenMsg( FONT_LTGREEN, MSG_INTERFACE, L"kicking client " ); + client->RPC("Snull_team",(const char*)&kick, (int)sizeof(kickR)*8, HIGH_PRIORITY, RELIABLE, 0, UNASSIGNED_SYSTEM_ADDRESS, true, 0, UNASSIGNED_NETWORK_ID,0); + +} + +void null_team (RPCParameters *rpcParameters) +{ + kickR* kick = (kickR*)rpcParameters->input; + ScreenMsg( FONT_LTGREEN, MSG_INTERFACE, MPClientMessage[29],(kick->ubResult-5),client_names[kick->ubResult-6] ); + int fID = gTacticalStatus.Team[ kick->ubResult ].bFirstID; + int lID = gTacticalStatus.Team[ kick->ubResult ].bLastID; + + if(kick->ubResult==netbTeam)fID=0,lID=19; + int cnt; + for ( cnt=fID ; cnt <= lID; cnt++ ) + { + TacticalRemoveSoldier( cnt ); + } + +} + +void overide_turn (void) +{ + if(is_server) + { + //manual overide command for server + const STR16 msg = MPClientMessage[30]; + + SGPRect CenterRect = { 100, 100, SCREEN_WIDTH - 100, 300 }; + DoMessageBox( MSG_BOX_BASIC_STYLE, msg, guiCurrentScreen, MSG_BOX_FLAG_FOUR_NUMBERED_BUTTONS | MSG_BOX_FLAG_USE_CENTERING_RECT, turn_callback, &CenterRect ); + + } + else ScreenMsg( FONT_LTGREEN, MSG_INTERFACE, MPClientMessage[22] ); + +} + +void turn_callback (UINT8 ubResult) +{ + + if(is_server) + { + ScreenMsg( FONT_LTGREEN, MSG_INTERFACE, MPClientMessage[31],ubResult ); + + if(!( gTacticalStatus.uiFlags & INCOMBAT )) + { + gTacticalStatus.uiFlags |= INCOMBAT; + } + if(ubResult ==1)EndTurn( 0 ); + else EndTurn( ubResult+5 ); + } +} + +void send_fireweapon (EV_S_FIREWEAPON *SFireWeapon) +{ + EV_S_FIREWEAPON sFire; + //sFire.usSoldierID=SFireWeapon->usSoldierID; + + if(SFireWeapon->usSoldierID < 20) + sFire.usSoldierID = (SFireWeapon->usSoldierID)+ubID_prefix; + else + sFire.usSoldierID = SFireWeapon->usSoldierID; + + sFire.sTargetGridNo=SFireWeapon->sTargetGridNo; + sFire.bTargetCubeLevel=SFireWeapon->bTargetCubeLevel; + sFire.bTargetLevel=SFireWeapon->bTargetLevel; + + client->RPC("sendFIREW",(const char*)&sFire, (int)sizeof(EV_S_FIREWEAPON)*8, HIGH_PRIORITY, RELIABLE, 0, UNASSIGNED_SYSTEM_ADDRESS, true, 0, UNASSIGNED_NETWORK_ID,0); + +} + +void recieve_fireweapon (RPCParameters *rpcParameters) +{ + EV_S_FIREWEAPON* SFireWeapon = (EV_S_FIREWEAPON*)rpcParameters->input; + //ScreenMsg( FONT_LTGREEN, MSG_INTERFACE, L"recieve_fireweapon" ); + //SFireWeapon.usSoldierID = pSoldier->ubID; + ////SFireWeapon.uiUniqueId = pSoldier->uiUniqueSoldierIdValue; + //SFireWeapon.sTargetGridNo = pSoldier->sTargetGridNo; + //SFireWeapon.bTargetLevel = pSoldier->bTargetLevel; + //SFireWeapon.bTargetCubeLevel= pSoldier->bTargetCubeLevel; + //AddGameEvent( S_FIREWEAPON, 0, &SFireWeapon ); + + SOLDIERTYPE *pSoldier = MercPtrs[ SFireWeapon->usSoldierID ]; + + pSoldier->sTargetGridNo = SFireWeapon->sTargetGridNo; + pSoldier->bTargetLevel = SFireWeapon->bTargetLevel; + pSoldier->bTargetCubeLevel = SFireWeapon->bTargetCubeLevel; + FireWeapon( pSoldier, SFireWeapon->sTargetGridNo ); + +} + +void send_door ( SOLDIERTYPE *pSoldier, INT16 sGridNo, BOOLEAN fNoAnimations ) +{ +if((is_server && pSoldier->ubID<120) || (!is_server && is_client && pSoldier->ubID<20) || (!is_server && !is_client) ) +{ + doors sDoor; + sDoor.ubID=pSoldier->ubID; + sDoor.sGridNo=sGridNo; + sDoor.fNoAnimations=fNoAnimations; + + client->RPC("sendDOOR",(const char*)&sDoor, (int)sizeof(doors)*8, HIGH_PRIORITY, RELIABLE, 0, UNASSIGNED_SYSTEM_ADDRESS, true, 0, UNASSIGNED_NETWORK_ID,0); +} +} + +void recieve_door (RPCParameters *rpcParameters) +{ + + doors* sDoor = (doors*)rpcParameters->input; + + SOLDIERTYPE *pSoldier = MercPtrs[ sDoor->ubID ]; + HandleDoorChangeFromGridNo( pSoldier, sDoor->sGridNo, sDoor->fNoAnimations ); + +} + + +void sendRT(void) +{ + if(!requested) + { + ScreenMsg( FONT_MCOLOR_LTYELLOW, MSG_INTERFACE, MPClientMessage[32] ); + requested=true; + real_struct rData; + rData.bteam=netbTeam; + + client->RPC("sendREAL",(const char*)&rData, (int)sizeof(real_struct)*8, HIGH_PRIORITY, RELIABLE, 0, UNASSIGNED_SYSTEM_ADDRESS, true, 0, UNASSIGNED_NETWORK_ID,0); + } + +} + +void gotoRT(RPCParameters *rpcParameters) +{ + getReal=true; + + gTacticalStatus.bConsNumTurnsNotSeen = 0; + gTacticalStatus.ubCurrentTeam = OUR_TEAM; + guiPendingOverrideEvent = LA_ENDUIOUTURNLOCK; + ExitCombatMode(); + fInterfacePanelDirty = DIRTYLEVEL2; + + + + if ( (gTacticalStatus.uiFlags & TURNBASED) && (gTacticalStatus.uiFlags & INCOMBAT) ) + { + ScreenMsg( FONT_MCOLOR_LTYELLOW, MSG_INTERFACE, MPClientMessage[34] ); + + + } + else + { + ScreenMsg( FONT_MCOLOR_LTYELLOW, MSG_INTERFACE, MPClientMessage[33] ); + } + +getReal=false; +} + +void startCombat(UINT8 ubStartingTeam) +{ + sc_struct data; + if(ubStartingTeam==0) + ubStartingTeam=netbTeam; + data.ubStartingTeam=ubStartingTeam; + client->RPC("startCOMBAT",(const char*)&data, (int)sizeof(sc_struct)*8, HIGH_PRIORITY, RELIABLE, 0, UNASSIGNED_SYSTEM_ADDRESS, true, 0, UNASSIGNED_NETWORK_ID,0); + + +} + + +//*************************** +//*** client connection***** +//************************* + +void connect_client ( void ) +{ + + if(!is_client) + { + ScreenMsg( FONT_LTGREEN, MSG_CHAT, MPClientMessage[0] ); + + + + + client=RakNetworkFactory::GetRakPeerInterface(); + bool b = client->Startup(1,30,&SocketDescriptor(), 1); + + //RPC's + REGISTER_STATIC_RPC(client, recievePATH); + REGISTER_STATIC_RPC(client, recieveSTANCE); + REGISTER_STATIC_RPC(client, recieveDIR); + REGISTER_STATIC_RPC(client, recieveFIRE); + REGISTER_STATIC_RPC(client, recieveHIT); + REGISTER_STATIC_RPC(client, recieveHIRE); + REGISTER_STATIC_RPC(client, recieveguiPOS); + REGISTER_STATIC_RPC(client, recieveguiDIR); + REGISTER_STATIC_RPC(client, recieveEndTurn); + REGISTER_STATIC_RPC(client, recieveAI); + REGISTER_STATIC_RPC(client, recieveSTOP); + REGISTER_STATIC_RPC(client, recieveINTERRUPT); + REGISTER_STATIC_RPC(client, recieveREADY); + REGISTER_STATIC_RPC(client, recieveGUI); + REGISTER_STATIC_RPC(client, recieveSETTINGS); + REGISTER_STATIC_RPC(client, recieveBULLET); + REGISTER_STATIC_RPC(client, recieveSTATE); + REGISTER_STATIC_RPC(client, recieveDEATH); + REGISTER_STATIC_RPC(client, recievehitSTRUCT); + REGISTER_STATIC_RPC(client, recievehitWINDOW); + REGISTER_STATIC_RPC(client, recieveMISS); + REGISTER_STATIC_RPC(client, resume_turn); + REGISTER_STATIC_RPC(client, UpdateSoldierFromNetwork); + REGISTER_STATIC_RPC(client, recieve_fireweapon); + REGISTER_STATIC_RPC(client, recieve_door); + REGISTER_STATIC_RPC(client, null_team); + REGISTER_STATIC_RPC(client, gotoRT); + //*** + + if (b) + { + //ScreenMsg( FONT_LTGREEN, MSG_CHAT, L"Client started, waiting for connections..."); + is_client=true; + /*repo=0;*/ + } + else + { + ScreenMsg( FONT_LTGREEN, MSG_CHAT, L"Client failed to start. Terminating."); + + } + + is_connected=false; + + + + + + + } + + //reconnect/connect + if( !is_connected && !is_connecting) + { + + recieved_settings=0; + goahead = 0; + numready = 0; + readystage = 0; + status = 0; + gTacticalStatus.uiFlags&= (~SHOW_ALL_MERCS ); + memset( &readyteamreg , 0 , sizeof (int) * 10); + + //retrieve settings from Ja2_mp.ini + char ip[30]; + char port[30]; +// char client_number[30]; + char sector_edge[30]; + + + //disable cheating + gubCheatLevel = 0; + + //char c_x[30]; + + + char clname[30]; + + + + MAX_CLIENTS=0;//reset server only set settings. + //INTERRUPTS=0; + DAMAGE_MULTIPLIER=0; + SAME_MERC=0; + + GetPrivateProfileString( "Ja2_mp Settings","SERVER_IP", "", ip, MAX_PATH, "..\\Ja2_mp.ini" ); + GetPrivateProfileString( "Ja2_mp Settings","SERVER_PORT", "", port, MAX_PATH, "..\\Ja2_mp.ini" ); + // GetPrivateProfileString( "Ja2_mp Settings","CLIENT_NUM", "", client_number, MAX_PATH, "..\\Ja2_mp.ini" ); + GetPrivateProfileString( "Ja2_mp Settings","SECTOR_EDGE", "", sector_edge, MAX_PATH, "..\\Ja2_mp.ini" ); + + + //GetPrivateProfileString( "Ja2_mp Settings","CRATE_X", "", c_x, MAX_PATH, "..\\Ja2_mp.ini" ); + + + GetPrivateProfileString( "Ja2_mp Settings","CLIENT_NAME", "", clname, MAX_PATH, "..\\Ja2_mp.ini" ); + + + + + + char op1[30]; + //char op2[30]; + //char op3[30]; + //char op4[30]; + + GetPrivateProfileString( "Ja2_mp Settings","TEAM", "", op1, MAX_PATH, "..\\Ja2_mp.ini" ); + //GetPrivateProfileString( "Ja2_mp Settings","OP_TEAM_2", "", op2, MAX_PATH, "..\\Ja2_mp.ini" ); + //GetPrivateProfileString( "Ja2_mp Settings","OP_TEAM_3", "", op3, MAX_PATH, "..\\Ja2_mp.ini" ); + //GetPrivateProfileString( "Ja2_mp Settings","OP_TEAM_4", "", op4, MAX_PATH, "..\\Ja2_mp.ini" ); + /*char stt[30]; + GetPrivateProfileString( "Ja2_mp Settings","START_TEAM_TURN", "", stt, MAX_PATH, "..\\Ja2_mp.ini" );*/ + + + TEAM=atoi(op1); + //OP_TEAM_2=atoi(op2); + // OP_TEAM_3=atoi(op3); + // OP_TEAM_4=atoi(op4); + + strcpy( CLIENT_NAME, clname); + + + if(is_server)strcpy( SERVER_IP , "127.0.0.1" ); + else strcpy( SERVER_IP , ip ); + + strcpy( SERVER_PORT, port ); + + /*if (is_server) strcpy( CLIENT_NUM, "1" ); + else strcpy( CLIENT_NUM, client_number );*/ + + strcpy( SECT_EDGE, sector_edge); + + //START_TEAM_TURN=atoi(stt); + //crate_sGridX = atoi(c_x); +// crate_sGridY = atoi(c_y); + + /*netbTeam = (CLIENT_NUM)+5; + ubID_prefix = gTacticalStatus.Team[ netbTeam ].bFirstID;*/ + + + + + //********************** + //here some nifty little tweaks + + LaptopSaveInfo.guiNumberOfMercPaymentsInDays += 20; + LaptopSaveInfo.gubLastMercIndex = LAST_MERC_ID; + + LaptopSaveInfo.ubLastMercAvailableId = 7; + + extern BOOLEAN gfTemporaryDisablingOfLoadPendingFlag; + gfTemporaryDisablingOfLoadPendingFlag = TRUE; + SetBookMark( AIM_BOOKMARK ); + SetBookMark( BOBBYR_BOOKMARK ); + //SetBookMark( IMP_BOOKMARK ); + SetBookMark( MERC_BOOKMARK ); + + gMercProfiles[ 57 ].sSalary = 2000; + gMercProfiles[ 58 ].sSalary = 1500; + gMercProfiles[ 59 ].sSalary = 600; + gMercProfiles[ 60 ].sSalary = 500; + gMercProfiles[ 64 ].sSalary = 1500; + gMercProfiles[ 72 ].sSalary = 1000; + gMercProfiles[ 148 ].sSalary = 100; + + + //********************** + + + ScreenMsg( FONT_LTGREEN, MSG_CHAT, MPClientMessage[1],SERVER_IP); + client->Connect(SERVER_IP, atoi(SERVER_PORT), 0,0); + is_connecting=true; + + } + + else if (is_connecting) + { + ScreenMsg( FONT_LTGREEN, MSG_CHAT, MPClientMessage[4] ); + } + else if (is_connected) + { + ScreenMsg( FONT_LTGREEN, MSG_CHAT, MPClientMessage[3] ); + } + +} + +void client_packet ( void ) +{ + + Packet* p; + + + if (is_client) + { + + p = client->Receive(); + + while(p) + { + //continue; // Didn't get any packets + + // We got a packet, get the identifier with our handy function + packetIdentifier = GetPacketIdentifier(p); + //ScreenMsg( FONT_LTGREEN, MSG_CHAT, L"packet recieved"); + // Check if this is a network message packet + switch (packetIdentifier) + { + case ID_DISCONNECTION_NOTIFICATION: + // Connection lost normally + ScreenMsg( FONT_LTGREEN, MSG_CHAT, L"ID_DISCONNECTION_NOTIFICATION"); + is_connected=false; + break; + case ID_ALREADY_CONNECTED: + // Connection lost normally + ScreenMsg( FONT_LTGREEN, MSG_CHAT, L"ID_ALREADY_CONNECTED"); + break; + case ID_REMOTE_DISCONNECTION_NOTIFICATION: // Server telling the clients of another client disconnecting gracefully. You can manually broadcast this in a peer to peer enviroment if you want. + ScreenMsg( FONT_LTGREEN, MSG_CHAT, L"ID_REMOTE_DISCONNECTION_NOTIFICATION"); + break; + case ID_REMOTE_CONNECTION_LOST: // Server telling the clients of another client disconnecting forcefully. You can manually broadcast this in a peer to peer enviroment if you want. + ScreenMsg( FONT_LTGREEN, MSG_CHAT, L"ID_REMOTE_CONNECTION_LOST"); + break; + case ID_REMOTE_NEW_INCOMING_CONNECTION: // Server telling the clients of another client connecting. You can manually broadcast this in a peer to peer enviroment if you want. + ScreenMsg( FONT_LTGREEN, MSG_CHAT, L"ID_REMOTE_NEW_INCOMING_CONNECTION"); + break; + case ID_CONNECTION_ATTEMPT_FAILED: + ScreenMsg( FONT_LTGREEN, MSG_CHAT, L"ID_CONNECTION_ATTEMPT_FAILED"); + is_connected=false; + is_connecting=false; + break; + case ID_NO_FREE_INCOMING_CONNECTIONS: + // Sorry, the server is full. I don't do anything here but + // A real app should tell the user + ScreenMsg( FONT_LTGREEN, MSG_CHAT, L"ID_NO_FREE_INCOMING_CONNECTIONS"); + break; + case ID_CONNECTION_LOST: + // Couldn't deliver a reliable packet - i.e. the other system was abnormally + // terminated + ScreenMsg( FONT_LTGREEN, MSG_CHAT, L"ID_CONNECTION_LOST"); + is_connected=false; + break; + case ID_CONNECTION_REQUEST_ACCEPTED: + // This tells the client they have connected + ScreenMsg( FONT_LTGREEN, MSG_CHAT, L"ID_CONNECTION_REQUEST_ACCEPTED"); + is_connected=true; + is_connecting=false; + requestSETTINGS(); + //request_settings();//ask server for game settings... + break; + case ID_NEW_INCOMING_CONNECTION: + //tells server client has connected + ScreenMsg( FONT_LTGREEN, MSG_CHAT, L"ID_NEW_INCOMING_CONNECTION"); + break; + case ID_MODIFIED_PACKET: + // Cheater! + ScreenMsg( FONT_LTGREEN, MSG_CHAT, L"ID_MODIFIED_PACKET"); + break; + default: + + ScreenMsg( FONT_LTGREEN, MSG_CHAT, L"** a packet has been recieved for which i dont know what to do... **"); + break; + } + + + // We're done with the packet, get more :) + client->DeallocatePacket(p); + p = client->Receive(); + } + } +} +// Copied from Multiplayer.cpp +// If the first byte is ID_TIMESTAMP, then we want the 5th byte +// Otherwise we want the 1st byte +unsigned char GetPacketIdentifier(Packet *p) +{ + if (p==0) + return 255; + + if ((unsigned char)p->data[0] == ID_TIMESTAMP) + { + assert(p->length > sizeof(unsigned char) + sizeof(unsigned long)); + return (unsigned char) p->data[sizeof(unsigned char) + sizeof(unsigned long)]; + } + else + return (unsigned char) p->data[0]; +} + + +void client_disconnect (void) +{ + if(is_client) + { + client->Shutdown(300); + is_client = false; + is_connected=false; + is_connecting=false; + + allowlaptop=false; + + + + // We're done with the network + RakNetworkFactory::DestroyRakPeerInterface(client); + ScreenMsg( FONT_LTGREEN, MSG_CHAT, L"client disconnected and shutdown"); + } + else + { + ScreenMsg( FONT_LTGREEN, MSG_CHAT, L"client is not running"); + } +} \ No newline at end of file diff --git a/Multiplayer/connect.h b/Multiplayer/connect.h new file mode 100644 index 00000000..f059ac6e --- /dev/null +++ b/Multiplayer/connect.h @@ -0,0 +1,95 @@ +#pragma once + + +#include "Soldier Init List.h" +#include "Merc Hiring.h" +#include "event pump.h" + +extern bool is_connected; +extern bool is_connecting; +extern bool is_client; +extern bool is_server; +extern bool is_networked; + +extern int PLAYER_TEAM_TIMER_SEC_PER_TICKS; + +//extern char CLIENT_NUM[30]; +extern int CLIENT_NUM; + +extern int ENEMY_ENABLED; +extern int CREATURE_ENABLED; +extern int MILITIA_ENABLED; +extern int CIV_ENABLED; + +extern int MAX_CLIENTS; +extern int SAME_MERC; + +extern bool allowlaptop; + +extern UINT8 netbTeam; +extern UINT8 ubID_prefix; +extern FLOAT DAMAGE_MULTIPLIER; + +extern UINT16 crate_usMapPos; + +//extern int INTERRUPTS; + +extern int ALLOW_EQUIP; + +extern INT32 MAX_MERCS; + +void lockui (bool unlock); + +void start_battle ( void ); +void DropOffItemsInSector( UINT8 ubOrderNum ); + +void test_func2 ( void ); + +void mp_help (void); +void mp_help2 (void); +void grid_display ( void); + +void send_loaded (void); +void send_donegui ( UINT8 ubResult ); + + +UINT8 numenemyLAN( UINT8 ubSectorX, UINT8 ubSectorY ); + +void connect_client ( void ); +void start_server (void); +void client_packet ( void ); +void server_packet ( void ); + +void server_disconnect (void); +void client_disconnect (void); + +void DialogRemoved( UINT8 ubResult ); +void manual_overide(void); + +void send_path ( SOLDIERTYPE *pSoldier, UINT16 sDestGridNo, UINT16 usMovementAnim, BOOLEAN fFromUI, BOOLEAN fForceRestartAnim ); +void send_stance ( SOLDIERTYPE *pSoldier, UINT8 ubDesiredStance ); +void send_dir ( SOLDIERTYPE *pSoldier, UINT16 usDesiredDirection ); +void send_fire( SOLDIERTYPE *pSoldier, INT16 sTargetGridNo ); +void send_hit( EV_S_WEAPONHIT *SWeaponHit ); + +void send_hire( UINT8 iNewIndex, UINT8 ubCurrentSoldier, INT16 iTotalContractLength, BOOLEAN fCopyProfileItemsOver); + +void send_gui_pos(SOLDIERTYPE *pSoldier, FLOAT dNewXPos, FLOAT dNewYPos); +void send_gui_dir(SOLDIERTYPE *pSoldier, UINT16 usNewDirection); + +void send_EndTurn( UINT8 ubNextTeam ); + +void send_AI( SOLDIERCREATE_STRUCT *pCreateStruct, UINT8 *pubID ); + +void send_stop (EV_S_STOP_MERC *SStopMerc); + +void send_interrupt(SOLDIERTYPE *pSoldier); + +BOOLEAN CheckConditionsForBattle( GROUP *pGroup ); // this comes from strategic movement.cpp + +extern char client_names[4][30]; + +void send_settings(); + + +void StartInterrupt( void ); diff --git a/Multiplayer/fresh_header.h b/Multiplayer/fresh_header.h new file mode 100644 index 00000000..44288c83 --- /dev/null +++ b/Multiplayer/fresh_header.h @@ -0,0 +1,57 @@ +#pragma once + +//time for a new header :) + +extern int readyteamreg[10]; + +typedef struct +{ + UINT16 soldier_id; + UINT16 attacker_id; +}death_struct; + +typedef struct +{ + UINT16 ubID; + INT16 sGridNo; + BOOLEAN fNoAnimations; +}doors; +void send_door ( SOLDIERTYPE *pSoldier, INT16 sGridNo, BOOLEAN fNoAnimations ); + +void send_changestate (EV_S_CHANGESTATE * SChangeState); + +void send_death( SOLDIERTYPE *pSoldier); + +void send_hitstruct(EV_S_STRUCTUREHIT * SStructureHit); +void send_hitwindow(EV_S_WINDOWHIT * SWindowHit); +void send_miss(EV_S_MISS * SMiss); + +void cheat_func(void); +//void start_tt(void); +void unlock (void); + +void UpdateSoldierToNetwork ( SOLDIERTYPE *pSoldier ); + +extern BOOLEAN gfUIInterfaceSetBusy; + +void kick_player (void); +void overide_turn (void); + +extern bool DISABLE_MORALE; + +void send_fireweapon ( EV_S_FIREWEAPON * SFireWeapon); + +void end_interrupt ( BOOLEAN fMarkInterruptOccurred ); +void EndInterrupt( BOOLEAN fMarkInterruptOccurred ); +void sendRT (void); + +extern int numreadyteams;//for realtime + +extern bool requested; +extern bool getReal; + +extern UINT8 gubCheatLevel; + +void startCombat(UINT8 ubStartingTeam); + +extern int WEAPON_READIED_BONUS; \ No newline at end of file diff --git a/Multiplayer/network.h b/Multiplayer/network.h new file mode 100644 index 00000000..ea706dfb --- /dev/null +++ b/Multiplayer/network.h @@ -0,0 +1,83 @@ +#pragma once + +//this one just for structs, variables and functions used between the client and server scripts... + +extern char CLIENT_NAME[30]; + + + +typedef struct +{ + UINT8 client_num; + char client_name[30]; + int team; + int cl_edge; +}client_info; + +typedef struct +{ + int max_clients; + int same_merc; + float damage_multiplier; + INT16 gsMercArriveSectorX; + INT16 gsMercArriveSectorY; + int ENEMY_ENABLED; + int CREATURE_ENABLED; + int MILITIA_ENABLED; + int CIV_ENABLED; + int gsPLAYER_BSIDE; + INT32 secs_per_tick; + INT32 starting_balance; + bool soDis_Bobby; + bool soDis_Equip; + BOOLEAN sofGunNut; + UINT8 soubGameStyle; + UINT8 soubDifficultyLevel; + BOOLEAN sofTurnTimeLimit; + BOOLEAN sofIronManMode; + UINT8 soubBobbyRay; + BOOLEAN sofNewInv; // WANNE - MP: New inventory + INT32 gsMAX_MERCS; + UINT8 client_num; + char client_name[30]; + char client_names[4][30]; + //int cl_ops[4]; + int team; + int TESTING; + char kitbag[100]; + bool emorale; + int gsREPORT_NAME; + int cl_edge; + float TIME; + int WEAPON_READIED_BONUS; +} settings_struct; + +//typedef struct +//{ +// int clnum; +// UINT8 ubid; +//}ovh_struct; +// +//typedef struct +//{ +// UINT8 ubid; +//}adv; + + +typedef struct +{ + BOOLEAN fMarkInterruptOccurred; + INT8 bteam; + UINT8 ubid; + +}endINT; + +typedef struct +{ + INT8 bteam; +}real_struct; + +typedef struct +{ + UINT8 ubStartingTeam; +}sc_struct; \ No newline at end of file diff --git a/Multiplayer/raknet/BitStream.h b/Multiplayer/raknet/BitStream.h new file mode 100644 index 00000000..0f4b5744 --- /dev/null +++ b/Multiplayer/raknet/BitStream.h @@ -0,0 +1,1450 @@ +/// \file +/// \brief This class allows you to write and read native types as a string of bits. BitStream is used extensively throughout RakNet and is designed to be used by users as well. +/// +/// This file is part of RakNet Copyright 2003 Kevin Jenkins. +/// +/// Usage of RakNet is subject to the appropriate license agreement. +/// Creative Commons Licensees are subject to the +/// license found at +/// http://creativecommons.org/licenses/by-nc/2.5/ +/// Single application licensees are subject to the license found at +/// http://www.rakkarsoft.com/SingleApplicationLicense.html +/// Custom license users are subject to the terms therein. +/// GPL license users are subject to the GNU General Public +/// License as published by the Free +/// Software Foundation; either version 2 of the License, or (at your +/// option) any later version. + + +#if defined(_MSC_VER) && _MSC_VER < 1299 // VC6 doesn't support template specialization +#include "BitStream_NoTemplate.h" +#else + +#ifndef __BITSTREAM_H +#define __BITSTREAM_H + +#include "RakNetDefines.h" +#include "Export.h" +#include "RakNetTypes.h" +#include +#include +#include + +#ifdef _MSC_VER +#pragma warning( push ) +#endif + +/// Arbitrary size, just picking something likely to be larger than most packets +#define BITSTREAM_STACK_ALLOCATION_SIZE 256 + +/// The namespace RakNet is not consistently used. It's only purpose is to avoid compiler errors for classes whose names are very common. +/// For the most part I've tried to avoid this simply by using names very likely to be unique for my classes. +namespace RakNet +{ + /// This class allows you to write and read native types as a string of bits. BitStream is used extensively throughout RakNet and is designed to be used by users as well. + /// \sa BitStreamSample.txt + class RAK_DLL_EXPORT BitStream + { + + public: + /// Default Constructor + BitStream(); + + /// Create the bitstream, with some number of bytes to immediately allocate. + /// There is no benefit to calling this, unless you know exactly how many bytes you need and it is greater than BITSTREAM_STACK_ALLOCATION_SIZE. + /// In that case all it does is save you one or more realloc calls. + /// \param[in] initialBytesToAllocate the number of bytes to pre-allocate. + BitStream( int initialBytesToAllocate ); + + /// Initialize the BitStream, immediately setting the data it contains to a predefined pointer. + /// Set \a _copyData to true if you want to make an internal copy of the data you are passing. Set it to false to just save a pointer to the data. + /// You shouldn't call Write functions with \a _copyData as false, as this will write to unallocated memory + /// 99% of the time you will use this function to cast Packet::data to a bitstream for reading, in which case you should write something as follows: + /// \code + /// RakNet::BitStream bs(packet->data, packet->length, false); + /// \endcode + /// \param[in] _data An array of bytes. + /// \param[in] lengthInBytes Size of the \a _data. + /// \param[in] _copyData true or false to make a copy of \a _data or not. + BitStream( unsigned char* _data, unsigned int lengthInBytes, bool _copyData ); + + /// Destructor + ~BitStream(); + + /// Resets the bitstream for reuse. + void Reset( void ); + + /// Bidirectional serialize/deserialize any integral type to/from a bitstream. Undefine __BITSTREAM_NATIVE_END if you need endian swapping. + /// \param[in] writeToBitstream true to write from your data to this bitstream. False to read from this bitstream and write to your data + /// \param[in] var The value to write + /// \return true if \a writeToBitstream is true. true if \a writeToBitstream is false and the read was successful. false if \a writeToBitstream is false and the read was not successful. + template + bool Serialize(bool writeToBitstream, templateType &var); + + /// Bidirectional serialize/deserialize any integral type to/from a bitstream. If the current value is different from the last value + /// the current value will be written. Otherwise, a single bit will be written + /// \param[in] writeToBitstream true to write from your data to this bitstream. False to read from this bitstream and write to your data + /// \param[in] currentValue The current value to write + /// \param[in] lastValue The last value to compare against. Only used if \a writeToBitstream is true. + /// \return true if \a writeToBitstream is true. true if \a writeToBitstream is false and the read was successful. false if \a writeToBitstream is false and the read was not successful. + template + bool SerializeDelta(bool writeToBitstream, templateType ¤tValue, templateType lastValue); + + /// Bidirectional version of SerializeDelta when you don't know what the last value is, or there is no last value. + /// \param[in] writeToBitstream true to write from your data to this bitstream. False to read from this bitstream and write to your data + /// \param[in] currentValue The current value to write + /// \return true if \a writeToBitstream is true. true if \a writeToBitstream is false and the read was successful. false if \a writeToBitstream is false and the read was not successful. + template + bool SerializeDelta(bool writeToBitstream, templateType ¤tValue); + + /// Bidirectional serialize/deserialize any integral type to/from a bitstream. Undefine __BITSTREAM_NATIVE_END if you need endian swapping. + /// If you are not using __BITSTREAM_NATIVE_END the opposite is true for types larger than 1 byte + /// For floating point, this is lossy, using 2 bytes for a float and 4 for a double. The range must be between -1 and +1. + /// For non-floating point, this is lossless, but only has benefit if you use less than half the range of the type + /// \param[in] writeToBitstream true to write from your data to this bitstream. False to read from this bitstream and write to your data + /// \param[in] var The value to write + /// \return true if \a writeToBitstream is true. true if \a writeToBitstream is false and the read was successful. false if \a writeToBitstream is false and the read was not successful. + template + bool SerializeCompressed(bool writeToBitstream, templateType &var); + + /// Bidirectional serialize/deserialize any integral type to/from a bitstream. If the current value is different from the last value + /// the current value will be written. Otherwise, a single bit will be written + /// For floating point, this is lossy, using 2 bytes for a float and 4 for a double. The range must be between -1 and +1. + /// For non-floating point, this is lossless, but only has benefit if you use less than half the range of the type + /// If you are not using __BITSTREAM_NATIVE_END the opposite is true for types larger than 1 byte + /// \param[in] writeToBitstream true to write from your data to this bitstream. False to read from this bitstream and write to your data + /// \param[in] currentValue The current value to write + /// \param[in] lastValue The last value to compare against. Only used if \a writeToBitstream is true. + /// \return true if \a writeToBitstream is true. true if \a writeToBitstream is false and the read was successful. false if \a writeToBitstream is false and the read was not successful. + template + bool SerializeCompressedDelta(bool writeToBitstream, templateType ¤tValue, templateType lastValue); + + /// Save as SerializeCompressedDelta(templateType ¤tValue, templateType lastValue) when we have an unknown second parameter + template + bool SerializeCompressedDelta(bool writeToBitstream, templateType ¤tValue); + + /// Bidirectional serialize/deserialize an array or casted stream or raw data. This does NOT do endian swapping. + /// \param[in] writeToBitstream true to write from your data to this bitstream. False to read from this bitstream and write to your data + /// \param[in] input a byte buffer + /// \param[in] numberOfBytes the size of \a input in bytes + /// \return true if \a writeToBitstream is true. true if \a writeToBitstream is false and the read was successful. false if \a writeToBitstream is false and the read was not successful. + bool Serialize(bool writeToBitstream, char* input, const int numberOfBytes ); + + /// Bidirectional serialize/deserialize a normalized 3D vector, using (at most) 4 bytes + 3 bits instead of 12-24 bytes. Will further compress y or z axis aligned vectors. + /// Accurate to 1/32767.5. + /// \param[in] writeToBitstream true to write from your data to this bitstream. False to read from this bitstream and write to your data + /// \param[in] x x + /// \param[in] y y + /// \param[in] z z + /// \return true if \a writeToBitstream is true. true if \a writeToBitstream is false and the read was successful. false if \a writeToBitstream is false and the read was not successful. + template // templateType for this function must be a float or double + bool SerializeNormVector(bool writeToBitstream, templateType &x, templateType &y, templateType &z ); + + /// Bidirectional serialize/deserialize a vector, using 10 bytes instead of 12. + /// Loses accuracy to about 3/10ths and only saves 2 bytes, so only use if accuracy is not important. + /// \param[in] writeToBitstream true to write from your data to this bitstream. False to read from this bitstream and write to your data + /// \param[in] x x + /// \param[in] y y + /// \param[in] z z + /// \return true if \a writeToBitstream is true. true if \a writeToBitstream is false and the read was successful. false if \a writeToBitstream is false and the read was not successful. + template // templateType for this function must be a float or double + bool SerializeVector(bool writeToBitstream, templateType &x, templateType &y, templateType &z ); + + /// Bidirectional serialize/deserialize a normalized quaternion in 6 bytes + 4 bits instead of 16 bytes. Slightly lossy. + /// \param[in] writeToBitstream true to write from your data to this bitstream. False to read from this bitstream and write to your data + /// \param[in] w w + /// \param[in] x x + /// \param[in] y y + /// \param[in] z z + /// \return true if \a writeToBitstream is true. true if \a writeToBitstream is false and the read was successful. false if \a writeToBitstream is false and the read was not successful. + template // templateType for this function must be a float or double + bool SerializeNormQuat(bool writeToBitstream, templateType &w, templateType &x, templateType &y, templateType &z); + + /// Bidirectional serialize/deserialize an orthogonal matrix by creating a quaternion, and writing 3 components of the quaternion in 2 bytes each + /// for 6 bytes instead of 36 + /// Lossy, although the result is renormalized + template // templateType for this function must be a float or double + bool SerializeOrthMatrix( + bool writeToBitstream, + templateType &m00, templateType &m01, templateType &m02, + templateType &m10, templateType &m11, templateType &m12, + templateType &m20, templateType &m21, templateType &m22 ); + + /// Bidirectional serialize/deserialize numberToSerialize bits to/from the input. Right aligned + /// data means in the case of a partial byte, the bits are aligned + /// from the right (bit 0) rather than the left (as in the normal + /// internal representation) You would set this to true when + /// writing user data, and false when copying bitstream data, such + /// as writing one bitstream to another + /// \param[in] writeToBitstream true to write from your data to this bitstream. False to read from this bitstream and write to your data + /// \param[in] input The data + /// \param[in] numberOfBitsToSerialize The number of bits to write + /// \param[in] rightAlignedBits if true data will be right aligned + /// \return true if \a writeToBitstream is true. true if \a writeToBitstream is false and the read was successful. false if \a writeToBitstream is false and the read was not successful. + bool SerializeBits(bool writeToBitstream, unsigned char* input, int numberOfBitsToSerialize, const bool rightAlignedBits = true ); + + /// Write any integral type to a bitstream. Undefine __BITSTREAM_NATIVE_END if you need endian swapping. + /// \param[in] var The value to write + template + void Write(templateType var); + + /// Write any integral type to a bitstream. If the current value is different from the last value + /// the current value will be written. Otherwise, a single bit will be written + /// \param[in] currentValue The current value to write + /// \param[in] lastValue The last value to compare against + template + void WriteDelta(templateType currentValue, templateType lastValue); + + /// WriteDelta when you don't know what the last value is, or there is no last value. + /// \param[in] currentValue The current value to write + template + void WriteDelta(templateType currentValue); + + /// Write any integral type to a bitstream. Undefine __BITSTREAM_NATIVE_END if you need endian swapping. + /// If you are not using __BITSTREAM_NATIVE_END the opposite is true for types larger than 1 byte + /// For floating point, this is lossy, using 2 bytes for a float and 4 for a double. The range must be between -1 and +1. + /// For non-floating point, this is lossless, but only has benefit if you use less than half the range of the type + /// \param[in] var The value to write + template + void WriteCompressed(templateType var); + + /// Write any integral type to a bitstream. If the current value is different from the last value + /// the current value will be written. Otherwise, a single bit will be written + /// For floating point, this is lossy, using 2 bytes for a float and 4 for a double. The range must be between -1 and +1. + /// For non-floating point, this is lossless, but only has benefit if you use less than half the range of the type + /// If you are not using __BITSTREAM_NATIVE_END the opposite is true for types larger than 1 byte + /// \param[in] currentValue The current value to write + /// \param[in] lastValue The last value to compare against + template + void WriteCompressedDelta(templateType currentValue, templateType lastValue); + + /// Save as WriteCompressedDelta(templateType currentValue, templateType lastValue) when we have an unknown second parameter + template + void WriteCompressedDelta(templateType currentValue); + + /// Read any integral type from a bitstream. Define __BITSTREAM_NATIVE_END if you need endian swapping. + /// \param[in] var The value to read + template + bool Read(templateType &var); + + /// Read any integral type from a bitstream. If the written value differed from the value compared against in the write function, + /// var will be updated. Otherwise it will retain the current value. + /// ReadDelta is only valid from a previous call to WriteDelta + /// \param[in] var The value to read + template + bool ReadDelta(templateType &var); + + /// Read any integral type from a bitstream. Undefine __BITSTREAM_NATIVE_END if you need endian swapping. + /// For floating point, this is lossy, using 2 bytes for a float and 4 for a double. The range must be between -1 and +1. + /// For non-floating point, this is lossless, but only has benefit if you use less than half the range of the type + /// If you are not using __BITSTREAM_NATIVE_END the opposite is true for types larger than 1 byte + /// \param[in] var The value to read + template + bool ReadCompressed(templateType &var); + + /// Read any integral type from a bitstream. If the written value differed from the value compared against in the write function, + /// var will be updated. Otherwise it will retain the current value. + /// the current value will be updated. + /// For floating point, this is lossy, using 2 bytes for a float and 4 for a double. The range must be between -1 and +1. + /// For non-floating point, this is lossless, but only has benefit if you use less than half the range of the type + /// If you are not using __BITSTREAM_NATIVE_END the opposite is true for types larger than 1 byte + /// ReadCompressedDelta is only valid from a previous call to WriteDelta + /// \param[in] var The value to read + template + bool ReadCompressedDelta(templateType &var); + + /// Write an array or casted stream or raw data. This does NOT do endian swapping. + /// \param[in] input a byte buffer + /// \param[in] numberOfBytes the size of \a input in bytes + void Write( const char* input, const int numberOfBytes ); + + /// Write one bitstream to another + /// \param[in] numberOfBits bits to write + /// \param bitStream the bitstream to copy from + void Write( BitStream *bitStream, int numberOfBits ); + void Write( BitStream *bitStream ); + + /// Read a normalized 3D vector, using (at most) 4 bytes + 3 bits instead of 12-24 bytes. Will further compress y or z axis aligned vectors. + /// Accurate to 1/32767.5. + /// \param[in] x x + /// \param[in] y y + /// \param[in] z z + template // templateType for this function must be a float or double + void WriteNormVector( templateType x, templateType y, templateType z ); + + /// Write a vector, using 10 bytes instead of 12. + /// Loses accuracy to about 3/10ths and only saves 2 bytes, so only use if accuracy is not important. + /// \param[in] x x + /// \param[in] y y + /// \param[in] z z + template // templateType for this function must be a float or double + void WriteVector( templateType x, templateType y, templateType z ); + + /// Write a normalized quaternion in 6 bytes + 4 bits instead of 16 bytes. Slightly lossy. + /// \param[in] w w + /// \param[in] x x + /// \param[in] y y + /// \param[in] z z + template // templateType for this function must be a float or double + void WriteNormQuat( templateType w, templateType x, templateType y, templateType z); + + /// Write an orthogonal matrix by creating a quaternion, and writing 3 components of the quaternion in 2 bytes each + /// for 6 bytes instead of 36 + /// Lossy, although the result is renormalized + template // templateType for this function must be a float or double + void WriteOrthMatrix( + templateType m00, templateType m01, templateType m02, + templateType m10, templateType m11, templateType m12, + templateType m20, templateType m21, templateType m22 ); + + /// Read an array or casted stream of byte. The array + /// is raw data. There is no automatic endian conversion with this function + /// \param[in] output The result byte array. It should be larger than @em numberOfBytes. + /// \param[in] numberOfBytes The number of byte to read + /// \return true on success false if there is some missing bytes. + bool Read( char* output, const int numberOfBytes ); + + /// Read a normalized 3D vector, using (at most) 4 bytes + 3 bits instead of 12-24 bytes. Will further compress y or z axis aligned vectors. + /// Accurate to 1/32767.5. + /// \param[in] x x + /// \param[in] y y + /// \param[in] z z + template // templateType for this function must be a float or double + bool ReadNormVector( templateType &x, templateType &y, templateType &z ); + + /// Read 3 floats or doubles, using 10 bytes, where those float or doubles comprise a vector + /// Loses accuracy to about 3/10ths and only saves 2 bytes, so only use if accuracy is not important. + /// \param[in] x x + /// \param[in] y y + /// \param[in] z z + template // templateType for this function must be a float or double + bool ReadVector( templateType &x, templateType &y, templateType &z ); + + /// Read a normalized quaternion in 6 bytes + 4 bits instead of 16 bytes. + /// \param[in] w w + /// \param[in] x x + /// \param[in] y y + /// \param[in] z z + template // templateType for this function must be a float or double + bool ReadNormQuat( templateType &w, templateType &x, templateType &y, templateType &z); + + /// Read an orthogonal matrix from a quaternion, reading 3 components of the quaternion in 2 bytes each and extrapolatig the 4th. + /// for 6 bytes instead of 36 + /// Lossy, although the result is renormalized + template // templateType for this function must be a float or double + bool ReadOrthMatrix( + templateType &m00, templateType &m01, templateType &m02, + templateType &m10, templateType &m11, templateType &m12, + templateType &m20, templateType &m21, templateType &m22 ); + + ///Sets the read pointer back to the beginning of your data. + void ResetReadPointer( void ); + + /// Sets the write pointer back to the beginning of your data. + void ResetWritePointer( void ); + + ///This is good to call when you are done with the stream to make + /// sure you didn't leave any data left over void + void AssertStreamEmpty( void ); + + /// printf the bits in the stream. Great for debugging. + void PrintBits( void ) const; + + /// Ignore data we don't intend to read + /// \param[in] numberOfBits The number of bits to ignore + void IgnoreBits( const int numberOfBits ); + + ///Move the write pointer to a position on the array. + /// \param[in] offset the offset from the start of the array. + /// \attention + /// Dangerous if you don't know what you are doing! + /// For efficiency reasons you can only write mid-stream if your data is byte aligned. + void SetWriteOffset( const int offset ); + + /// Returns the length in bits of the stream + inline int GetNumberOfBitsUsed( void ) const {return GetWriteOffset();} + inline int GetWriteOffset( void ) const {return numberOfBitsUsed;} + + ///Returns the length in bytes of the stream + inline int GetNumberOfBytesUsed( void ) const {return BITS_TO_BYTES( numberOfBitsUsed );} + + ///Returns the number of bits into the stream that we have read + inline int GetReadOffset( void ) const {return readOffset;} + + // Sets the read bit index + inline void SetReadOffset( int newReadOffset ) {readOffset=newReadOffset;} + + ///Returns the number of bits left in the stream that haven't been read + inline int GetNumberOfUnreadBits( void ) const {return numberOfBitsUsed - readOffset;} + + /// Makes a copy of the internal data for you \a _data will point to + /// the stream. Returns the length in bits of the stream. Partial + /// bytes are left aligned + /// \param[out] _data The allocated copy of GetData() + int CopyData( unsigned char** _data ) const; + + /// Set the stream to some initial data. + /// \internal + void SetData( unsigned char *input ); + + /// Gets the data that BitStream is writing to / reading from + /// Partial bytes are left aligned. + /// \return A pointer to the internal state + inline unsigned char* GetData( void ) const {return data;} + + /// Write numberToWrite bits from the input source Right aligned + /// data means in the case of a partial byte, the bits are aligned + /// from the right (bit 0) rather than the left (as in the normal + /// internal representation) You would set this to true when + /// writing user data, and false when copying bitstream data, such + /// as writing one bitstream to another + /// \param[in] input The data + /// \param[in] numberOfBitsToWrite The number of bits to write + /// \param[in] rightAlignedBits if true data will be right aligned + void WriteBits( const unsigned char* input, int numberOfBitsToWrite, const bool rightAlignedBits = true ); + + /// Align the bitstream to the byte boundary and then write the + /// specified number of bits. This is faster than WriteBits but + /// wastes the bits to do the alignment and requires you to call + /// ReadAlignedBits at the corresponding read position. + /// \param[in] input The data + /// \param[in] numberOfBytesToWrite The size of data. + void WriteAlignedBytes( const unsigned char *input, const int numberOfBytesToWrite ); + + /// Read bits, starting at the next aligned bits. Note that the + /// modulus 8 starting offset of the sequence must be the same as + /// was used with WriteBits. This will be a problem with packet + /// coalescence unless you byte align the coalesced packets. + /// \param[in] output The byte array larger than @em numberOfBytesToRead + /// \param[in] numberOfBytesToRead The number of byte to read from the internal state + /// \return true if there is enough byte. + bool ReadAlignedBytes( unsigned char *output, const int numberOfBytesToRead ); + + /// Align the next write and/or read to a byte boundary. This can + /// be used to 'waste' bits to byte align for efficiency reasons It + /// can also be used to force coalesced bitstreams to start on byte + /// boundaries so so WriteAlignedBits and ReadAlignedBits both + /// calculate the same offset when aligning. + void AlignWriteToByteBoundary( void ); + + /// Align the next write and/or read to a byte boundary. This can + /// be used to 'waste' bits to byte align for efficiency reasons It + /// can also be used to force coalesced bitstreams to start on byte + /// boundaries so so WriteAlignedBits and ReadAlignedBits both + /// calculate the same offset when aligning. + void AlignReadToByteBoundary( void ); + + /// Read \a numberOfBitsToRead bits to the output source + /// alignBitsToRight should be set to true to convert internal + /// bitstream data to userdata. It should be false if you used + /// WriteBits with rightAlignedBits false + /// \param[in] output The resulting bits array + /// \param[in] numberOfBitsToRead The number of bits to read + /// \param[in] alignBitsToRight if true bits will be right aligned. + /// \return true if there is enough bits to read + bool ReadBits( unsigned char *output, int numberOfBitsToRead, const bool alignBitsToRight = true ); + + /// Write a 0 + void Write0( void ); + + /// Write a 1 + void Write1( void ); + + /// Reads 1 bit and returns true if that bit is 1 and false if it is 0 + bool ReadBit( void ); + + /// If we used the constructor version with copy data off, this + /// *makes sure it is set to on and the data pointed to is copied. + void AssertCopyData( void ); + + /// Use this if you pass a pointer copy to the constructor + /// *(_copyData==false) and want to overallocate to prevent + /// *reallocation + void SetNumberOfBitsAllocated( const unsigned int lengthInBits ); + + /// Reallocates (if necessary) in preparation of writing numberOfBitsToWrite + void AddBitsAndReallocate( const int numberOfBitsToWrite ); + + + /// ---- Member function template specialization declarations ---- + // Used for VC7 +#if defined(_MSC_VER) && _MSC_VER == 1300 + /// Write a bool to a bitstream + /// \param[in] var The value to write + template <> + void Write(bool var); + + /// Write a systemAddress to a bitstream + /// \param[in] var The value to write + template <> + void Write(SystemAddress var); + + /// Write a systemAddress. If the current value is different from the last value + /// the current value will be written. Otherwise, a single bit will be written + /// \param[in] currentValue The current value to write + /// \param[in] lastValue The last value to compare against + template <> + void WriteDelta(SystemAddress currentValue, SystemAddress lastValue); + + /// Write an networkID to a bitstream + /// \param[in] var The value to write + template <> + void Write(NetworkID var); + + /// Write an networkID. If the current value is different from the last value + /// the current value will be written. Otherwise, a single bit will be written + /// \param[in] currentValue The current value to write + /// \param[in] lastValue The last value to compare against + template <> + void WriteDelta(NetworkID currentValue, NetworkID lastValue); + + /// Write a bool delta. Same thing as just calling Write + /// \param[in] currentValue The current value to write + /// \param[in] lastValue The last value to compare against + template <> + void WriteDelta(bool currentValue, bool lastValue); + + template <> + void WriteCompressed(SystemAddress var); + + template <> + void WriteCompressed(NetworkID var); + + template <> + void WriteCompressed(bool var); + + /// For values between -1 and 1 + template <> + void WriteCompressed(float var); + + /// For values between -1 and 1 + template <> + void WriteCompressed(double var); + + /// Write a bool delta. Same thing as just calling Write + /// \param[in] currentValue The current value to write + /// \param[in] lastValue The last value to compare against + template <> + void WriteCompressedDelta(bool currentValue, bool lastValue); + + /// Save as WriteCompressedDelta(bool currentValue, templateType lastValue) when we have an unknown second bool + template <> + void WriteCompressedDelta(bool currentValue); + + /// Read a bool from a bitstream + /// \param[in] var The value to read + template <> + bool Read(bool &var); + + /// Read a systemAddress from a bitstream + /// \param[in] var The value to read + template <> + bool Read(SystemAddress &var); + + /// Read an NetworkID from a bitstream + /// \param[in] var The value to read + template <> + bool Read(NetworkID &var); + + /// Read a bool from a bitstream + /// \param[in] var The value to read + template <> + bool ReadDelta(bool &var); + + template <> + bool ReadCompressed(SystemAddress &var); + + template <> + bool ReadCompressed(NetworkID &var); + + template <> + bool ReadCompressed(bool &var); + + template <> + bool ReadCompressed(float &var); + + /// For values between -1 and 1 + template <> + bool ReadCompressed(double &var); + + /// Read a bool from a bitstream + /// \param[in] var The value to read + template <> + bool ReadCompressedDelta(bool &var); +#endif + private: + + BitStream( const BitStream &invalid) { + #ifdef _MSC_VER + #pragma warning(disable:4100) + // warning C4100: 'invalid' : unreferenced formal parameter + #endif + + } + + /// Assume the input source points to a native type, compress and write it. + void WriteCompressed( const unsigned char* input, const int size, const bool unsignedData ); + + /// Assume the input source points to a compressed native type. Decompress and read it. + bool ReadCompressed( unsigned char* output, const int size, const bool unsignedData ); + + void ReverseBytes(unsigned char *input, unsigned char *output, int length); + + bool DoEndianSwap(void) const; + + int numberOfBitsUsed; + + int numberOfBitsAllocated; + + int readOffset; + + unsigned char *data; + + /// true if the internal buffer is copy of the data passed to the constructor + bool copyData; + + /// BitStreams that use less than BITSTREAM_STACK_ALLOCATION_SIZE use the stack, rather than the heap to store data. It switches over if BITSTREAM_STACK_ALLOCATION_SIZE is exceeded + unsigned char stackData[BITSTREAM_STACK_ALLOCATION_SIZE]; + }; + + template + inline bool BitStream::Serialize(bool writeToBitstream, templateType &var) + { + if (writeToBitstream) + Write(var); + else + return Read(var); + return true; + } + + template + inline bool BitStream::SerializeDelta(bool writeToBitstream, templateType ¤tValue, templateType lastValue) + { + if (writeToBitstream) + WriteDelta(currentValue, lastValue); + else + return ReadDelta(currentValue); + return true; + } + + template + inline bool BitStream::SerializeDelta(bool writeToBitstream, templateType ¤tValue) + { + if (writeToBitstream) + WriteDelta(currentValue); + else + return ReadDelta(currentValue); + return true; + } + + template + inline bool BitStream::SerializeCompressed(bool writeToBitstream, templateType &var) + { + if (writeToBitstream) + WriteCompressed(var); + else + return ReadCompressed(var); + return true; + } + + template + inline bool BitStream::SerializeCompressedDelta(bool writeToBitstream, templateType ¤tValue, templateType lastValue) + { + if (writeToBitstream) + WriteCompressedDelta(currentValue,lastValue); + else + return ReadCompressedDelta(currentValue); + return true; + } + + template + inline bool BitStream::SerializeCompressedDelta(bool writeToBitstream, templateType ¤tValue) + { + if (writeToBitstream) + WriteCompressedDelta(currentValue); + else + return ReadCompressedDelta(currentValue); + return true; + } + + inline bool BitStream::Serialize(bool writeToBitstream, char* input, const int numberOfBytes ) + { + if (writeToBitstream) + Write(input, numberOfBytes); + else + return Read(input, numberOfBytes); + return true; + } + + template + inline bool BitStream::SerializeNormVector(bool writeToBitstream, templateType &x, templateType &y, templateType &z ) + { + if (writeToBitstream) + WriteNormVector(x,y,z); + else + return ReadNormVector(x,y,z); + return true; + } + + template + inline bool BitStream::SerializeVector(bool writeToBitstream, templateType &x, templateType &y, templateType &z ) + { + if (writeToBitstream) + WriteVector(x,y,z); + else + return ReadVector(x,y,z); + return true; + } + + template + inline bool BitStream::SerializeNormQuat(bool writeToBitstream, templateType &w, templateType &x, templateType &y, templateType &z) + { + if (writeToBitstream) + WriteNormQuat(w,x,y,z); + else + return ReadNormQuat(w,x,y,z); + return true; + } + + template + inline bool BitStream::SerializeOrthMatrix( + bool writeToBitstream, + templateType &m00, templateType &m01, templateType &m02, + templateType &m10, templateType &m11, templateType &m12, + templateType &m20, templateType &m21, templateType &m22 ) + { + if (writeToBitstream) + WriteOrthMatrix(m00,m01,m02,m10,m11,m12,m20,m21,m22); + else + return ReadOrthMatrix(m00,m01,m02,m10,m11,m12,m20,m21,m22); + return true; + } + + inline bool BitStream::SerializeBits(bool writeToBitstream, unsigned char* input, int numberOfBitsToSerialize, const bool rightAlignedBits ) + { + if (writeToBitstream) + WriteBits(input,numberOfBitsToSerialize,rightAlignedBits); + else + return ReadBits(input,numberOfBitsToSerialize,rightAlignedBits); + return true; + } + + template + inline void BitStream::Write(templateType var) + { +#ifdef _MSC_VER +#pragma warning(disable:4127) // conditional expression is constant +#endif + if (sizeof(var)==1) + WriteBits( ( unsigned char* ) & var, sizeof( templateType ) * 8, true ); + else + { +#ifndef __BITSTREAM_NATIVE_END + if (DoEndianSwap()) + { + unsigned char output[sizeof(templateType)]; + ReverseBytes((unsigned char*)&var, output, sizeof(templateType)); + WriteBits( ( unsigned char* ) output, sizeof(templateType) * 8, true ); + } + else +#endif + WriteBits( ( unsigned char* ) & var, sizeof(templateType) * 8, true ); + } + } + + /// Write a bool to a bitstream + /// \param[in] var The value to write + template <> + inline void BitStream::Write(bool var) + { + if ( var ) + Write1(); + else + Write0(); + } + + /// Write a systemAddress to a bitstream + /// \param[in] var The value to write + template <> + inline void BitStream::Write(SystemAddress var) + { + // Write(var.binaryAddress); + WriteBits( ( unsigned char* ) & var.binaryAddress, sizeof(var.binaryAddress) * 8, true ); + Write(var.port); + } + + /// Write an networkID to a bitstream + /// \param[in] var The value to write + template <> + inline void BitStream::Write(NetworkID var) + { + if (NetworkID::IsPeerToPeerMode()) // Use the function rather than directly access the member or DLL users will get an undefined external error + Write(var.systemAddress); + Write(var.localSystemAddress); + } + + /// Write any integral type to a bitstream. If the current value is different from the last value + /// the current value will be written. Otherwise, a single bit will be written + /// \param[in] currentValue The current value to write + /// \param[in] lastValue The last value to compare against + template + inline void BitStream::WriteDelta(templateType currentValue, templateType lastValue) + { + if (currentValue==lastValue) + { + Write(false); + } + else + { + Write(true); + Write(currentValue); + } + } + + /// Write a systemAddress. If the current value is different from the last value + /// the current value will be written. Otherwise, a single bit will be written + /// \param[in] currentValue The current value to write + /// \param[in] lastValue The last value to compare against + template <> + inline void BitStream::WriteDelta(SystemAddress currentValue, SystemAddress lastValue) + { + if (currentValue==lastValue) + { + Write(false); + } + else + { + Write(true); + Write(currentValue.binaryAddress); + Write(currentValue.port); + } + } + + /// Write a systemAddress. If the current value is different from the last value + /// the current value will be written. Otherwise, a single bit will be written + /// \param[in] currentValue The current value to write + /// \param[in] lastValue The last value to compare against + template <> + inline void BitStream::WriteDelta(NetworkID currentValue, NetworkID lastValue) + { + if (currentValue==lastValue) + { + Write(false); + } + else + { + Write(true); + if (NetworkID::IsPeerToPeerMode()) // Use the function rather than directly access the member or DLL users will get an undefined external error + Write(currentValue.systemAddress); + Write(currentValue.localSystemAddress); + } + } + + /// Write a bool delta. Same thing as just calling Write + /// \param[in] currentValue The current value to write + /// \param[in] lastValue The last value to compare against + template <> + inline void BitStream::WriteDelta(bool currentValue, bool lastValue) + { +#ifdef _MSC_VER +#pragma warning(disable:4100) // warning C4100: 'lastValue' : unreferenced formal parameter +#endif + Write(currentValue); + } + + /// WriteDelta when you don't know what the last value is, or there is no last value. + /// \param[in] currentValue The current value to write + template + inline void BitStream::WriteDelta(templateType currentValue) + { + Write(true); + Write(currentValue); + } + + /// Write any integral type to a bitstream. Undefine __BITSTREAM_NATIVE_END if you need endian swapping. + /// For floating point, this is lossy, using 2 bytes for a float and 4 for a double. The range must be between -1 and +1. + /// For non-floating point, this is lossless, but only has benefit if you use less than half the range of the type + /// If you are not using __BITSTREAM_NATIVE_END the opposite is true for types larger than 1 byte + /// \param[in] var The value to write + template + inline void BitStream::WriteCompressed(templateType var) + { +#ifdef _MSC_VER +#pragma warning(disable:4127) // conditional expression is constant +#endif + if (sizeof(var)==1) + WriteCompressed( ( unsigned char* ) & var, sizeof( templateType ) * 8, true ); + else + { +#ifndef __BITSTREAM_NATIVE_END +#ifdef _MSC_VER +#pragma warning(disable:4244) // '=' : conversion from 'unsigned long' to 'unsigned short', possible loss of data +#endif + + if (DoEndianSwap()) + { + unsigned char output[sizeof(templateType)]; + ReverseBytes((unsigned char*)&var, output, sizeof(templateType)); + WriteCompressed( ( unsigned char* ) output, sizeof(templateType) * 8, true ); + } + else +#endif + WriteCompressed( ( unsigned char* ) & var, sizeof(templateType) * 8, true ); + } + } + + template <> + inline void BitStream::WriteCompressed(SystemAddress var) + { + Write(var); + } + + template <> + inline void BitStream::WriteCompressed(NetworkID var) + { + Write(var); + } + + template <> + inline void BitStream::WriteCompressed(bool var) + { + Write(var); + } + + /// For values between -1 and 1 + template <> + inline void BitStream::WriteCompressed(float var) + { + assert(var > -1.01f && var < 1.01f); + if (var < -1.0f) + var=-1.0f; + if (var > 1.0f) + var=1.0f; + Write((unsigned short)((var+1.0f)*32767.5f)); + } + + /// For values between -1 and 1 + template <> + inline void BitStream::WriteCompressed(double var) + { + assert(var > -1.01 && var < 1.01); + if (var < -1.0f) + var=-1.0f; + if (var > 1.0f) + var=1.0f; +#ifdef _DEBUG + assert(sizeof(unsigned long)==4); +#endif + Write((unsigned long)((var+1.0)*2147483648.0)); + } + + /// Write any integral type to a bitstream. If the current value is different from the last value + /// the current value will be written. Otherwise, a single bit will be written + /// For floating point, this is lossy, using 2 bytes for a float and 4 for a double. The range must be between -1 and +1. + /// For non-floating point, this is lossless, but only has benefit if you use less than half the range of the type + /// If you are not using __BITSTREAM_NATIVE_END the opposite is true for types larger than 1 byte + /// \param[in] currentValue The current value to write + /// \param[in] lastValue The last value to compare against + template + inline void BitStream::WriteCompressedDelta(templateType currentValue, templateType lastValue) + { + if (currentValue==lastValue) + { + Write(false); + } + else + { + Write(true); + WriteCompressed(currentValue); + } + } + + /// Write a bool delta. Same thing as just calling Write + /// \param[in] currentValue The current value to write + /// \param[in] lastValue The last value to compare against + template <> + inline void BitStream::WriteCompressedDelta(bool currentValue, bool lastValue) + { +#ifdef _MSC_VER +#pragma warning(disable:4100) // warning C4100: 'lastValue' : unreferenced formal parameter +#endif + Write(currentValue); + } + + /// Save as WriteCompressedDelta(templateType currentValue, templateType lastValue) when we have an unknown second parameter + template + inline void BitStream::WriteCompressedDelta(templateType currentValue) + { + Write(true); + WriteCompressed(currentValue); + } + + /// Save as WriteCompressedDelta(bool currentValue, templateType lastValue) when we have an unknown second bool + template <> + inline void BitStream::WriteCompressedDelta(bool currentValue) + { + Write(currentValue); + } + + /// Read any integral type from a bitstream. Define __BITSTREAM_NATIVE_END if you need endian swapping. + /// \param[in] var The value to read + template + inline bool BitStream::Read(templateType &var) + { +#ifdef _MSC_VER +#pragma warning(disable:4127) // conditional expression is constant +#endif + if (sizeof(var)==1) + return ReadBits( ( unsigned char* ) &var, sizeof(templateType) * 8, true ); + else + { +#ifndef __BITSTREAM_NATIVE_END +#ifdef _MSC_VER +#pragma warning(disable:4244) // '=' : conversion from 'unsigned long' to 'unsigned short', possible loss of data +#endif + if (DoEndianSwap()) + { + unsigned char output[sizeof(templateType)]; + if (ReadBits( ( unsigned char* ) output, sizeof(templateType) * 8, true )) + { + ReverseBytes(output, (unsigned char*)&var, sizeof(templateType)); + return true; + } + return false; + } + else +#endif + return ReadBits( ( unsigned char* ) & var, sizeof(templateType) * 8, true ); + } + } + + /// Read a bool from a bitstream + /// \param[in] var The value to read + template <> + inline bool BitStream::Read(bool &var) + { + if ( readOffset + 1 > numberOfBitsUsed ) + return false; + + if ( data[ readOffset >> 3 ] & ( 0x80 >> ( readOffset & 7 ) ) ) // Is it faster to just write it out here? + var = true; + else + var = false; + + // Has to be on a different line for Mac + readOffset++; + + return true; + } + + /// Read a systemAddress from a bitstream + /// \param[in] var The value to read + template <> + inline bool BitStream::Read(SystemAddress &var) + { + // Read(var.binaryAddress); + ReadBits( ( unsigned char* ) & var.binaryAddress, sizeof(var.binaryAddress) * 8, true ); + return Read(var.port); + } + + /// Read an networkID from a bitstream + /// \param[in] var The value to read + template <> + inline bool BitStream::Read(NetworkID &var) + { + if (NetworkID::IsPeerToPeerMode()) // Use the function rather than directly access the member or DLL users will get an undefined external error + Read(var.systemAddress); + return Read(var.localSystemAddress); + } + + /// Read any integral type from a bitstream. If the written value differed from the value compared against in the write function, + /// var will be updated. Otherwise it will retain the current value. + /// ReadDelta is only valid from a previous call to WriteDelta + /// \param[in] var The value to read + template + inline bool BitStream::ReadDelta(templateType &var) + { + bool dataWritten; + bool success; + success=Read(dataWritten); + if (dataWritten) + success=Read(var); + return success; + } + + /// Read a bool from a bitstream + /// \param[in] var The value to read + template <> + inline bool BitStream::ReadDelta(bool &var) + { + return Read(var); + } + + /// Read any integral type from a bitstream. Undefine __BITSTREAM_NATIVE_END if you need endian swapping. + /// For floating point, this is lossy, using 2 bytes for a float and 4 for a double. The range must be between -1 and +1. + /// For non-floating point, this is lossless, but only has benefit if you use less than half the range of the type + /// If you are not using __BITSTREAM_NATIVE_END the opposite is true for types larger than 1 byte + /// \param[in] var The value to read + template + inline bool BitStream::ReadCompressed(templateType &var) + { +#ifdef _MSC_VER +#pragma warning(disable:4127) // conditional expression is constant +#endif + if (sizeof(var)==1) + return ReadCompressed( ( unsigned char* ) &var, sizeof(templateType) * 8, true ); + else + { +#ifndef __BITSTREAM_NATIVE_END + if (DoEndianSwap()) + { + unsigned char output[sizeof(templateType)]; + if (ReadCompressed( ( unsigned char* ) output, sizeof(templateType) * 8, true )) + { + ReverseBytes(output, (unsigned char*)&var, sizeof(templateType)); + return true; + } + return false; + } + else +#endif + return ReadCompressed( ( unsigned char* ) & var, sizeof(templateType) * 8, true ); + } + } + + template <> + inline bool BitStream::ReadCompressed(SystemAddress &var) + { + return Read(var); + } + + template <> + inline bool BitStream::ReadCompressed(NetworkID &var) + { + return Read(var); + } + + template <> + inline bool BitStream::ReadCompressed(bool &var) + { + return Read(var); + } + + /// For values between -1 and 1 + template <> + inline bool BitStream::ReadCompressed(float &var) + { + unsigned short compressedFloat; + if (Read(compressedFloat)) + { + var = ((float)compressedFloat / 32767.5f - 1.0f); + return true; + } + return false; + } + + /// For values between -1 and 1 + template <> + inline bool BitStream::ReadCompressed(double &var) + { + unsigned long compressedFloat; + if (Read(compressedFloat)) + { + var = ((double)compressedFloat / 2147483648.0 - 1.0); + return true; + } + return false; + } + + + /// Read any integral type from a bitstream. If the written value differed from the value compared against in the write function, + /// var will be updated. Otherwise it will retain the current value. + /// the current value will be updated. + /// For floating point, this is lossy, using 2 bytes for a float and 4 for a double. The range must be between -1 and +1. + /// For non-floating point, this is lossless, but only has benefit if you use less than half the range of the type + /// If you are not using __BITSTREAM_NATIVE_END the opposite is true for types larger than 1 byte + /// ReadCompressedDelta is only valid from a previous call to WriteDelta + /// \param[in] var The value to read + template + inline bool BitStream::ReadCompressedDelta(templateType &var) + { + bool dataWritten; + bool success; + success=Read(dataWritten); + if (dataWritten) + success=ReadCompressed(var); + return success; + } + + /// Read a bool from a bitstream + /// \param[in] var The value to read + template <> + inline bool BitStream::ReadCompressedDelta(bool &var) + { + return Read(var); + } + + + template // templateType for this function must be a float or double + void BitStream::WriteNormVector( templateType x, templateType y, templateType z ) + { +#ifdef _DEBUG + assert(x <= 1.01 && y <= 1.01 && z <= 1.01 && x >= -1.01 && y >= -1.01 && z >= -1.01); +#endif + if (x>1.0) + x=1.0; + if (y>1.0) + y=1.0; + if (z>1.0) + z=1.0; + if (x<-1.0) + x=-1.0; + if (y<-1.0) + y=-1.0; + if (z<-1.0) + z=-1.0; + + Write((bool) (x < 0.0)); + if (y==0.0) + Write(true); + else + { + Write(false); + WriteCompressed((float)y); + //Write((unsigned short)((y+1.0f)*32767.5f)); + } + if (z==0.0) + Write(true); + else + { + Write(false); + WriteCompressed((float)z); + //Write((unsigned short)((z+1.0f)*32767.5f)); + } + } + + template // templateType for this function must be a float or double + void BitStream::WriteVector( templateType x, templateType y, templateType z ) + { + templateType magnitude = sqrt(x * x + y * y + z * z); + Write((float)magnitude); + if (magnitude > 0.0) + { + WriteCompressed((float)(x/magnitude)); + WriteCompressed((float)(y/magnitude)); + WriteCompressed((float)(z/magnitude)); + // Write((unsigned short)((x/magnitude+1.0f)*32767.5f)); + // Write((unsigned short)((y/magnitude+1.0f)*32767.5f)); + // Write((unsigned short)((z/magnitude+1.0f)*32767.5f)); + } + } + + template // templateType for this function must be a float or double + void BitStream::WriteNormQuat( templateType w, templateType x, templateType y, templateType z) + { + Write((bool)(w<0.0)); + Write((bool)(x<0.0)); + Write((bool)(y<0.0)); + Write((bool)(z<0.0)); + Write((unsigned short)(fabs(x)*65535.0)); + Write((unsigned short)(fabs(y)*65535.0)); + Write((unsigned short)(fabs(z)*65535.0)); + // Leave out w and calculate it on the target + } + + template // templateType for this function must be a float or double + void BitStream::WriteOrthMatrix( + templateType m00, templateType m01, templateType m02, + templateType m10, templateType m11, templateType m12, + templateType m20, templateType m21, templateType m22 ) + { + double qw; + double qx; + double qy; + double qz; + +#ifdef _MSC_VER +#pragma warning(disable:4100) // m10, m01 : unreferenced formal parameter +#endif + + // Convert matrix to quat + // http://www.euclideanspace.com/maths/geometry/rotations/conversions/matrixToQuaternion/ + float sum; + sum = 1 + m00 + m11 + m22; + if (sum < 0.0f) sum=0.0f; + qw = sqrt( sum ) / 2; + sum = 1 + m00 - m11 - m22; + if (sum < 0.0f) sum=0.0f; + qx = sqrt( sum ) / 2; + sum = 1 - m00 + m11 - m22; + if (sum < 0.0f) sum=0.0f; + qy = sqrt( sum ) / 2; + sum = 1 - m00 - m11 + m22; + if (sum < 0.0f) sum=0.0f; + qz = sqrt( sum ) / 2; + if (qw < 0.0) qw=0.0; + if (qx < 0.0) qx=0.0; + if (qy < 0.0) qy=0.0; + if (qz < 0.0) qz=0.0; + qx = _copysign( qx, m21 - m12 ); + qy = _copysign( qy, m02 - m20 ); + qz = _copysign( qz, m10 - m01 ); + + WriteNormQuat(qw,qx,qy,qz); + } + + template // templateType for this function must be a float or double + bool BitStream::ReadNormVector( templateType &x, templateType &y, templateType &z ) + { + // unsigned short sy, sz; + bool yZero, zZero; + bool xNeg; + float cy,cz; + + Read(xNeg); + + Read(yZero); + if (yZero) + y=0.0; + else + { + ReadCompressed((float)cy); + y=cy; + //Read(sy); + //y=((float)sy / 32767.5f - 1.0f); + } + + if (!Read(zZero)) + return false; + + if (zZero) + z=0.0; + else + { + // if (!Read(sz)) + // return false; + + // z=((float)sz / 32767.5f - 1.0f); + if (!ReadCompressed((float)cz)) + return false; + z=cz; + } + + x = (templateType) (sqrtf((templateType)1.0 - y*y - z*z)); + if (xNeg) + x=-x; + return true; + } + + template // templateType for this function must be a float or double + bool BitStream::ReadVector( templateType &x, templateType &y, templateType &z ) + { + float magnitude; + //unsigned short sx,sy,sz; + if (!Read(magnitude)) + return false; + if (magnitude!=0.0) + { + // Read(sx); + // Read(sy); + // if (!Read(sz)) + // return false; + // x=((float)sx / 32767.5f - 1.0f) * magnitude; + // y=((float)sy / 32767.5f - 1.0f) * magnitude; + // z=((float)sz / 32767.5f - 1.0f) * magnitude; + float cx,cy,cz; + ReadCompressed(cx); + ReadCompressed(cy); + if (!ReadCompressed(cz)) + return false; + x=cx; + y=cy; + z=cz; + x*=magnitude; + y*=magnitude; + z*=magnitude; + } + else + { + x=0.0; + y=0.0; + z=0.0; + } + return true; + } + + template // templateType for this function must be a float or double + bool BitStream::ReadNormQuat( templateType &w, templateType &x, templateType &y, templateType &z) + { + bool cwNeg, cxNeg, cyNeg, czNeg; + unsigned short cx,cy,cz; + Read(cwNeg); + Read(cxNeg); + Read(cyNeg); + Read(czNeg); + Read(cx); + Read(cy); + if (!Read(cz)) + return false; + + // Calculate w from x,y,z + x=(templateType)(cx/65535.0); + y=(templateType)(cy/65535.0); + z=(templateType)(cz/65535.0); + if (cxNeg) x=-x; + if (cyNeg) y=-y; + if (czNeg) z=-z; + float difference = 1.0 - x*x - y*y - z*z; + if (difference < 0.0f) + difference=0.0f; + w = (templateType)(sqrt(difference)); + if (cwNeg) + w=-w; + return true; + } + + template // templateType for this function must be a float or double + bool BitStream::ReadOrthMatrix( + templateType &m00, templateType &m01, templateType &m02, + templateType &m10, templateType &m11, templateType &m12, + templateType &m20, templateType &m21, templateType &m22 ) + { + float qw,qx,qy,qz; + if (!ReadNormQuat(qw,qx,qy,qz)) + return false; + + // Quat to orthogonal rotation matrix + // http://www.euclideanspace.com/maths/geometry/rotations/conversions/quaternionToMatrix/index.htm + double sqw = (double)qw*(double)qw; + double sqx = (double)qx*(double)qx; + double sqy = (double)qy*(double)qy; + double sqz = (double)qz*(double)qz; + m00 = (templateType)(sqx - sqy - sqz + sqw); // since sqw + sqx + sqy + sqz =1 + m11 = (templateType)(-sqx + sqy - sqz + sqw); + m22 = (templateType)(-sqx - sqy + sqz + sqw); + + double tmp1 = (double)qx*(double)qy; + double tmp2 = (double)qz*(double)qw; + m10 = (templateType)(2.0 * (tmp1 + tmp2)); + m01 = (templateType)(2.0 * (tmp1 - tmp2)); + + tmp1 = (double)qx*(double)qz; + tmp2 = (double)qy*(double)qw; + m20 =(templateType)(2.0 * (tmp1 - tmp2)); + m02 = (templateType)(2.0 * (tmp1 + tmp2)); + tmp1 = (double)qy*(double)qz; + tmp2 = (double)qx*(double)qw; + m21 = (templateType)(2.0 * (tmp1 + tmp2)); + m12 = (templateType)(2.0 * (tmp1 - tmp2)); + + return true; + } +} + +#ifdef _MSC_VER +#pragma warning( pop ) +#endif + +#endif + +#endif // VC6 diff --git a/Multiplayer/raknet/Export.h b/Multiplayer/raknet/Export.h new file mode 100644 index 00000000..bbbfb0b1 --- /dev/null +++ b/Multiplayer/raknet/Export.h @@ -0,0 +1,6 @@ +// Fuck it, GCC won't compile with exports. Someone else can fix this if they want +#if defined(_WIN32) && !(defined(__GNUC__) || defined(__GCCXML__)) && !defined(_RAKNET_LIB) && defined(_RAKNET_DLL) +#define RAK_DLL_EXPORT __declspec(dllexport) +#else +#define RAK_DLL_EXPORT +#endif diff --git a/Multiplayer/raknet/MessageIdentifiers.h b/Multiplayer/raknet/MessageIdentifiers.h new file mode 100644 index 00000000..17cddf01 --- /dev/null +++ b/Multiplayer/raknet/MessageIdentifiers.h @@ -0,0 +1,212 @@ +/// \file +/// \brief All the message identifiers used by RakNet. Message identifiers comprise the first byte of any message. +/// +/// This file is part of RakNet Copyright 2003 Kevin Jenkins. +/// +/// Usage of RakNet is subject to the appropriate license agreement. +/// Creative Commons Licensees are subject to the +/// license found at +/// http://creativecommons.org/licenses/by-nc/2.5/ +/// Single application licensees are subject to the license found at +/// http://www.rakkarsoft.com/SingleApplicationLicense.html +/// Custom license users are subject to the terms therein. +/// GPL license users are subject to the GNU General Public +/// License as published by the Free +/// Software Foundation; either version 2 of the License, or (at your +/// option) any later version. + +#ifndef __MESSAGE_IDENTIFIERS_H +#define __MESSAGE_IDENTIFIERS_H + +/// You should not edit the file MessageIdentifiers.h as it is a part of RakNet static library +/// To define your own message id, define an enum following the code example that follows. +/// +/// \code +/// enum { +/// ID_MYPROJECT_MSG_1 = ID_USER_PACKET_ENUM, +/// ID_MYPROJECT_MSG_2, +/// ... +/// }; +/// \endcode +/// +/// \note All these enumerations should be casted to (unsigned char) before writing them to RakNet::BitStream +enum +{ + // + // RESERVED TYPES - DO NOT CHANGE THESE + // All types from RakPeer + // + /// These types are never returned to the user. + /// Ping from a connected system. Update timestamps (internal use only) + ID_INTERNAL_PING, + /// Ping from an unconnected system. Reply but do not update timestamps. (internal use only) + ID_PING, + /// Ping from an unconnected system. Only reply if we have open connections. Do not update timestamps. (internal use only) + ID_PING_OPEN_CONNECTIONS, + /// Pong from a connected system. Update timestamps (internal use only) + ID_CONNECTED_PONG, + /// Asking for a new connection (internal use only) + ID_CONNECTION_REQUEST, + /// Connecting to a secured server/peer (internal use only) + ID_SECURED_CONNECTION_RESPONSE, + /// Connecting to a secured server/peer (internal use only) + ID_SECURED_CONNECTION_CONFIRMATION, + /// Packet that tells us the packet contains an integer ID to name mapping for the remote system (internal use only) + ID_RPC_MAPPING, + /// A reliable packet to detect lost connections (internal use only) + ID_DETECT_LOST_CONNECTIONS, + /// Offline message so we know when to reset and start a new connection (internal use only) + ID_OPEN_CONNECTION_REQUEST, + /// Offline message response so we know when to reset and start a new connection (internal use only) + ID_OPEN_CONNECTION_REPLY, + /// Remote procedure call (internal use only) + ID_RPC, + /// Remote procedure call reply, for RPCs that return data (internal use only) + ID_RPC_REPLY, + + // + // USER TYPES - DO NOT CHANGE THESE + // + + /// RakPeer - In a client/server environment, our connection request to the server has been accepted. + ID_CONNECTION_REQUEST_ACCEPTED, + /// RakPeer - Sent to the player when a connection request cannot be completed due to inability to connect. + ID_CONNECTION_ATTEMPT_FAILED, + /// RakPeer - Sent a connect request to a system we are currently connected to. + ID_ALREADY_CONNECTED, + /// RakPeer - A remote system has successfully connected. + ID_NEW_INCOMING_CONNECTION, + /// RakPeer - The system we attempted to connect to is not accepting new connections. + ID_NO_FREE_INCOMING_CONNECTIONS, + /// RakPeer - The system specified in Packet::systemAddress has disconnected from us. For the client, this would mean the server has shutdown. + ID_DISCONNECTION_NOTIFICATION, + /// RakPeer - Reliable packets cannot be delivered to the system specified in Packet::systemAddress. The connection to that system has been closed. + ID_CONNECTION_LOST, + /// RakPeer - We preset an RSA public key which does not match what the system we connected to is using. + ID_RSA_PUBLIC_KEY_MISMATCH, + /// RakPeer - We are banned from the system we attempted to connect to. + ID_CONNECTION_BANNED, + /// RakPeer - The remote system is using a password and has refused our connection because we did not set the correct password. + ID_INVALID_PASSWORD, + /// RakPeer - A packet has been tampered with in transit. The sender is contained in Packet::systemAddress. + ID_MODIFIED_PACKET, + /// RakPeer - The four bytes following this byte represent an unsigned int which is automatically modified by the difference in system times between the sender and the recipient. Requires that you call SetOccasionalPing. + ID_TIMESTAMP, + /// RakPeer - Pong from an unconnected system. First byte is ID_PONG, second sizeof(RakNetTime) bytes is the ping, following bytes is system specific enumeration data. + ID_PONG, + /// RakPeer - Inform a remote system of our IP/Port, plus some offline data + ID_ADVERTISE_SYSTEM, + /// ConnectionGraph plugin - In a client/server environment, a client other than ourselves has disconnected gracefully. Packet::systemAddress is modified to reflect the systemAddress of this client. + ID_REMOTE_DISCONNECTION_NOTIFICATION, + /// ConnectionGraph plugin - In a client/server environment, a client other than ourselves has been forcefully dropped. Packet::systemAddress is modified to reflect the systemAddress of this client. + ID_REMOTE_CONNECTION_LOST, + /// ConnectionGraph plugin - In a client/server environment, a client other than ourselves has connected. Packet::systemAddress is modified to reflect the systemAddress of this client. + ID_REMOTE_NEW_INCOMING_CONNECTION, + // RakPeer - Downloading a large message. Format is ID_DOWNLOAD_PROGRESS (MessageID), partCount (unsigned int), partTotal (unsigned int), partLength (unsigned int), first part data (length <= MAX_MTU_SIZE) + ID_DOWNLOAD_PROGRESS, + + /// FileListTransfer plugin - Setup data + ID_FILE_LIST_TRANSFER_HEADER, + /// FileListTransfer plugin - A file + ID_FILE_LIST_TRANSFER_FILE, + + /// DirectoryDeltaTransfer plugin - Request from a remote system for a download of a directory + ID_DDT_DOWNLOAD_REQUEST, + + /// RakNetTransport plugin - Transport provider message, used for remote console + ID_TRANSPORT_STRING, + + /// ReplicaManager plugin - Create an object + ID_REPLICA_MANAGER_CONSTRUCTION, + /// ReplicaManager plugin - Destroy an object + ID_REPLICA_MANAGER_DESTRUCTION, + /// ReplicaManager plugin - Changed scope of an object + ID_REPLICA_MANAGER_SCOPE_CHANGE, + /// ReplicaManager plugin - Serialized data of an object + ID_REPLICA_MANAGER_SERIALIZE, + /// ReplicaManager plugin - Finished downloading all serialized objects + ID_REPLICA_MANAGER_DOWNLOAD_COMPLETE, + + /// ConnectionGraph plugin - Request the connection graph from another system + ID_CONNECTION_GRAPH_REQUEST, + /// ConnectionGraph plugin - Reply to a connection graph download request + ID_CONNECTION_GRAPH_REPLY, + /// ConnectionGraph plugin - Update edges / nodes for a system with a connection graph + ID_CONNECTION_GRAPH_UPDATE, + /// ConnectionGraph plugin - Add a new connection to a connection graph + ID_CONNECTION_GRAPH_NEW_CONNECTION, + /// ConnectionGraph plugin - Remove a connection from a connection graph - connection was abruptly lost + ID_CONNECTION_GRAPH_CONNECTION_LOST, + /// ConnectionGraph plugin - Remove a connection from a connection graph - connection was gracefully lost + ID_CONNECTION_GRAPH_DISCONNECTION_NOTIFICATION, + + /// Router plugin - route a message through another system + ID_ROUTE_AND_MULTICAST, + + /// RakVoice plugin - Open a communication channel + ID_RAKVOICE_OPEN_CHANNEL_REQUEST, + /// RakVoice plugin - Communication channel accepted + ID_RAKVOICE_OPEN_CHANNEL_REPLY, + /// RakVoice plugin - Close a communication channel + ID_RAKVOICE_CLOSE_CHANNEL, + /// RakVoice plugin - Voice data + ID_RAKVOICE_DATA, + + /// Autopatcher plugin - Get a list of files that have changed since a certain date + ID_AUTOPATCHER_GET_CHANGELIST_SINCE_DATE, + /// Autopatcher plugin - A list of files to create + ID_AUTOPATCHER_CREATION_LIST, + /// Autopatcher plugin - A list of files to delete + ID_AUTOPATCHER_DELETION_LIST, + /// Autopatcher plugin - A list of files to get patches for + ID_AUTOPATCHER_GET_PATCH, + /// Autopatcher plugin - A list of patches for a list of files + ID_AUTOPATCHER_PATCH_LIST, + /// Autopatcher plugin - Returned to the user: An error from the database repository for the autopatcher. + ID_AUTOPATCHER_REPOSITORY_FATAL_ERROR, + /// Autopatcher plugin - Finished getting all files from the autopatcher + ID_AUTOPATCHER_FINISHED_INTERNAL, + ID_AUTOPATCHER_FINISHED, + /// Autopatcher plugin - Returned to the user: You must restart the application to finish patching. + ID_AUTOPATCHER_RESTART_APPLICATION, + + /// NATPunchthrough plugin - Intermediary got a request to help punch through a nat + ID_NAT_PUNCHTHROUGH_REQUEST, + /// NATPunchthrough plugin - Intermediary cannot complete the request because the target system is not connected + ID_NAT_TARGET_NOT_CONNECTED, + /// NATPunchthrough plugin - While attempting to connect, we lost the connection to the target system + ID_NAT_TARGET_CONNECTION_LOST, + /// NATPunchthrough plugin - Internal message to connect at a certain time + ID_NAT_CONNECT_AT_TIME, + /// NATPunchthrough plugin - Internal message to send a message (to punch through the nat) at a certain time + ID_NAT_SEND_OFFLINE_MESSAGE_AT_TIME, + + /// LightweightDatabase plugin - Query + ID_DATABASE_QUERY_REQUEST, + /// LightweightDatabase plugin - Update + ID_DATABASE_UPDATE_ROW, + /// LightweightDatabase plugin - Remove + ID_DATABASE_REMOVE_ROW, + /// LightweightDatabase plugin - A serialized table. Bytes 1+ contain the table. Pass to TableSerializer::DeserializeTable + ID_DATABASE_QUERY_REPLY, + /// LightweightDatabase plugin - Specified table not found + ID_DATABASE_UNKNOWN_TABLE, + /// LightweightDatabase plugin - Incorrect password + ID_DATABASE_INCORRECT_PASSWORD, + + /// ReadyEvent plugin - Set the ready state for a particular system + ID_READY_EVENT_SET, + /// ReadyEvent plugin - Unset the ready state for a particular system + ID_READY_EVENT_UNSET, + /// All systems are in state ID_READY_EVENT_SET + ID_READY_EVENT_ALL_SET, + /// ReadyEvent plugin - Request of ready event state - used for pulling data when newly connecting + ID_READY_EVENT_QUERY, + + // For the user to use. Start your first enumeration at this value. + ID_USER_PACKET_ENUM, + //------------------------------------------------------------------------------------------------------------- + +}; + +#endif diff --git a/Multiplayer/raknet/PacketPriority.h b/Multiplayer/raknet/PacketPriority.h new file mode 100644 index 00000000..9ff92232 --- /dev/null +++ b/Multiplayer/raknet/PacketPriority.h @@ -0,0 +1,42 @@ +/// \file +/// \brief This file contains enumerations for packet priority and reliability enumerations. +/// +/// This file is part of RakNet Copyright 2003 Kevin Jenkins. +/// +/// Usage of RakNet is subject to the appropriate license agreement. +/// Creative Commons Licensees are subject to the +/// license found at +/// http://creativecommons.org/licenses/by-nc/2.5/ +/// Single application licensees are subject to the license found at +/// http://www.rakkarsoft.com/SingleApplicationLicense.html +/// Custom license users are subject to the terms therein. +/// GPL license users are subject to the GNU General Public +/// License as published by the Free +/// Software Foundation; either version 2 of the License, or (at your +/// option) any later version. + +#ifndef __PACKET_PRIORITY_H +#define __PACKET_PRIORITY_H + +/// These enumerations are used to describe when packets are delivered. +enum PacketPriority +{ + SYSTEM_PRIORITY, /// \internal Used by RakNet to send above-high priority messages. + HIGH_PRIORITY, /// High priority messages are send before medium priority messages. + MEDIUM_PRIORITY, /// Medium priority messages are send before low priority messages. + LOW_PRIORITY, /// Low priority messages are only sent when no other messages are waiting. + NUMBER_OF_PRIORITIES +}; + +/// These enumerations are used to describe how packets are delivered. +/// \note Note to self: I write this with 3 bits in the stream. If I add more remember to change that +enum PacketReliability +{ + UNRELIABLE, /// Same as regular UDP, except that it will also discard duplicate datagrams. RakNet adds (6 to 17) + 21 bits of overhead, 16 of which is used to detect duplicate packets and 6 to 17 of which is used for message length. + UNRELIABLE_SEQUENCED, /// Regular UDP with a sequence counter. Out of order messages will be discarded. This adds an additional 13 bits on top what is used for UNRELIABLE. + RELIABLE, /// The message is sent reliably, but not necessarily in any order. Same overhead as UNRELIABLE. + RELIABLE_ORDERED, /// This message is reliable and will arrive in the order you sent it. Messages will be delayed while waiting for out of order messages. Same overhead as UNRELIABLE_SEQUENCED. + RELIABLE_SEQUENCED /// This message is reliable and will arrive in the sequence you sent it. Out or order messages will be dropped. Same overhead as UNRELIABLE_SEQUENCED. +}; + +#endif diff --git a/Multiplayer/raknet/RakNetDefines.h b/Multiplayer/raknet/RakNetDefines.h new file mode 100644 index 00000000..3de9af8e --- /dev/null +++ b/Multiplayer/raknet/RakNetDefines.h @@ -0,0 +1,30 @@ +/// Define __GET_TIME_64BIT to have RakNetTime use a 64, rather than 32 bit value. A 32 bit value will overflow after about 5 weeks. +/// However, this doubles the bandwidth use for sending times, so don't do it unless you have a reason to. +/// Disabled by default. +// #define __GET_TIME_64BIT + +/// Makes RakNet threadsafe +/// Define this if you use the same instance of RakPeer from multiple threads +/// Otherwise leave it undefined, since it makes things an order of magnitude slower. +/// Disabled by default +// #define _RAKNET_THREADSAFE + +/// Define __BITSTREAM_NATIVE_END to NOT support endian swapping in the BitStream class. This is faster and is what you should use +/// unless you actually plan to have different endianness systems connect to each other +/// Enabled by default. +#define __BITSTREAM_NATIVE_END + +#if defined(_CONSOLE_2) +#undef __BITSTREAM_NATIVE_END +#endif + +/// Maximum (stack) size to use with _alloca before using new and delete instead. +#define MAX_ALLOCA_STACK_ALLOCATION 1048576 + +// Use WaitForSingleObject instead of sleep. +// Defining it plays nicer with other systems, and uses less CPU, but gives worse RakNet performance +// Undefining it uses more CPU time, but is more responsive and faster. +#define USE_WAIT_FOR_MULTIPLE_EVENTS + +// If you need it +#define RAKNET_VERSION "3.0 09/07/07" diff --git a/Multiplayer/raknet/RakNetLibStatic.lib b/Multiplayer/raknet/RakNetLibStatic.lib new file mode 100644 index 00000000..b61bfc97 Binary files /dev/null and b/Multiplayer/raknet/RakNetLibStatic.lib differ diff --git a/Multiplayer/raknet/RakNetLibStaticDebug.idb b/Multiplayer/raknet/RakNetLibStaticDebug.idb new file mode 100644 index 00000000..a1e1ff75 Binary files /dev/null and b/Multiplayer/raknet/RakNetLibStaticDebug.idb differ diff --git a/Multiplayer/raknet/RakNetLibStaticDebug.lib b/Multiplayer/raknet/RakNetLibStaticDebug.lib new file mode 100644 index 00000000..dc3f09c6 Binary files /dev/null and b/Multiplayer/raknet/RakNetLibStaticDebug.lib differ diff --git a/Multiplayer/raknet/RakNetStatistics.h b/Multiplayer/raknet/RakNetStatistics.h new file mode 100644 index 00000000..f521e16d --- /dev/null +++ b/Multiplayer/raknet/RakNetStatistics.h @@ -0,0 +1,172 @@ +/// \file +/// \brief A structure that holds all statistical data returned by RakNet. +/// +/// This file is part of RakNet Copyright 2003 Kevin Jenkins. +/// +/// Usage of RakNet is subject to the appropriate license agreement. +/// Creative Commons Licensees are subject to the +/// license found at +/// http://creativecommons.org/licenses/by-nc/2.5/ +/// Single application licensees are subject to the license found at +/// http://www.rakkarsoft.com/SingleApplicationLicense.html +/// Custom license users are subject to the terms therein. +/// GPL license users are subject to the GNU General Public +/// License as published by the Free +/// Software Foundation; either version 2 of the License, or (at your +/// option) any later version. + + +#ifndef __RAK_NET_STATISTICS_H +#define __RAK_NET_STATISTICS_H + +#include "PacketPriority.h" +#include "Export.h" +#include "RakNetTypes.h" + +/// \brief Network Statisics Usage +/// +/// Store Statistics information related to network usage +struct RAK_DLL_EXPORT RakNetStatistics +{ + /// Number of Messages in the send Buffer (high, medium, low priority) + unsigned messageSendBuffer[ NUMBER_OF_PRIORITIES ]; + /// Number of messages sent (high, medium, low priority) + unsigned messagesSent[ NUMBER_OF_PRIORITIES ]; + /// Number of data bits used for user messages + unsigned messageDataBitsSent[ NUMBER_OF_PRIORITIES ]; + /// Number of total bits used for user messages, including headers + unsigned messageTotalBitsSent[ NUMBER_OF_PRIORITIES ]; + + /// Number of packets sent containing only acknowledgements + unsigned packetsContainingOnlyAcknowlegements; + /// Number of acknowledgements sent + unsigned acknowlegementsSent; + /// Number of acknowledgements waiting to be sent + unsigned acknowlegementsPending; + /// Number of acknowledgements bits sent + unsigned acknowlegementBitsSent; + + /// Number of packets containing only acknowledgements and resends + unsigned packetsContainingOnlyAcknowlegementsAndResends; + + /// Number of messages resent + unsigned messageResends; + /// Number of bits resent of actual data + unsigned messageDataBitsResent; + /// Total number of bits resent, including headers + unsigned messagesTotalBitsResent; + /// Number of messages waiting for ack (// TODO - rename this) + unsigned messagesOnResendQueue; + + /// Number of messages not split for sending + unsigned numberOfUnsplitMessages; + /// Number of messages split for sending + unsigned numberOfSplitMessages; + /// Total number of splits done for sending + unsigned totalSplits; + + /// Total packets sent + unsigned packetsSent; + + /// Number of bits added by encryption + unsigned encryptionBitsSent; + /// total bits sent + unsigned totalBitsSent; + + /// Number of sequenced messages arrived out of order + unsigned sequencedMessagesOutOfOrder; + /// Number of sequenced messages arrived in order + unsigned sequencedMessagesInOrder; + + /// Number of ordered messages arrived out of order + unsigned orderedMessagesOutOfOrder; + /// Number of ordered messages arrived in order + unsigned orderedMessagesInOrder; + + /// Packets with a good CRC received + unsigned packetsReceived; + /// Packets with a bad CRC received + unsigned packetsWithBadCRCReceived; + /// Bits with a good CRC received + unsigned bitsReceived; + /// Bits with a bad CRC received + unsigned bitsWithBadCRCReceived; + /// Number of acknowledgement messages received for packets we are resending + unsigned acknowlegementsReceived; + /// Number of acknowledgement messages received for packets we are not resending + unsigned duplicateAcknowlegementsReceived; + /// Number of data messages (anything other than an ack) received that are valid and not duplicate + unsigned messagesReceived; + /// Number of data messages (anything other than an ack) received that are invalid + unsigned invalidMessagesReceived; + /// Number of data messages (anything other than an ack) received that are duplicate + unsigned duplicateMessagesReceived; + /// Number of messages waiting for reassembly + unsigned messagesWaitingForReassembly; + /// Number of messages in reliability output queue + unsigned internalOutputQueueSize; + /// Current bits per second + double bitsPerSecond; + /// connection start time + RakNetTime connectionStartTime; + // If true, not all the data can go out in one frame, and RakNet is sending continuously + // RakNet will try to increase the bandwidth, so this condition may be temporary and only last a second. However, it if + // stays on most of the time, you are at the maximum bandwidth and should slow down your sends, because other data is now waiting. + bool bandwidthExceeded; + + RakNetStatistics operator +=(const RakNetStatistics& other) + { + unsigned i; + for (i=0; i < NUMBER_OF_PRIORITIES; i++) + { + messageSendBuffer[i]+=other.messageSendBuffer[i]; + messagesSent[i]+=other.messagesSent[i]; + messageDataBitsSent[i]+=other.messageDataBitsSent[i]; + messageTotalBitsSent[i]+=other.messageTotalBitsSent[i]; + } + + packetsContainingOnlyAcknowlegements+=other.packetsContainingOnlyAcknowlegements; + acknowlegementsSent+=other.packetsContainingOnlyAcknowlegements; + acknowlegementsPending+=other.acknowlegementsPending; + acknowlegementBitsSent+=other.acknowlegementBitsSent; + packetsContainingOnlyAcknowlegementsAndResends+=other.packetsContainingOnlyAcknowlegementsAndResends; + messageResends+=other.messageResends; + messageDataBitsResent+=other.messageDataBitsResent; + messagesTotalBitsResent+=other.messagesTotalBitsResent; + messagesOnResendQueue+=other.messagesOnResendQueue; + numberOfUnsplitMessages+=other.numberOfUnsplitMessages; + numberOfSplitMessages+=other.numberOfSplitMessages; + totalSplits+=other.totalSplits; + packetsSent+=other.packetsSent; + encryptionBitsSent+=other.encryptionBitsSent; + totalBitsSent+=other.totalBitsSent; + sequencedMessagesOutOfOrder+=other.sequencedMessagesOutOfOrder; + sequencedMessagesInOrder+=other.sequencedMessagesInOrder; + orderedMessagesOutOfOrder+=other.orderedMessagesOutOfOrder; + orderedMessagesInOrder+=other.orderedMessagesInOrder; + packetsReceived+=other.packetsReceived; + packetsWithBadCRCReceived+=other.packetsWithBadCRCReceived; + bitsReceived+=other.bitsReceived; + bitsWithBadCRCReceived+=other.bitsWithBadCRCReceived; + acknowlegementsReceived+=other.acknowlegementsReceived; + duplicateAcknowlegementsReceived+=other.duplicateAcknowlegementsReceived; + messagesReceived+=other.messagesReceived; + invalidMessagesReceived+=other.invalidMessagesReceived; + duplicateMessagesReceived+=other.duplicateMessagesReceived; + messagesWaitingForReassembly+=other.messagesWaitingForReassembly; + internalOutputQueueSize+=other.internalOutputQueueSize; + + return *this; + } +}; + +/// Verbosity level currently supports 0 (low), 1 (medium), 2 (high) +/// \param[in] s The Statistical information to format out +/// \param[in] buffer The buffer containing a formated report +/// \param[in] verbosityLevel +/// 0 low +/// 1 medium +/// 2 high +void RAK_DLL_EXPORT StatisticsToString( RakNetStatistics *s, char *buffer, int verbosityLevel ); + +#endif diff --git a/Multiplayer/raknet/RakNetTypes.h b/Multiplayer/raknet/RakNetTypes.h new file mode 100644 index 00000000..2d98a917 --- /dev/null +++ b/Multiplayer/raknet/RakNetTypes.h @@ -0,0 +1,273 @@ +/// \file +/// \brief Types used by RakNet, most of which involve user code. +/// +/// This file is part of RakNet Copyright 2003 Kevin Jenkins. +/// +/// Usage of RakNet is subject to the appropriate license agreement. +/// Creative Commons Licensees are subject to the +/// license found at +/// http://creativecommons.org/licenses/by-nc/2.5/ +/// Single application licensees are subject to the license found at +/// http://www.rakkarsoft.com/SingleApplicationLicense.html +/// Custom license users are subject to the terms therein. +/// GPL license users are subject to the GNU General Public +/// License as published by the Free +/// Software Foundation; either version 2 of the License, or (at your +/// option) any later version. + +#ifndef __NETWORK_TYPES_H +#define __NETWORK_TYPES_H + +#include "RakNetDefines.h" +#include "Export.h" + +/// Forward declaration +namespace RakNet +{ + class BitStream; +}; + +/// Given a number of bits, return how many bytes are needed to represent that. +#define BITS_TO_BYTES(x) (((x)+7)>>3) +#define BYTES_TO_BITS(x) ((x)<<3) + +/// \sa NetworkIDObject.h +typedef unsigned char UniqueIDType; +typedef unsigned short SystemIndex; +typedef unsigned char RPCIndex; +const int MAX_RPC_MAP_SIZE=((RPCIndex)-1)-1; +const int UNDEFINED_RPC_INDEX=((RPCIndex)-1); + +/// First byte of a network message +typedef unsigned char MessageID; + +// Define __GET_TIME_64BIT if you want to use large types for GetTime (takes more bandwidth when you transmit time though!) +// You would want to do this if your system is going to run long enough to overflow the millisecond counter (over a month) +#ifdef __GET_TIME_64BIT +typedef long long RakNetTime; +typedef long long RakNetTimeNS; +#else +typedef unsigned int RakNetTime; +typedef long long RakNetTimeNS; +#endif + +/// Describes the local socket to use for RakPeer::Startup +struct RAK_DLL_EXPORT SocketDescriptor +{ + SocketDescriptor(); + SocketDescriptor(unsigned short _port, const char *_hostAddress); + + /// The local port to bind to. Pass 0 to have the OS autoassign a port. + unsigned short port; + + /// The local network card address to bind to, such as "127.0.0.1". Pass an empty string to use INADDR_ANY. + char hostAddress[32]; +}; + +/// \brief Unique identifier for a system. +/// Corresponds to a network address +struct RAK_DLL_EXPORT SystemAddress +{ + ///The peer address from inet_addr. + unsigned int binaryAddress; + ///The port number + unsigned short port; + + // Return the systemAddress as a string in the format : + // Note - returns a static string. Not thread-safe or safe for multiple calls per line. + char *ToString(bool writePort=true) const; + + // Sets the binary address part from a string. Doesn't set the port + void SetBinaryAddress(const char *str); + + SystemAddress& operator = ( const SystemAddress& input ) + { + binaryAddress = input.binaryAddress; + port = input.port; + return *this; + } + + bool operator==( const SystemAddress& right ) const; + bool operator!=( const SystemAddress& right ) const; + bool operator > ( const SystemAddress& right ) const; + bool operator < ( const SystemAddress& right ) const; +}; + +struct RAK_DLL_EXPORT NetworkID +{ + // Set this to true to use peer to peer mode for NetworkIDs. + // Obviously the value of this must match on all systems. + // True, and this will write the systemAddress portion with network sends. Takes more bandwidth, but NetworkIDs can be locally generated + // False, and only localSystemAddress is used. + static bool peerToPeerMode; + + // In peer to peer, we use both systemAddress and localSystemAddress + // In client / server, we only use localSystemAddress + SystemAddress systemAddress; + unsigned short localSystemAddress; + + NetworkID& operator = ( const NetworkID& input ); + + static bool IsPeerToPeerMode(void); + static void SetPeerToPeerMode(bool isPeerToPeer); + bool operator==( const NetworkID& right ) const; + bool operator!=( const NetworkID& right ) const; + bool operator > ( const NetworkID& right ) const; + bool operator < ( const NetworkID& right ) const; +}; + +/// Size of SystemAddress data +#define SystemAddress_Size 6 + +/// This represents a user message from another system. +struct Packet +{ + /// Server only - this is the index into the player array that this systemAddress maps to + SystemIndex systemIndex; + + /// The system that send this packet. + SystemAddress systemAddress; + + /// The length of the data in bytes + /// \deprecated You should use bitSize. + unsigned int length; + + /// The length of the data in bits + unsigned int bitSize; + + /// The data from the sender + unsigned char* data; + + /// @internal + /// Indicates whether to delete the data, or to simply delete the packet. + bool deleteData; +}; + +class RakPeerInterface; + +/// All RPC functions have the same parameter list - this structure. +struct RPCParameters +{ + /// The data from the remote system + unsigned char *input; + + /// How many bits long \a input is + unsigned int numberOfBitsOfData; + + /// Which system called this RPC + SystemAddress sender; + + /// Which instance of RakPeer (or a derived RakPeer or RakPeer) got this call + RakPeerInterface *recipient; + + RakNetTime remoteTimestamp; + + /// The name of the function that was called. + char *functionName; + + /// You can return values from RPC calls by writing them to this BitStream. + /// This is only sent back if the RPC call originally passed a BitStream to receive the reply. + /// If you do so and your send is reliable, it will block until you get a reply or you get disconnected from the system you are sending to, whichever is first. + /// If your send is not reliable, it will block for triple the ping time, or until you are disconnected, or you get a reply, whichever is first. + RakNet::BitStream *replyToSender; +}; + +/// Index of an unassigned player +const SystemIndex UNASSIGNED_PLAYER_INDEX = 65535; + +/// Index of an invalid SystemAddress +const SystemAddress UNASSIGNED_SYSTEM_ADDRESS = +{ + 0xFFFFFFFF, 0xFFFF +}; + +/// Unassigned object ID +const NetworkID UNASSIGNED_NETWORK_ID = +{ + {0xFFFFFFFF, 0xFFFF}, 65535 +}; + +const int PING_TIMES_ARRAY_SIZE = 5; + +/// \brief RPC Function Implementation +/// +/// The Remote Procedure Call Subsystem provide the RPC paradigm to +/// RakNet user. It consists in providing remote function call over the +/// network. A call to a remote function require you to prepare the +/// data for each parameter (using BitStream) for example. +/// +/// Use the following C function prototype for your callbacks +/// @code +/// void functionName(RPCParameters *rpcParms); +/// @endcode +/// If you pass input data, you can parse the input data in two ways. +/// 1. +/// Cast input to a struct (such as if you sent a struct) +/// i.e. MyStruct *s = (MyStruct*) input; +/// Make sure that the sizeof(MyStruct) is equal to the number of bytes passed! +/// 2. +/// Create a BitStream instance with input as data and the number of bytes +/// i.e. BitStream myBitStream(input, (numberOfBitsOfData-1)/8+1) +/// (numberOfBitsOfData-1)/8+1 is how convert from bits to bytes +/// Full example: +/// @code +/// void MyFunc(RPCParameters *rpcParms) {} +/// RakPeer *rakClient; +/// REGISTER_AS_REMOTE_PROCEDURE_CALL(rakClient, MyFunc); +/// This would allow MyFunc to be called from the server using (for example) +/// rakServer->RPC("MyFunc", 0, clientID, false); +/// @endcode + + +/// \def REGISTER_STATIC_RPC +/// \ingroup RAKNET_RPC +/// Register a C function as a Remote procedure. +/// \param[in] networkObject Your instance of RakPeer, RakPeer, or RakPeer +/// \param[in] functionName The name of the C function to call +/// \attention 12/01/05 REGISTER_AS_REMOTE_PROCEDURE_CALL renamed to REGISTER_STATIC_RPC. Delete the old name sometime in the future +//#pragma deprecated(REGISTER_AS_REMOTE_PROCEDURE_CALL) +//#define REGISTER_AS_REMOTE_PROCEDURE_CALL(networkObject, functionName) REGISTER_STATIC_RPC(networkObject, functionName) +#define REGISTER_STATIC_RPC(networkObject, functionName) (networkObject)->RegisterAsRemoteProcedureCall((#functionName),(functionName)) + +/// \def CLASS_MEMBER_ID +/// \ingroup RAKNET_RPC +/// \brief Concatenate two strings + +/// \def REGISTER_CLASS_MEMBER_RPC +/// \ingroup RAKNET_RPC +/// \brief Register a member function of an instantiated object as a Remote procedure call. +/// RPC member Functions MUST be marked __cdecl! +/// \sa ObjectMemberRPC.cpp +/// \b CLASS_MEMBER_ID is a utility macro to generate a unique signature for a class and function pair and can be used for the Raknet functions RegisterClassMemberRPC(...) and RPC(...) +/// \b REGISTER_CLASS_MEMBER_RPC is a utility macro to more easily call RegisterClassMemberRPC +/// \param[in] networkObject Your instance of RakPeer, RakPeer, or RakPeer +/// \param[in] className The class containing the function +/// \param[in] functionName The name of the function (not in quotes, just the name) +#define CLASS_MEMBER_ID(className, functionName) #className "_" #functionName +#define REGISTER_CLASS_MEMBER_RPC(networkObject, className, functionName) {union {void (__cdecl className::*cFunc)( RPCParameters *rpcParms ); void* voidFunc;}; cFunc=&className::functionName; networkObject->RegisterClassMemberRPC(CLASS_MEMBER_ID(className, functionName),voidFunc);} + +/// \def UNREGISTER_AS_REMOTE_PROCEDURE_CALL +/// \depreciated +/// \brief Only calls UNREGISTER_STATIC_RPC + +/// \def UNREGISTER_STATIC_RPC +/// \ingroup RAKNET_RPC +/// Unregisters a remote procedure call +/// RPC member Functions MUST be marked __cdecl! See the ObjectMemberRPC example. +/// \param[in] networkObject The object that manages the function +/// \param[in] functionName The function name +// 12/01/05 UNREGISTER_AS_REMOTE_PROCEDURE_CALL Renamed to UNREGISTER_STATIC_RPC. Delete the old name sometime in the future +//#pragma deprecated(UNREGISTER_AS_REMOTE_PROCEDURE_CALL) +//#define UNREGISTER_AS_REMOTE_PROCEDURE_CALL(networkObject,functionName) UNREGISTER_STATIC_RPC(networkObject,functionName) +#define UNREGISTER_STATIC_RPC(networkObject,functionName) (networkObject)->UnregisterAsRemoteProcedureCall((#functionName)) + +/// \def UNREGISTER_CLASS_INST_RPC +/// \ingroup RAKNET_RPC +/// \brief Unregisters a member function of an instantiated object as a Remote procedure call. +/// \param[in] networkObject The object that manages the function +/// \param[in] className The className that was originally passed to REGISTER_AS_REMOTE_PROCEDURE_CALL +/// \param[in] functionName The function name +#define UNREGISTER_CLASS_MEMBER_RPC(networkObject, className, functionName) (networkObject)->UnregisterAsRemoteProcedureCall((#className "_" #functionName)) + +#endif + diff --git a/Multiplayer/raknet/RakNetworkFactory.h b/Multiplayer/raknet/RakNetworkFactory.h new file mode 100644 index 00000000..5858ec81 --- /dev/null +++ b/Multiplayer/raknet/RakNetworkFactory.h @@ -0,0 +1,71 @@ +/// \file +/// \brief Factory class for RakNet objects +/// +/// This file is part of RakNet Copyright 2003 Kevin Jenkins. +/// +/// Usage of RakNet is subject to the appropriate license agreement. +/// Creative Commons Licensees are subject to the +/// license found at +/// http://creativecommons.org/licenses/by-nc/2.5/ +/// Single application licensees are subject to the license found at +/// http://www.rakkarsoft.com/SingleApplicationLicense.html +/// Custom license users are subject to the terms therein. +/// GPL license users are subject to the GNU General Public +/// License as published by the Free +/// Software Foundation; either version 2 of the License, or (at your +/// option) any later version. + +#ifndef __RAK_NETWORK_FACTORY_H +#define __RAK_NETWORK_FACTORY_H + +#include "Export.h" + +class RakPeerInterface; +class ConsoleServer; +class ReplicaManager; +class LogCommandParser; +class PacketLogger; +class RakNetCommandParser; +class RakNetTransport; +class TelnetTransport; +class PacketConsoleLogger; +class PacketFileLogger; +class Router; +class ConnectionGraph; + +class RAK_DLL_EXPORT RakNetworkFactory +{ +public: + // For DLL's, these are user classes that you might want to new and delete. + // You can't instantiate exported classes directly in your program. The instantiation + // has to take place inside the DLL. So these functions will do the news and deletes for you. + // if you're using the source or static library you don't need these functions, but can use them if you want. + static RakPeerInterface* GetRakPeerInterface( void ); + static ConsoleServer* GetConsoleServer( void ); + static ReplicaManager* GetReplicaManager( void ); + static LogCommandParser* GetLogCommandParser( void ); + static PacketLogger* GetPacketLogger( void ); + static RakNetCommandParser* GetRakNetCommandParser( void ); + static RakNetTransport* GetRakNetTransport( void ); + static TelnetTransport* GetTelnetTransport( void ); + static PacketConsoleLogger* GetPacketConsoleLogger( void ); + static PacketFileLogger* GetPacketFileLogger( void ); + static Router* GetRouter( void ); + static ConnectionGraph* GetConnectionGraph( void ); + + // To delete the object returned by the Get functions above. + static void DestroyRakPeerInterface( RakPeerInterface* i ); + static void DestroyConsoleServer( ConsoleServer* i); + static void DestroyReplicaManager( ReplicaManager* i); + static void DestroyLogCommandParser( LogCommandParser* i); + static void DestroyPacketLogger( PacketLogger* i); + static void DestroyRakNetCommandParser( RakNetCommandParser* i ); + static void DestroyRakNetTransport( RakNetTransport* i ); + static void DestroyTelnetTransport( TelnetTransport* i ); + static void DestroyPacketConsoleLogger( PacketConsoleLogger* i ); + static void DestroyPacketFileLogger( PacketFileLogger* i ); + static void DestroyRouter( Router* i ); + static void DestroyConnectionGraph( ConnectionGraph* i ); +}; + +#endif diff --git a/Multiplayer/raknet/RakPeerInterface.h b/Multiplayer/raknet/RakPeerInterface.h new file mode 100644 index 00000000..523dcc4f --- /dev/null +++ b/Multiplayer/raknet/RakPeerInterface.h @@ -0,0 +1,488 @@ +/// \file +/// \brief An interface for RakPeer. Simply contains all user functions as pure virtuals. +/// +/// This file is part of RakNet Copyright 2003 Kevin Jenkins. +/// +/// Usage of RakNet is subject to the appropriate license agreement. +/// Creative Commons Licensees are subject to the +/// license found at +/// http://creativecommons.org/licenses/by-nc/2.5/ +/// Single application licensees are subject to the license found at +/// http://www.rakkarsoft.com/SingleApplicationLicense.html +/// Custom license users are subject to the terms therein. +/// GPL license users are subject to the GNU General Public +/// License as published by the Free +/// Software Foundation; either version 2 of the License, or (at your +/// option) any later version. + +#ifndef __RAK_PEER_INTERFACE_H +#define __RAK_PEER_INTERFACE_H + +#include "PacketPriority.h" +#include "RakNetTypes.h" +#include "Export.h" + +// Forward declarations +namespace RakNet +{ + class BitStream; +} +class PluginInterface; +struct RPCMap; +struct RakNetStatistics; +class RouterInterface; +class NetworkIDManager; + +/// The primary interface for RakNet, RakPeer contains all major functions for the library. +/// See the individual functions for what the class can do. +/// \brief The main interface for network communications +class RAK_DLL_EXPORT RakPeerInterface +{ +public: + ///Destructor + virtual ~RakPeerInterface() {} + + // --------------------------------------------------------------------------------------------Major Low Level Functions - Functions needed by most users-------------------------------------------------------------------------------------------- + /// \brief Starts the network threads, opens the listen port. + /// You must call this before calling Connect(). + /// Multiple calls while already active are ignored. To call this function again with different settings, you must first call Shutdown(). + /// \note Call SetMaximumIncomingConnections if you want to accept incoming connections + /// \param[in] maxConnections The maximum number of connections between this instance of RakPeer and another instance of RakPeer. Required so the network can preallocate and for thread safety. A pure client would set this to 1. A pure server would set it to the number of allowed clients.- A hybrid would set it to the sum of both types of connections + /// \param[in] localPort The port to listen for connections on. + /// \param[in] _threadSleepTimer How many ms to Sleep each internal update cycle (30 to give the game priority, 0 for regular (recommended) + /// \param[in] socketDescriptors An array of SocketDescriptor structures to force RakNet to listen on a particular IP address or port (or both). Each SocketDescriptor will represent one unique socket. Do not pass redundant structures. To listen on a specific port, you can pass SocketDescriptor(myPort,0); such as for a server. For a client, it is usually OK to just pass SocketDescriptor(); + /// \param[in] socketDescriptorCount The size of the \a socketDescriptors array. Pass 1 if you are not sure what to pass. + /// \return False on failure (can't create socket or thread), true on success. + virtual bool Startup( unsigned short maxConnections, int _threadSleepTimer, SocketDescriptor *socketDescriptors, unsigned socketDescriptorCount )=0; + + /// Secures connections though a combination of SHA1, AES128, SYN Cookies, and RSA to prevent connection spoofing, replay attacks, data eavesdropping, packet tampering, and MitM attacks. + /// There is a significant amount of processing and a slight amount of bandwidth overhead for this feature. + /// If you accept connections, you must call this or else secure connections will not be enabled for incoming connections. + /// If you are connecting to another system, you can call this with values for the (e and p,q) public keys before connecting to prevent MitM + /// \pre Must be called while offline + /// \param[in] pubKeyE A pointer to the public keys from the RSACrypt class. + /// \param[in] pubKeyN A pointer to the public keys from the RSACrypt class. + /// \param[in] privKeyP Public key generated from the RSACrypt class. + /// \param[in] privKeyQ Public key generated from the RSACrypt class. If the private keys are 0, then a new key will be generated when this function is called@see the Encryption sample + virtual void InitializeSecurity(const char *pubKeyE, const char *pubKeyN, const char *privKeyP, const char *privKeyQ )=0; + + /// Disables all security. + /// \note Must be called while offline + virtual void DisableSecurity( void )=0; + + /// Sets how many incoming connections are allowed. If this is less than the number of players currently connected, + /// no more players will be allowed to connect. If this is greater than the maximum number of peers allowed, + /// it will be reduced to the maximum number of peers allowed. Defaults to 0. + /// \param[in] numberAllowed Maximum number of incoming connections allowed. + virtual void SetMaximumIncomingConnections( unsigned short numberAllowed )=0; + + /// Returns the value passed to SetMaximumIncomingConnections() + /// \return the maximum number of incoming connections, which is always <= maxConnections + virtual unsigned short GetMaximumIncomingConnections( void ) const=0; + + /// Returns how many open connections there are at this time + /// \return the number of open connections + virtual unsigned short NumberOfConnections(void) const=0; + + /// Sets the password incoming connections must match in the call to Connect (defaults to none). Pass 0 to passwordData to specify no password + /// This is a way to set a low level password for all incoming connections. To selectively reject connections, implement your own scheme using CloseConnection() to remove unwanted connections + /// \param[in] passwordData A data block that incoming connections must match. This can be just a password, or can be a stream of data. Specify 0 for no password data + /// \param[in] passwordDataLength The length in bytes of passwordData + virtual void SetIncomingPassword( const char* passwordData, int passwordDataLength )=0; + + /// Gets the password passed to SetIncomingPassword + /// \param[out] passwordData Should point to a block large enough to hold the password data you passed to SetIncomingPassword() + /// \param[in,out] passwordDataLength Maximum size of the array passwordData. Modified to hold the number of bytes actually written + virtual void GetIncomingPassword( char* passwordData, int *passwordDataLength )=0; + + /// \brief Connect to the specified host (ip or domain name) and server port. + /// Calling Connect and not calling SetMaximumIncomingConnections acts as a dedicated client. + /// Calling both acts as a true peer. This is a non-blocking connection. + /// You know the connection is successful when IsConnected() returns true or Receive() gets a message with the type identifier ID_CONNECTION_ACCEPTED. + /// If the connection is not successful, such as a rejected connection or no response then neither of these things will happen. + /// \pre Requires that you first call Initialize + /// \param[in] host Either a dotted IP address or a domain name + /// \param[in] remotePort Which port to connect to on the remote machine. + /// \param[in] passwordData A data block that must match the data block on the server passed to SetIncomingPassword. This can be a string or can be a stream of data. Use 0 for no password. + /// \param[in] passwordDataLength The length in bytes of passwordData + /// \param[in] connectionSocketIndex Index into the array of socket descriptors passed to socketDescriptors in RakPeer::Startup() to send on. + /// \return True on successful initiation. False on incorrect parameters, internal error, or too many existing peers. Returning true does not mean you connected! + virtual bool Connect( const char* host, unsigned short remotePort, const char *passwordData, int passwordDataLength, unsigned connectionSocketIndex=0 )=0; + + /// \brief Connect to the specified network ID (Platform specific console function) + /// Does built-in NAt traversal + /// \param[in] passwordData A data block that must match the data block on the server passed to SetIncomingPassword. This can be a string or can be a stream of data. Use 0 for no password. + /// \param[in] passwordDataLength The length in bytes of passwordData + virtual bool Console2Connect( void *networkServiceId, const char *passwordData, int passwordDataLength )=0; + + /// \brief Stops the network threads and closes all connections. + /// \param[in] blockDuration How long, in milliseconds, you should wait for all remaining messages to go out, including ID_DISCONNECTION_NOTIFICATION. If 0, it doesn't wait at all. + /// \param[in] orderingChannel If blockDuration > 0, ID_DISCONNECTION_NOTIFICATION will be sent on this channel + /// If you set it to 0 then the disconnection notification won't be sent + virtual void Shutdown( unsigned int blockDuration, unsigned char orderingChannel=0 )=0; + + /// Returns if the network thread is running + /// \return true if the network thread is running, false otherwise + virtual bool IsActive( void ) const=0; + + /// Fills the array remoteSystems with the SystemAddress of all the systems we are connected to + /// \param[out] remoteSystems An array of SystemAddress structures to be filled with the SystemAddresss of the systems we are connected to. Pass 0 to remoteSystems to only get the number of systems we are connected to + /// \param[in, out] numberOfSystems As input, the size of remoteSystems array. As output, the number of elements put into the array + virtual bool GetConnectionList( SystemAddress *remoteSystems, unsigned short *numberOfSystems ) const=0; + + /// Sends a block of data to the specified system that you are connected to. + /// This function only works while the connected + /// \param[in] data The block of data to send + /// \param[in] length The size in bytes of the data to send + /// \param[in] priority What priority level to send on. See PacketPriority.h + /// \param[in] reliability How reliability to send this data. See PacketPriority.h + /// \param[in] orderingChannel When using ordered or sequenced messages, what channel to order these on. Messages are only ordered relative to other messages on the same stream + /// \param[in] systemAddress Who to send this packet to, or in the case of broadcasting who not to send it to. Use UNASSIGNED_SYSTEM_ADDRESS to specify none + /// \param[in] broadcast True to send this packet to all connected systems. If true, then systemAddress specifies who not to send the packet to. + /// \return False if we are not connected to the specified recipient. True otherwise + virtual bool Send( const char *data, const int length, PacketPriority priority, PacketReliability reliability, char orderingChannel, SystemAddress systemAddress, bool broadcast )=0; + + /// Sends a block of data to the specified system that you are connected to. Same as the above version, but takes a BitStream as input. + /// \param[in] bitStream The bitstream to send + /// \param[in] priority What priority level to send on. See PacketPriority.h + /// \param[in] reliability How reliability to send this data. See PacketPriority.h + /// \param[in] orderingChannel When using ordered or sequenced messages, what channel to order these on. Messages are only ordered relative to other messages on the same stream + /// \param[in] systemAddress Who to send this packet to, or in the case of broadcasting who not to send it to. Use UNASSIGNED_SYSTEM_ADDRESS to specify none + /// \param[in] broadcast True to send this packet to all connected systems. If true, then systemAddress specifies who not to send the packet to. + /// \return False if we are not connected to the specified recipient. True otherwise + virtual bool Send( const RakNet::BitStream * bitStream, PacketPriority priority, PacketReliability reliability, char orderingChannel, SystemAddress systemAddress, bool broadcast )=0; + + /// Gets a message from the incoming message queue. + /// Use DeallocatePacket() to deallocate the message after you are done with it. + /// User-thread functions, such as RPC calls and the plugin function PluginInterface::Update occur here. + /// \return 0 if no packets are waiting to be handled, otherwise a pointer to a packet. + /// sa RakNetTypes.h contains struct Packet + virtual Packet* Receive( void )=0; + + /// Call this to deallocate a message returned by Receive() when you are done handling it. + /// \param[in] packet The message to deallocate. + virtual void DeallocatePacket( Packet *packet )=0; + + /// Return the total number of connections we are allowed + // TODO - rename for RakNet 3.0 + virtual unsigned short GetMaximumNumberOfPeers( void ) const=0; + + // --------------------------------------------------------------------------------------------Remote Procedure Call Functions - Functions to initialize and perform RPC-------------------------------------------------------------------------------------------- + /// \ingroup RAKNET_RPC + /// Register a C or static member function as available for calling as a remote procedure call + /// \param[in] uniqueID A null-terminated unique string to identify this procedure. See RegisterClassMemberRPC() for class member functions. + /// \param[in] functionPointer(...) The name of the function to be used as a function pointer. This can be called whether active or not, and registered functions stay registered unless unregistered + virtual void RegisterAsRemoteProcedureCall( const char* uniqueID, void ( *functionPointer ) ( RPCParameters *rpcParms ) )=0; + + /// \ingroup RAKNET_RPC + /// Register a C++ member function as available for calling as a remote procedure call. + /// \param[in] uniqueID A null terminated string to identify this procedure. Recommended you use the macro REGISTER_CLASS_MEMBER_RPC to create the string. Use RegisterAsRemoteProcedureCall() for static functions. + /// \param[in] functionPointer The name of the function to be used as a function pointer. This can be called whether active or not, and registered functions stay registered unless unregistered with UnregisterAsRemoteProcedureCall + /// \sa The sample ObjectMemberRPC.cpp + virtual void RegisterClassMemberRPC( const char* uniqueID, void *functionPointer )=0; + + /// \ingroup RAKNET_RPC + /// Unregisters a C function as available for calling as a remote procedure call that was formerly registered with RegisterAsRemoteProcedureCall. Only call offline. + /// \param[in] uniqueID A string of only letters to identify this procedure. Recommended you use the macro CLASS_MEMBER_ID for class member functions. + virtual void UnregisterAsRemoteProcedureCall( const char* uniqueID )=0; + + /// \ingroup RAKNET_RPC + /// Used by Object member RPC to lookup objects given that object's ID + /// Also used by the ReplicaManager plugin + /// \param[in] An instance of NetworkIDManager to use for the lookup. + virtual void SetNetworkIDManager( NetworkIDManager *manager )=0; + + /// \return Returns the value passed to SetNetworkIDManager or 0 if never called. + virtual NetworkIDManager *GetNetworkIDManager(void) const=0; + + /// \ingroup RAKNET_RPC + /// Calls a C function on the remote system that was already registered using RegisterAsRemoteProcedureCall(). + /// \param[in] uniqueID A NULL terminated string identifying the function to call. Recommended you use the macro CLASS_MEMBER_ID for class member functions. + /// \param[in] data The data to send + /// \param[in] bitLength The number of bits of \a data + /// \param[in] priority What priority level to send on. See PacketPriority.h. + /// \param[in] reliability How reliability to send this data. See PacketPriority.h. + /// \param[in] orderingChannel When using ordered or sequenced message, what channel to order these on. + /// \param[in] systemAddress Who to send this message to, or in the case of broadcasting who not to send it to. Use UNASSIGNED_SYSTEM_ADDRESS to specify none + /// \param[in] broadcast True to send this packet to all connected systems. If true, then systemAddress specifies who not to send the packet to. + /// \param[in] includedTimestamp Pass a timestamp if you wish, to be adjusted in the usual fashion as per ID_TIMESTAMP. Pass 0 to not include a timestamp. + /// \param[in] networkID For static functions, pass UNASSIGNED_NETWORK_ID. For member functions, you must derive from NetworkIDObject and pass the value returned by NetworkIDObject::GetNetworkID for that object. + /// \param[in] replyFromTarget If 0, this function is non-blocking. Otherwise it will block while waiting for a reply from the target procedure, which should be remotely written to RPCParameters::replyToSender and copied to replyFromTarget. The block will return early on disconnect or if the sent packet is unreliable and more than 3X the ping has elapsed. + /// \return True on a successful packet send (this does not indicate the recipient performed the call), false on failure + virtual bool RPC( const char* uniqueID, const char *data, unsigned int bitLength, PacketPriority priority, PacketReliability reliability, char orderingChannel, SystemAddress systemAddress, bool broadcast, RakNetTime *includedTimestamp, NetworkID networkID, RakNet::BitStream *replyFromTarget )=0; + + /// \ingroup RAKNET_RPC + /// Calls a C function on the remote system that was already registered using RegisterAsRemoteProcedureCall. + /// If you want that function to return data you should call RPC from that system in the same wayReturns true on a successful packet + /// send (this does not indicate the recipient performed the call), false on failure + /// \param[in] uniqueID A NULL terminated string identifying the function to call. Recommended you use the macro CLASS_MEMBER_ID for class member functions. + /// \param[in] data The data to send + /// \param[in] bitLength The number of bits of \a data + /// \param[in] priority What priority level to send on. See PacketPriority.h. + /// \param[in] reliability How reliability to send this data. See PacketPriority.h. + /// \param[in] orderingChannel When using ordered or sequenced message, what channel to order these on. + /// \param[in] systemAddress Who to send this message to, or in the case of broadcasting who not to send it to. Use UNASSIGNED_SYSTEM_ADDRESS to specify none + /// \param[in] broadcast True to send this packet to all connected systems. If true, then systemAddress specifies who not to send the packet to. + /// \param[in] includedTimestamp Pass a timestamp if you wish, to be adjusted in the usual fashion as per ID_TIMESTAMP. Pass 0 to not include a timestamp. + /// \param[in] networkID For static functions, pass UNASSIGNED_NETWORK_ID. For member functions, you must derive from NetworkIDObject and pass the value returned by NetworkIDObject::GetNetworkID for that object. + /// \param[in] replyFromTarget If 0, this function is non-blocking. Otherwise it will block while waiting for a reply from the target procedure, which should be remotely written to RPCParameters::replyToSender and copied to replyFromTarget. The block will return early on disconnect or if the sent packet is unreliable and more than 3X the ping has elapsed. + /// \return True on a successful packet send (this does not indicate the recipient performed the call), false on failure + virtual bool RPC( const char* uniqueID, const RakNet::BitStream *bitStream, PacketPriority priority, PacketReliability reliability, char orderingChannel, SystemAddress systemAddress, bool broadcast, RakNetTime *includedTimestamp, NetworkID networkID, RakNet::BitStream *replyFromTarget )=0; + + // -------------------------------------------------------------------------------------------- Connection Management Functions-------------------------------------------------------------------------------------------- + /// Close the connection to another host (if we initiated the connection it will disconnect, if they did it will kick them out). + /// \param[in] target Which system to close the connection to. + /// \param[in] sendDisconnectionNotification True to send ID_DISCONNECTION_NOTIFICATION to the recipient. False to close it silently. + /// \param[in] channel Which ordering channel to send the disconnection notification on, if any + virtual void CloseConnection( const SystemAddress target, bool sendDisconnectionNotification, unsigned char orderingChannel=0 )=0; + + /// Returns if a particular systemAddress is connected to us + /// \param[in] systemAddress The SystemAddress we are referring to + /// \return True if this system is connected and active, false otherwise. + virtual bool IsConnected(const SystemAddress systemAddress)=0; + + /// Given a systemAddress, returns an index from 0 to the maximum number of players allowed - 1. + /// \param[in] systemAddress The SystemAddress we are referring to + /// \return The index of this SystemAddress or -1 on system not found. + virtual int GetIndexFromSystemAddress( const SystemAddress systemAddress )=0; + + /// This function is only useful for looping through all systems + /// Given an index, will return a SystemAddress. + /// \param[in] index Index should range between 0 and the maximum number of players allowed - 1. + /// \return The SystemAddress + virtual SystemAddress GetSystemAddressFromIndex( int index )=0; + + /// Bans an IP from connecting. Banned IPs persist between connections but are not saved on shutdown nor loaded on startup. + /// param[in] IP Dotted IP address. Can use * as a wildcard, such as 128.0.0.* will ban all IP addresses starting with 128.0.0 + /// \param[in] milliseconds how many ms for a temporary ban. Use 0 for a permanent ban + virtual void AddToBanList( const char *IP, RakNetTime milliseconds=0 )=0; + + /// Allows a previously banned IP to connect. + /// param[in] Dotted IP address. Can use * as a wildcard, such as 128.0.0.* will banAll IP addresses starting with 128.0.0 + virtual void RemoveFromBanList( const char *IP )=0; + + /// Allows all previously banned IPs to connect. + virtual void ClearBanList( void )=0; + + /// Returns true or false indicating if a particular IP is banned. + /// \param[in] IP - Dotted IP address. + /// \return true if IP matches any IPs in the ban list, accounting for any wildcards. False otherwise. + virtual bool IsBanned( const char *IP )=0; + + // --------------------------------------------------------------------------------------------Pinging Functions - Functions dealing with the automatic ping mechanism-------------------------------------------------------------------------------------------- + /// Send a ping to the specified connected system. + /// \pre The sender and recipient must already be started via a successful call to Startup() + /// \param[in] target Which system to ping + virtual void Ping( const SystemAddress target )=0; + + /// Send a ping to the specified unconnected system. The remote system, if it is Initialized, will respond with ID_PONG followed by sizeof(RakNetTime) containing the system time the ping was sent.(Default is 4 bytes - See __GET_TIME_64BIT in RakNetTypes.h + /// \param[in] host Either a dotted IP address or a domain name. Can be 255.255.255.255 for LAN broadcast. + /// \param[in] remotePort Which port to connect to on the remote machine. + /// \param[in] onlyReplyOnAcceptingConnections Only request a reply if the remote system is accepting connections + /// \param[in] connectionSocketIndex Index into the array of socket descriptors passed to socketDescriptors in RakPeer::Startup() to send on. + virtual void Ping( const char* host, unsigned short remotePort, bool onlyReplyOnAcceptingConnections, unsigned connectionSocketIndex=0 )=0; + + /// Returns the average of all ping times read for the specific system or -1 if none read yet + /// \param[in] systemAddress Which system we are referring to + /// \return The ping time for this system, or -1 + virtual int GetAveragePing( const SystemAddress systemAddress )=0; + + /// Returns the last ping time read for the specific system or -1 if none read yet + /// \param[in] systemAddress Which system we are referring to + /// \return The last ping time for this system, or -1 + virtual int GetLastPing( const SystemAddress systemAddress ) const=0; + + /// Returns the lowest ping time read or -1 if none read yet + /// \param[in] systemAddress Which system we are referring to + /// \return The lowest ping time for this system, or -1 + virtual int GetLowestPing( const SystemAddress systemAddress ) const=0; + + /// Ping the remote systems every so often, or not. This is off by default. Can be called anytime. + /// \param[in] doPing True to start occasional pings. False to stop them. + virtual void SetOccasionalPing( bool doPing )=0; + + // --------------------------------------------------------------------------------------------Static Data Functions - Functions dealing with API defined synchronized memory-------------------------------------------------------------------------------------------- + /// Sets the data to send along with a LAN server discovery or offline ping reply. + /// \a length should be under 400 bytes, as a security measure against flood attacks + /// \param[in] data a block of data to store, or 0 for none + /// \param[in] length The length of data in bytes, or 0 for none + /// \sa Ping.cpp + virtual void SetOfflinePingResponse( const char *data, const unsigned int length )=0; + + //--------------------------------------------------------------------------------------------Network Functions - Functions dealing with the network in general-------------------------------------------------------------------------------------------- + /// Return the unique address identifier that represents you on the the network and is based on your local IP / port. + /// \return the identifier of your system internally, which may not be how other systems see if you if you are behind a NAT or proxy + virtual SystemAddress GetInternalID( const SystemAddress systemAddress=UNASSIGNED_SYSTEM_ADDRESS ) const=0; + + /// Return the unique address identifier that represents you on the the network and is based on your externalIP / port + /// (the IP / port the specified player uses to communicate with you) + /// \param[in] target Which remote system you are referring to for your external ID. Usually the same for all systems, unless you have two or more network cards. + virtual SystemAddress GetExternalID( const SystemAddress target ) const=0; + + /// Set the time, in MS, to use before considering ourselves disconnected after not being able to deliver a reliable message. + /// Default time is 10,000 or 10 seconds in release and 30,000 or 30 seconds in debug. + /// \param[in] timeMS Time, in MS + /// \param[in] target Which system to do this for + virtual void SetTimeoutTime( RakNetTime timeMS, const SystemAddress target )=0; + + /// Set the MTU per datagram. It's important to set this correctly - otherwise packets will be needlessly split, decreasing performance and throughput. + /// Maximum allowed size is MAXIMUM_MTU_SIZE. + /// Too high of a value will cause packets not to arrive at worst and be fragmented at best. + /// Too low of a value will split packets unnecessarily. + /// Recommended size is 1500 + /// sa MTUSize.h + /// \param[in] size The MTU size + /// \pre Can only be called when not connected. + /// \return false on failure (we are connected), else true + virtual bool SetMTUSize( int size )=0; + + /// Returns the current MTU size + /// \param[in] target Which system to get this for. UNASSIGNED_SYSTEM_ADDRESS to get the default + /// \return The current MTU size + virtual int GetMTUSize( const SystemAddress target ) const=0; + + /// Returns the number of IP addresses this system has internally. Get the actual addresses from GetLocalIP() + virtual unsigned GetNumberOfAddresses( void )=0; + + /// Returns an IP address at index 0 to GetNumberOfAddresses-1 + virtual const char* GetLocalIP( unsigned int index )=0; + + /// Allow or disallow connection responses from any IP. Normally this should be false, but may be necessary + /// when connecting to servers with multiple IP addresses. + /// \param[in] allow - True to allow this behavior, false to not allow. Defaults to false. Value persists between connections + virtual void AllowConnectionResponseIPMigration( bool allow )=0; + + /// Sends a one byte message ID_ADVERTISE_SYSTEM to the remote unconnected system. + /// This will tell the remote system our external IP outside the LAN along with some user data. + /// \pre The sender and recipient must already be started via a successful call to Initialize + /// \param[in] host Either a dotted IP address or a domain name + /// \param[in] remotePort Which port to connect to on the remote machine. + /// \param[in] data Optional data to append to the packet. + /// \param[in] dataLength length of data in bytes. Use 0 if no data. + /// \param[in] connectionSocketIndex Index into the array of socket descriptors passed to socketDescriptors in RakPeer::Startup() to send on. + virtual void AdvertiseSystem( const char *host, unsigned short remotePort, const char *data, int dataLength, unsigned connectionSocketIndex=0 )=0; + + /// Controls how often to return ID_DOWNLOAD_PROGRESS for large message downloads. + /// ID_DOWNLOAD_PROGRESS is returned to indicate a new partial message chunk, roughly the MTU size, has arrived + /// As it can be slow or cumbersome to get this notification for every chunk, you can set the interval at which it is returned. + /// Defaults to 0 (never return this notification) + /// \param[in] interval How many messages to use as an interval + virtual void SetSplitMessageProgressInterval(int interval)=0; + + /// Set how long to wait before giving up on sending an unreliable message + /// Useful if the network is clogged up. + /// Set to 0 or less to never timeout. Defaults to 0. + /// \param[in] timeoutMS How many ms to wait before simply not sending an unreliable message. + virtual void SetUnreliableTimeout(RakNetTime timeoutMS)=0; + + /// Send a message to host, with the IP socket option TTL set to 1 + /// This message will not reach the host, but will open the router. + /// Used for NAT-Punchthrough + virtual void SendTTL1( const char* host, unsigned short remotePort, unsigned connectionSocketIndex=0 )=0; + + // --------------------------------------------------------------------------------------------Compression Functions - Functions related to the compression layer-------------------------------------------------------------------------------------------- + /// Enables or disables frequency table tracking. This is required to get a frequency table, which is used in GenerateCompressionLayer() + /// This value persists between connect calls and defaults to false (no frequency tracking) + /// \pre You can call this at any time - however you SHOULD only call it when disconnected. Otherwise you will only trackpart of the values sent over the network. + /// \param[in] doCompile True to enable tracking + virtual void SetCompileFrequencyTable( bool doCompile )=0; + + /// Returns the frequency of outgoing bytes into output frequency table + /// The purpose is to save to file as either a master frequency table from a sample game session for passing to + /// GenerateCompressionLayer() + /// \pre You should only call this when disconnected. Requires that you first enable data frequency tracking by calling SetCompileFrequencyTable(true) + /// \param[out] outputFrequencyTable The frequency of each corresponding byte + /// \return False (failure) if connected or if frequency table tracking is not enabled. Otherwise true (success) + virtual bool GetOutgoingFrequencyTable( unsigned int outputFrequencyTable[ 256 ] )=0; + + /// This is an optional function to generate the compression layer based on the input frequency table. + /// If you want to use it you should call this twice - once with inputLayer as true and once as false. + /// The frequency table passed here with inputLayer=true should match the frequency table on the recipient with inputLayer=false. + /// Likewise, the frequency table passed here with inputLayer=false should match the frequency table on the recipient with inputLayer=true. + /// Calling this function when there is an existing layer will overwrite the old layer. + /// \pre You should only call this when disconnected + /// \param[in] inputFrequencyTable A frequency table for your data + /// \param[in] inputLayer Is this the input layer? + /// \return false (failure) if connected. Otherwise true (success) + /// \sa Compression.cpp + virtual bool GenerateCompressionLayer( unsigned int inputFrequencyTable[ 256 ], bool inputLayer )=0; + + /// Delete the output or input layer as specified. This is not necessary to call and is only valuable for freeing memory. + /// \pre You should only call this when disconnected + /// \param[in] inputLayer True to mean the inputLayer, false to mean the output layer + /// \return false (failure) if connected. Otherwise true (success) + virtual bool DeleteCompressionLayer( bool inputLayer )=0; + + /// Returns the compression ratio. A low compression ratio is good. Compression is for outgoing data + /// \return The compression ratio + virtual float GetCompressionRatio( void ) const=0; + + ///Returns the decompression ratio. A high decompression ratio is good. Decompression is for incoming data + /// \return The decompression ratio + virtual float GetDecompressionRatio( void ) const=0; + + // -------------------------------------------------------------------------------------------- Plugin Functions-------------------------------------------------------------------------------------------- + /// Attatches a Plugin interface to run code automatically on message receipt in the Receive call + /// \note If plugins have dependencies on each other then the order does matter - for example the router plugin should go first because it might route messages for other plugins + /// \param[in] messageHandler Pointer to a plugin to attach + virtual void AttachPlugin( PluginInterface *plugin )=0; + + /// Detaches a Plugin interface to run code automatically on message receipt + /// \param[in] messageHandler Pointer to a plugin to detach + virtual void DetachPlugin( PluginInterface *messageHandler )=0; + + // --------------------------------------------------------------------------------------------Miscellaneous Functions-------------------------------------------------------------------------------------------- + /// Put a message back at the end of the receive queue in case you don't want to deal with it immediately + /// \param[in] packet The packet you want to push back. + /// \param[in] pushAtHead True to push the packet so that the next receive call returns it. False to push it at the end of the queue (obviously pushing it at the end makes the packets out of order) + virtual void PushBackPacket( Packet *packet, bool pushAtHead )=0; + + /// \Internal + // \param[in] routerInterface The router to use to route messages to systems not directly connected to this system. + virtual void SetRouterInterface( RouterInterface *routerInterface )=0; + + /// \Internal + // \param[in] routerInterface The router to use to route messages to systems not directly connected to this system. + virtual void RemoveRouterInterface( RouterInterface *routerInterface )=0; + + /// \Returns a packet for you to write to if you want to create a Packet for some reason. + /// You can add it to the receive buffer with PushBackPacket + /// \param[in] dataSize How many bytes to allocate for the buffer + /// \return A packet you can write to + virtual Packet* AllocatePacket(unsigned dataSize)=0; + + // --------------------------------------------------------------------------------------------Network Simulator Functions-------------------------------------------------------------------------------------------- + /// Adds simulated ping and packet loss to the outgoing data flow. + /// To simulate bi-directional ping and packet loss, you should call this on both the sender and the recipient, with half the total ping and maxSendBPS value on each. + /// You can exclude network simulator code with the _RELEASE #define to decrease code size + /// \param[in] maxSendBPS Maximum bits per second to send. Packetloss grows linearly. 0 to disable. (CURRENTLY BROKEN - ALWAYS DISABLED) + /// \param[in] minExtraPing The minimum time to delay sends. + virtual void ApplyNetworkSimulator( double maxSendBPS, unsigned short minExtraPing, unsigned short extraPingVariance)=0; + + /// Limits how much outgoing bandwidth can be sent per-connection. + /// This limit does not apply to the sum of all connections! + /// Exceeding the limit queues up outgoing traffic + /// \param[in] maxBitsPerSecond Maximum bits per second to send. Use 0 for unlimited (default). Once set, it takes effect immedately and persists until called again. + virtual void SetPerConnectionOutgoingBandwidthLimit( unsigned maxBitsPerSecond )=0; + + /// Returns if you previously called ApplyNetworkSimulator + /// \return If you previously called ApplyNetworkSimulator + virtual bool IsNetworkSimulatorActive( void )=0; + + // --------------------------------------------------------------------------------------------Statistical Functions - Functions dealing with API performance-------------------------------------------------------------------------------------------- + + /// Returns a structure containing a large set of network statistics for the specified system. + /// You can map this data to a string using the C style StatisticsToString() function + /// \param[in] systemAddress: Which connected system to get statistics for + /// \return 0 on can't find the specified system. A pointer to a set of data otherwise. + /// \sa RakNetStatistics.h + virtual RakNetStatistics * const GetStatistics( const SystemAddress systemAddress )=0; + + // --------------------------------------------------------------------------------------------EVERYTHING AFTER THIS COMMENT IS FOR INTERNAL USE ONLY-------------------------------------------------------------------------------------------- + /// \internal + virtual char *GetRPCString( const char *data, const unsigned int bitSize, const SystemAddress systemAddress)=0; + + +}; + +#endif diff --git a/Multiplayer/raknet/RakSleep.h b/Multiplayer/raknet/RakSleep.h new file mode 100644 index 00000000..81565c23 --- /dev/null +++ b/Multiplayer/raknet/RakSleep.h @@ -0,0 +1,6 @@ +#ifndef __RAK_SLEEP_H +#define __RAK_SLEEP_H + +void RakSleep(unsigned int ms); + +#endif diff --git a/Multiplayer/raknet/raknetlibstatic.idb b/Multiplayer/raknet/raknetlibstatic.idb new file mode 100644 index 00000000..3e6e29d7 Binary files /dev/null and b/Multiplayer/raknet/raknetlibstatic.idb differ diff --git a/Multiplayer/raknet/raknetlibstatic.pdb b/Multiplayer/raknet/raknetlibstatic.pdb new file mode 100644 index 00000000..84b070c0 Binary files /dev/null and b/Multiplayer/raknet/raknetlibstatic.pdb differ diff --git a/Multiplayer/raknet/raknetlibstaticdebug.pdb b/Multiplayer/raknet/raknetlibstaticdebug.pdb new file mode 100644 index 00000000..89141d9d Binary files /dev/null and b/Multiplayer/raknet/raknetlibstaticdebug.pdb differ diff --git a/Multiplayer/server.cpp b/Multiplayer/server.cpp new file mode 100644 index 00000000..c1b4895e --- /dev/null +++ b/Multiplayer/server.cpp @@ -0,0 +1,677 @@ + +#include "MessageIdentifiers.h" +#include "RakNetworkFactory.h" +#include "RakPeerInterface.h" +#include "RakNetStatistics.h" +#include "RakNetTypes.h" + +#include "BitStream.h" +#include "RakSleep.h" +#include +#include +#include +#include +#include +#include + +#include "types.h" +#include "gamesettings.h" + +char kbag[100]; +char net_div[30]; +INT32 gsMAX_MERCS; +bool gsMORALE; +int gsREPORT_NAME; + +#include "text.h" +#include "connect.h" +#include "message.h" +#include "network.h" +#include "overhead.h" + +UINT16 nc; //number of open connection +UINT16 ncr; //number of ready confirmed connections +//something keep record of ready connections .. +int mercs_ready[255]; + +bool gsDis_Bobby; +bool gsDis_Equip; + +int gsSAME_MERC; +float gsDAMAGE_MULTIPLIER; +int gsINTERRUPTS ; +int gsMAX_CLIENTS ; +int gsPLAYER_BSIDE; +int gsTESTING; + +INT32 gssecs_per_tick; +INT32 gsstarting_balance; +float TIME; +int sWEAPON_READIED_BONUS; + +unsigned char SGetPacketIdentifier(Packet *p); +unsigned char SpacketIdentifier; + +RakPeerInterface *server; + +int numreadyteams; +int readyteamreg[10]; + +SystemAddress blank; + +typedef struct +{ + SystemAddress address; + int cl_number; + +}client_data; + +client_data client_d[4]; + +// use UNASSIGNED_SYSTEM_ADDRESS instead of rpcParameters->sender to send it back to yourself (the sender) +// there is very little in here dependant on the game engine and originally started out as an independant dedicated server .exe, and could if go ther again ... hayden. +//********* RPC SECTION ************ + +void sendPATH(RPCParameters *rpcParameters) +{ + server->RPC("recievePATH",(const char*)rpcParameters->input, (*rpcParameters).numberOfBitsOfData, HIGH_PRIORITY, RELIABLE, 0, rpcParameters->sender, true, 0, UNASSIGNED_NETWORK_ID,0); +} + +void sendSTANCE(RPCParameters *rpcParameters) +{ + server->RPC("recieveSTANCE",(const char*)rpcParameters->input, (*rpcParameters).numberOfBitsOfData, HIGH_PRIORITY, RELIABLE, 0, rpcParameters->sender, true, 0, UNASSIGNED_NETWORK_ID,0); +} + +void sendDIR(RPCParameters *rpcParameters) +{ + server->RPC("recieveDIR",(const char*)rpcParameters->input, (*rpcParameters).numberOfBitsOfData, HIGH_PRIORITY, RELIABLE, 0, rpcParameters->sender, true, 0, UNASSIGNED_NETWORK_ID,0); +} + +void sendFIRE(RPCParameters *rpcParameters) +{ + server->RPC("recieveFIRE",(const char*)rpcParameters->input, (*rpcParameters).numberOfBitsOfData, HIGH_PRIORITY, RELIABLE, 0, rpcParameters->sender, true, 0, UNASSIGNED_NETWORK_ID,0); +} + +void sendHIT(RPCParameters *rpcParameters) +{ + server->RPC("recieveHIT",(const char*)rpcParameters->input, (*rpcParameters).numberOfBitsOfData, HIGH_PRIORITY, RELIABLE, 0, rpcParameters->sender, true, 0, UNASSIGNED_NETWORK_ID,0); +} + +void sendHIRE(RPCParameters *rpcParameters) +{ + server->RPC("recieveHIRE",(const char*)rpcParameters->input, (*rpcParameters).numberOfBitsOfData, HIGH_PRIORITY, RELIABLE, 0, rpcParameters->sender, true, 0, UNASSIGNED_NETWORK_ID,0); +} + +void sendguiPOS(RPCParameters *rpcParameters) +{ + server->RPC("recieveguiPOS",(const char*)rpcParameters->input, (*rpcParameters).numberOfBitsOfData, HIGH_PRIORITY, RELIABLE, 0, rpcParameters->sender, true, 0, UNASSIGNED_NETWORK_ID,0); +} + +void sendguiDIR(RPCParameters *rpcParameters) +{ + server->RPC("recieveguiDIR",(const char*)rpcParameters->input, (*rpcParameters).numberOfBitsOfData, HIGH_PRIORITY, RELIABLE, 0, rpcParameters->sender, true, 0, UNASSIGNED_NETWORK_ID,0); +} + +void sendEndTurn(RPCParameters *rpcParameters) +{ + server->RPC("recieveEndTurn",(const char*)rpcParameters->input, (*rpcParameters).numberOfBitsOfData, HIGH_PRIORITY, RELIABLE, 0, rpcParameters->sender, true, 0, UNASSIGNED_NETWORK_ID,0); +} + +void sendAI(RPCParameters *rpcParameters) +{ + server->RPC("recieveAI",(const char*)rpcParameters->input, (*rpcParameters).numberOfBitsOfData, HIGH_PRIORITY, RELIABLE, 0, rpcParameters->sender, true, 0, UNASSIGNED_NETWORK_ID,0); +} + +void sendSTOP(RPCParameters *rpcParameters) +{ + server->RPC("recieveSTOP",(const char*)rpcParameters->input, (*rpcParameters).numberOfBitsOfData, HIGH_PRIORITY, RELIABLE, 0, rpcParameters->sender, true, 0, UNASSIGNED_NETWORK_ID,0); +} +void sendINTERRUPT(RPCParameters *rpcParameters) +{ + server->RPC("recieveINTERRUPT",(const char*)rpcParameters->input, (*rpcParameters).numberOfBitsOfData, HIGH_PRIORITY, RELIABLE, 0, rpcParameters->sender, true, 0, UNASSIGNED_NETWORK_ID,0); +} +void sendREADY(RPCParameters *rpcParameters) +{ + server->RPC("recieveREADY",(const char*)rpcParameters->input, (*rpcParameters).numberOfBitsOfData, HIGH_PRIORITY, RELIABLE, 0, rpcParameters->sender, true, 0, UNASSIGNED_NETWORK_ID,0); +} + +void sendGUI(RPCParameters *rpcParameters) +{ + server->RPC("recieveGUI",(const char*)rpcParameters->input, (*rpcParameters).numberOfBitsOfData, HIGH_PRIORITY, RELIABLE, 0, rpcParameters->sender, true, 0, UNASSIGNED_NETWORK_ID,0); +} + +void sendBULLET(RPCParameters *rpcParameters) +{ + server->RPC("recieveBULLET",(const char*)rpcParameters->input, (*rpcParameters).numberOfBitsOfData, HIGH_PRIORITY, RELIABLE, 0, rpcParameters->sender, true, 0, UNASSIGNED_NETWORK_ID,0); +} + +void sendSTATE(RPCParameters *rpcParameters) +{ + server->RPC("recieveSTATE",(const char*)rpcParameters->input, (*rpcParameters).numberOfBitsOfData, HIGH_PRIORITY, RELIABLE, 0, rpcParameters->sender, true, 0, UNASSIGNED_NETWORK_ID,0); +} +void sendDEATH(RPCParameters *rpcParameters) +{ + server->RPC("recieveDEATH",(const char*)rpcParameters->input, (*rpcParameters).numberOfBitsOfData, HIGH_PRIORITY, RELIABLE, 0, rpcParameters->sender, true, 0, UNASSIGNED_NETWORK_ID,0); +} +void sendhitSTRUCT(RPCParameters *rpcParameters) +{ + server->RPC("recievehitSTRUCT",(const char*)rpcParameters->input, (*rpcParameters).numberOfBitsOfData, HIGH_PRIORITY, RELIABLE, 0, rpcParameters->sender, true, 0, UNASSIGNED_NETWORK_ID,0); +} +void sendhitWINDOW(RPCParameters *rpcParameters) +{ + server->RPC("recievehitWINDOW",(const char*)rpcParameters->input, (*rpcParameters).numberOfBitsOfData, HIGH_PRIORITY, RELIABLE, 0, rpcParameters->sender, true, 0, UNASSIGNED_NETWORK_ID,0); +} +void sendMISS(RPCParameters *rpcParameters) +{ + server->RPC("recieveMISS",(const char*)rpcParameters->input, (*rpcParameters).numberOfBitsOfData, HIGH_PRIORITY, RELIABLE, 0, rpcParameters->sender, true, 0, UNASSIGNED_NETWORK_ID,0); +} +void updatenetworksoldier(RPCParameters *rpcParameters) +{ + server->RPC("UpdateSoldierFromNetwork",(const char*)rpcParameters->input, (*rpcParameters).numberOfBitsOfData, HIGH_PRIORITY, RELIABLE, 0, rpcParameters->sender, true, 0, UNASSIGNED_NETWORK_ID,0); +} + +void Snull_team(RPCParameters *rpcParameters) +{ + server->RPC("null_team",(const char*)rpcParameters->input, (*rpcParameters).numberOfBitsOfData, HIGH_PRIORITY, RELIABLE, 0, UNASSIGNED_SYSTEM_ADDRESS, true, 0, UNASSIGNED_NETWORK_ID,0); +} + +void sendFIREW(RPCParameters *rpcParameters) +{ + server->RPC("recieve_fireweapon",(const char*)rpcParameters->input, (*rpcParameters).numberOfBitsOfData, HIGH_PRIORITY, RELIABLE, 0, rpcParameters->sender, true, 0, UNASSIGNED_NETWORK_ID,0); +} + +void sendDOOR(RPCParameters *rpcParameters) +{ + server->RPC("recieve_door",(const char*)rpcParameters->input, (*rpcParameters).numberOfBitsOfData, HIGH_PRIORITY, RELIABLE, 0, rpcParameters->sender, true, 0, UNASSIGNED_NETWORK_ID,0); +} + +void endINTERRUPT(RPCParameters *rpcParameters) +{ + server->RPC("resume_turn",(const char*)rpcParameters->input, (*rpcParameters).numberOfBitsOfData, HIGH_PRIORITY, RELIABLE, 0, rpcParameters->sender, true, 0, UNASSIGNED_NETWORK_ID,0); +} + +void startCOMBAT(RPCParameters *rpcParameters) +{ + if(!( gTacticalStatus.uiFlags & INCOMBAT )) + + { + + gTacticalStatus.uiFlags |= INCOMBAT; + + sc_struct* data = (sc_struct*)rpcParameters->input; + EndTurn( data->ubStartingTeam ); + } + +} + + + + + +void sendREAL(RPCParameters *rpcParameters) +{ + real_struct* rData = (real_struct*)rpcParameters->input; + + + + //ScreenMsg( FONT_LTBLUE, MSG_CHAT, L"netbTeam %d is ready for realtime",rData->bteam );//diabled unless testing as cheats + if(readyteamreg[rData->bteam]==0) + { + readyteamreg[rData->bteam]=1;//register vote, to prevent double voting ;p~ //hayden + numreadyteams++; + + int numactiveteams=0; + int b; + for(int i=6;i<=LAST_TEAM;i++) + { + if(i==6)b=0; + else b=i; + + if(gTacticalStatus.Team[ b ].bTeamActive)numactiveteams++; + + }//same + //ScreenMsg( FONT_LTBLUE, MSG_CHAT, MPServerMessage[5], numreadyteams, numactiveteams ); + //check # clients ready for realtime + if (numreadyteams >= numactiveteams) + { + //if all send notification for realtime changeover + //ScreenMsg( FONT_LTBLUE, MSG_CHAT, L"Switching to realtime..." ); + numreadyteams=0; + memset( &readyteamreg , 0 , sizeof (int) * 10); + + server->RPC("gotoRT",(const char*)rpcParameters->input, (*rpcParameters).numberOfBitsOfData, HIGH_PRIORITY, RELIABLE, 0, UNASSIGNED_SYSTEM_ADDRESS, true, 0, UNASSIGNED_NETWORK_ID,0); + + + } + } + +} +int f_rec_num(int mode, SystemAddress sender)//from client data +{ + int x; + client_data cl_record; + for ( x=0; x<4;x++) + { + cl_record = client_d[x]; + + if(mode==0)//find empty slot for new record + { + if(cl_record.address.binaryAddress==0) + return(x); + } + if(mode==1)//wipe clean all + { + client_d[x].address.binaryAddress=0; + client_d[x].address.port=0; + client_d[x].cl_number=0; + } + if(mode==2)//clear one record + { + if(cl_record.address.binaryAddress==sender.binaryAddress && cl_record.address.port==sender.port) + { + client_d[x].address.port=0; + client_d[x].cl_number=0; + client_d[x].address.binaryAddress=0; + return(254); + } + + } + + + } + if(mode == 0)//'no free slots' + { + ScreenMsg( FONT_RED, MSG_CHAT, L"Client Record Error, Restart Server, and Report Error." ); + return (255); + } + return(254); +} + +//************************* //UNASSIGNED_SYSTEM_ADDRESS +//START INTERNAL SERVER +//************************* +//void send_settings (void)//send server settings to client +void requestSETTINGS(RPCParameters *rpcParameters ) +{ + + client_info* clinf = (client_info*)rpcParameters->input; + + //server assigned client numbers - hayden. + SystemAddress sender = rpcParameters->sender;//get senders address + int bslot = f_rec_num(0,blank);//get empty record slot + client_d[bslot].address=sender; //record clients address + int new_cl_num = bslot+1;//client number to assign + client_d[bslot].cl_number=new_cl_num; //record clients number + + + settings_struct lan; + + //lan.client_num = clinf->client_num;//old client assigned number + lan.client_num = new_cl_num; //new server assigned number + strcpy(lan.client_name , clinf->client_name); + + lan.max_clients = gsMAX_CLIENTS; + memcpy(lan.kitbag , kbag,sizeof (char)*100); + lan.damage_multiplier = gsDAMAGE_MULTIPLIER; + + lan.same_merc = gsSAME_MERC; + lan.gsMercArriveSectorX=gsMercArriveSectorX; + lan.gsMercArriveSectorY=gsMercArriveSectorY; + + lan.ENEMY_ENABLED=ENEMY_ENABLED; + lan.CREATURE_ENABLED=CREATURE_ENABLED; + lan.MILITIA_ENABLED=MILITIA_ENABLED; + lan.CIV_ENABLED=CIV_ENABLED; + + lan.gsPLAYER_BSIDE=gsPLAYER_BSIDE; + + lan.emorale=gsMORALE; + lan.gsREPORT_NAME=gsREPORT_NAME; +//something new + lan.secs_per_tick=gssecs_per_tick; + lan.soubBobbyRay=gGameOptions.ubBobbyRay; + lan.sofGunNut=gGameOptions.fGunNut; + lan.soubGameStyle=gGameOptions.ubGameStyle; + lan.soubDifficultyLevel=gGameOptions.ubDifficultyLevel; + lan.sofTurnTimeLimit=gGameOptions.fTurnTimeLimit; + lan.sofIronManMode=gGameOptions.fIronManMode; + lan.starting_balance=gsstarting_balance; + + lan.sofNewInv=gGameOptions.ubInventorySystem; + + lan.soDis_Bobby=gsDis_Bobby; + lan.soDis_Equip=gsDis_Equip; + + lan.gsMAX_MERCS=gsMAX_MERCS; + + memcpy( lan.client_names , client_names, sizeof( char ) * 4 * 30 ); + lan.team=clinf->team; + //lan.cl_ops[0]=clinf->cl_ops[0]; + //lan.cl_ops[1]=clinf->cl_ops[1]; + //lan.cl_ops[2]=clinf->cl_ops[2]; + //lan.cl_ops[3]=clinf->cl_ops[3]; + //memcpy(lan.cl_ops,clinf->cl_ops,sizeof(int)*4); +//// + lan.TESTING=gsTESTING; + + lan.cl_edge=clinf->cl_edge; + lan.TIME=TIME; + lan.WEAPON_READIED_BONUS=sWEAPON_READIED_BONUS; + + server->RPC("recieveSETTINGS",(const char*)&lan, (int)sizeof(settings_struct)*8, HIGH_PRIORITY, RELIABLE, 0, UNASSIGNED_SYSTEM_ADDRESS, true, 0, UNASSIGNED_NETWORK_ID,0); + +} + +//void rOVH (RPCParameters *rpcParameters) +//{ +// ovh_struct* rovhs = (ovh_struct*)rpcParameters->input; +// +// +// +// ++mercs_ready[rovhs->ubid]; +// //ncr++; +// nc = server->NumberOfConnections(); +// +// if(mercs_ready[rovhs->ubid] >= nc) +// { +// mercs_ready[rovhs->ubid]=0; +// ScreenMsg( FONT_LTBLUE, MSG_CHAT, L"advance %d",rovhs->ubid ); +// +// adv aoh; +// aoh.ubid=rovhs->ubid; +// +// server->RPC("advance_ovh_frame",(const char*)&aoh, (int)sizeof(adv)*8, HIGH_PRIORITY, RELIABLE, 0, UNASSIGNED_SYSTEM_ADDRESS, true, 0, UNASSIGNED_NETWORK_ID,0); +// +// } +// +//} + + +void start_server (void) +{ + if(!is_server) + { + + + + //retrieve settings from .ini + + f_rec_num(1,blank);//wipe clean + //char maxclients[30]; + char port[30]; + char SERVER_PORT[30]; + //char MAX_CLIENTS[30] ; + + // GetPrivateProfileString( "Ja2_mp Settings","MAX_CLIENTS", "", maxclients, MAX_PATH, "..\\Ja2_mp.ini" ); + GetPrivateProfileString( "Ja2_mp Settings","SERVER_PORT", "", port, MAX_PATH, "..\\Ja2_mp.ini" ); + // strcpy( MAX_CLIENTS , maxclients ); + strcpy( SERVER_PORT, port ); + + + char ints[30]; + char maxclients[30]; + + char hire_same_merc[30]; + char bteam1_enabled[30]; + char bteam2_enabled[30]; + char bteam3_enabled[30]; + char bteam4_enabled[30]; + + char player_bside[30]; + + char sBalance[30]; + char time_div[30]; + char mor[30]; + + GetPrivateProfileString( "Ja2_mp Settings","SAME_MERC", "", hire_same_merc, MAX_PATH, "..\\Ja2_mp.ini" ); + GetPrivateProfileString( "Ja2_mp Settings","DISABLE_MORALE", "", mor, MAX_PATH, "..\\Ja2_mp.ini" ); + GetPrivateProfileString( "Ja2_mp Settings","MAX_CLIENTS", "", maxclients, MAX_PATH, "..\\Ja2_mp.ini" ); + GetPrivateProfileString( "Ja2_mp Settings","DAMAGE_MULTIPLIER", "", net_div, MAX_PATH, "..\\Ja2_mp.ini" ); + + GetPrivateProfileString( "Ja2_mp Settings","ENEMY_ENABLED", "", bteam1_enabled, MAX_PATH, "..\\Ja2_mp.ini" ); + GetPrivateProfileString( "Ja2_mp Settings","CREATURE_ENABLED", "", bteam2_enabled, MAX_PATH, "..\\Ja2_mp.ini" ); + GetPrivateProfileString( "Ja2_mp Settings","MILITIA_ENABLED", "", bteam3_enabled, MAX_PATH, "..\\Ja2_mp.ini" ); + GetPrivateProfileString( "Ja2_mp Settings","CIV_ENABLED", "", bteam4_enabled, MAX_PATH, "..\\Ja2_mp.ini" ); + + GetPrivateProfileString( "Ja2_mp Settings","GAME_MODE", "", player_bside, MAX_PATH, "..\\Ja2_mp.ini" ); + + +//something new + gsMORALE=0; + if(atoi(mor)==1)gsMORALE=1; + + + GetPrivateProfileString( "Ja2_mp Settings","KIT_BAG", "", kbag, MAX_PATH, "..\\Ja2_mp.ini" ); + + char rpn[30]; + GetPrivateProfileString( "Ja2_mp Settings","REPORT_NAME", "", rpn, MAX_PATH, "..\\Ja2_mp.ini" ); + gsREPORT_NAME=atoi(rpn); + + GetPrivateProfileString( "Ja2_mp Settings","STARTING_BALANCE", "", sBalance, MAX_PATH, "..\\Ja2_mp.ini" ); + GetPrivateProfileString( "Ja2_mp Settings","TIMED_TURN_SECS_PER_TICK", "", time_div, MAX_PATH, "..\\Ja2_mp.ini" ); + + char dis_bob[30]; + char dis_equip[30]; + char max_merc[30]; + char test[30]; + GetPrivateProfileString( "Ja2_mp Settings","DISABLE_BOBBY_RAYS", "", dis_bob, MAX_PATH, "..\\Ja2_mp.ini" ); + GetPrivateProfileString( "Ja2_mp Settings","DISABLE_AIM_AND_MERC_EQUIP", "", dis_equip, MAX_PATH, "..\\Ja2_mp.ini" ); + GetPrivateProfileString( "Ja2_mp Settings","MAX_MERCS", "", max_merc, MAX_PATH, "..\\Ja2_mp.ini" ); + GetPrivateProfileString( "Ja2_mp Settings","TESTING", "", test, MAX_PATH, "..\\Ja2_mp.ini" ); + gsDis_Bobby=false; + gsDis_Equip=false; + + if(atoi(dis_bob)==1)gsDis_Bobby=true; + if(atoi(dis_equip)==1)gsDis_Equip=true; + + gsMAX_MERCS=atoi(max_merc); + gsTESTING = atoi(test); +//// + ENEMY_ENABLED =atoi(bteam1_enabled); + CREATURE_ENABLED =atoi(bteam2_enabled); + MILITIA_ENABLED =atoi(bteam3_enabled); + CIV_ENABLED =atoi(bteam4_enabled); + + gsPLAYER_BSIDE = atoi(player_bside); + + gsSAME_MERC = atoi(hire_same_merc); + gsDAMAGE_MULTIPLIER =(FLOAT)atof(net_div); + gsINTERRUPTS = atoi(ints); + gsMAX_CLIENTS = atoi(maxclients); + + gssecs_per_tick=atoi(time_div) ; + gsstarting_balance=atoi(sBalance); + + char time[30]; + GetPrivateProfileString( "Ja2_mp Settings","TIME", "", time, MAX_PATH, "..\\Ja2_mp.ini" ); + TIME=(FLOAT)atof(time); + + char wpr[30]; + GetPrivateProfileString( "Ja2_mp Settings","WEAPON_READIED_BONUS", "", wpr, MAX_PATH, "..\\Ja2_mp.ini" ); + sWEAPON_READIED_BONUS=atoi(wpr); + + //********************** + + + + + ScreenMsg( FONT_LTBLUE, MSG_CHAT, MPServerMessage[0] ); + + server=RakNetworkFactory::GetRakPeerInterface(); + bool b = server->Startup(gsMAX_CLIENTS, 30, &SocketDescriptor(atoi(SERVER_PORT),0), 1); + + server->SetMaximumIncomingConnections((gsMAX_CLIENTS)); + + + + + //RPC's + REGISTER_STATIC_RPC(server, sendPATH); + REGISTER_STATIC_RPC(server, sendSTANCE); + REGISTER_STATIC_RPC(server, sendDIR); + REGISTER_STATIC_RPC(server, sendFIRE); + REGISTER_STATIC_RPC(server, sendHIT); + REGISTER_STATIC_RPC(server, sendHIRE); + REGISTER_STATIC_RPC(server, sendguiPOS); + REGISTER_STATIC_RPC(server, sendguiDIR); + REGISTER_STATIC_RPC(server, sendEndTurn); + REGISTER_STATIC_RPC(server, sendAI); + REGISTER_STATIC_RPC(server, sendSTOP); + REGISTER_STATIC_RPC(server, sendINTERRUPT); + REGISTER_STATIC_RPC(server, sendREADY); + REGISTER_STATIC_RPC(server, sendGUI); + REGISTER_STATIC_RPC(server, sendBULLET); + REGISTER_STATIC_RPC(server, requestSETTINGS); + REGISTER_STATIC_RPC(server, sendSTATE); + REGISTER_STATIC_RPC(server, sendDEATH); + REGISTER_STATIC_RPC(server, sendhitSTRUCT); + REGISTER_STATIC_RPC(server, sendhitWINDOW); + REGISTER_STATIC_RPC(server, sendMISS); + //REGISTER_STATIC_RPC(server, rOVH); + + REGISTER_STATIC_RPC(server, updatenetworksoldier); + REGISTER_STATIC_RPC(server, Snull_team); + REGISTER_STATIC_RPC(server, sendFIREW); + REGISTER_STATIC_RPC(server, sendDOOR); + REGISTER_STATIC_RPC(server, endINTERRUPT); + REGISTER_STATIC_RPC(server, sendREAL); + REGISTER_STATIC_RPC(server, startCOMBAT); + // + + + if (b) + { + ScreenMsg( FONT_LTBLUE, MSG_CHAT, MPServerMessage[1]); + ScreenMsg( FONT_LTBLUE, MSG_CHAT, MPServerMessage[2]); + is_server = true; + connect_client();//connect client to server + } + else + { + ScreenMsg( FONT_LTBLUE, MSG_CHAT, MPServerMessage[4]); + + } + } + else + { + ScreenMsg( FONT_LTBLUE, MSG_CHAT, MPServerMessage[3]); + } + + + + +} + +// recieve and process server info packets + +void server_packet ( void ) +{ + + Packet* p; + + + if (is_server) + { + + p = server->Receive(); + + while(p) + { + //continue; // Didn't get any packets + + // We got a packet, get the identifier with our handy function + SpacketIdentifier = SGetPacketIdentifier(p); + //ScreenMsg( FONT_MCOLOR_LTYELLOW, MSG_INTERFACE, L"packet recieved"); + // Check if this is a network message packet + switch (SpacketIdentifier) + { + case ID_DISCONNECTION_NOTIFICATION://client disconnected purposefullly + // Connection lost normally + ScreenMsg( FONT_LTBLUE, MSG_CHAT, L"ID_DISCONNECTION_NOTIFICATION"); + f_rec_num(2, p->systemAddress);//clear record + break; + case ID_ALREADY_CONNECTED: + // Connection lost normally + ScreenMsg( FONT_LTBLUE, MSG_CHAT, L"ID_ALREADY_CONNECTED"); + break; + case ID_REMOTE_DISCONNECTION_NOTIFICATION: // Server telling the clients of another client disconnecting gracefully. You can manually broadcast this in a peer to peer enviroment if you want. + ScreenMsg( FONT_LTBLUE, MSG_CHAT, L"ID_REMOTE_DISCONNECTION_NOTIFICATION"); + break; + case ID_REMOTE_CONNECTION_LOST: // Server telling the clients of another client disconnecting forcefully. You can manually broadcast this in a peer to peer enviroment if you want. + ScreenMsg( FONT_LTBLUE, MSG_CHAT, L"ID_REMOTE_CONNECTION_LOST"); + break; + case ID_REMOTE_NEW_INCOMING_CONNECTION: // Server telling the clients of another client connecting. You can manually broadcast this in a peer to peer enviroment if you want. + ScreenMsg( FONT_LTBLUE, MSG_CHAT, L"ID_REMOT/MING_CONNECTION"); + break; + case ID_CONNECTION_ATTEMPT_FAILED: + ScreenMsg( FONT_LTBLUE, MSG_CHAT, L"ID_CONNECTION_ATTEMPT_FAILED"); + break; + case ID_NO_FREE_INCOMING_CONNECTIONS: + // Sorry, the server is full. I don't do anything here but + // A real app should tell the user + ScreenMsg( FONT_LTBLUE, MSG_CHAT, L"ID_NO_FREE_INCOMING_CONNECTIONS"); + break; + case ID_CONNECTION_LOST: + // Couldn't deliver a reliable packet - i.e. the other system was abnormally + // terminated + ScreenMsg( FONT_LTBLUE, MSG_CHAT, L"ID_CONNECTION_LOST");//client dropped + f_rec_num(2, p->systemAddress);//clear record + break; + case ID_CONNECTION_REQUEST_ACCEPTED: + // This tells the client they have connected + ScreenMsg( FONT_LTBLUE, MSG_CHAT, L"ID_CONNECTION_REQUEST_ACCEPTED"); + break; + case ID_NEW_INCOMING_CONNECTION: + //tells server client has connected + ScreenMsg( FONT_LTBLUE, MSG_CHAT, L"ID_NEW_INCOMING_CONNECTION"); + //send_settings();//send off server set settings + break; + case ID_MODIFIED_PACKET: + // Cheater! + ScreenMsg( FONT_LTBLUE, MSG_CHAT, L"ID_MODIFIED_PACKET"); + break; + default: + + ScreenMsg( FONT_LTBLUE, MSG_CHAT, L"** a packet has been recieved for which i dont know what to do... **"); + break; + } + + + // We're done with the packet, get more :) + server->DeallocatePacket(p); + p = server->Receive(); + } + } +} +// Copied from Multiplayer.cpp +// If the first byte is ID_TIMESTAMP, then we want the 5th byte +// Otherwise we want the 1st byte +unsigned char SGetPacketIdentifier(Packet *p) +{ + if (p==0) + return 255; + + if ((unsigned char)p->data[0] == ID_TIMESTAMP) + { + assert(p->length > sizeof(unsigned char) + sizeof(unsigned long)); + return (unsigned char) p->data[sizeof(unsigned char) + sizeof(unsigned long)]; + } + else + return (unsigned char) p->data[0]; +} + +void server_disconnect (void) +{ + if(is_server) + { + server->Shutdown(300); + is_server = false; + // We're done with the network + RakNetworkFactory::DestroyRakPeerInterface(server); + ScreenMsg( FONT_LTBLUE, MSG_CHAT, MPServerMessage[6]); + } + else + { + ScreenMsg( FONT_LTBLUE, MSG_CHAT, MPServerMessage[7]); + } +} \ No newline at end of file diff --git a/Multiplayer/test_space.cpp b/Multiplayer/test_space.cpp new file mode 100644 index 00000000..eb1787ed --- /dev/null +++ b/Multiplayer/test_space.cpp @@ -0,0 +1,399 @@ +#ifdef PRECOMPILEDHEADERS + #include "Tactical All.h" + #include "strategic.h" +#else + #include "builddefines.h" +#include "Bullets.h" + #include + #include + #include "wcheck.h" + #include "stdlib.h" + #include "debug.h" + #include "math.h" + #include "worlddef.h" + #include "worldman.h" + #include "renderworld.h" + #include "Assignments.h" + #include "Soldier Control.h" + #include "Animation Control.h" + #include "Animation Data.h" + #include "Isometric Utils.h" + #include "Event Pump.h" + #include "Timer Control.h" + #include "Render Fun.h" + #include "Render Dirty.h" + #include "mousesystem.h" + #include "interface.h" + #include "sysutil.h" + #include "FileMan.h" + #include "points.h" + #include "Random.h" + #include "ai.h" + #include "Interactive Tiles.h" + #include "soldier ani.h" + #include "english.h" + #include "overhead.h" + #include "Soldier Profile.h" + #include "Game Clock.h" + #include "soldier create.h" + #include "Merc Hiring.h" + #include "Game Event Hook.h" + #include "message.h" + #include "strategicmap.h" + #include "strategic.h" + #include "items.h" + #include "Soldier Add.h" + #include "History.h" + #include "Squads.h" + #include "Strategic Merc Handler.h" + #include "Dialogue Control.h" + #include "Map Screen Interface.h" + #include "Map Screen Interface Map.h" + #include "screenids.h" + #include "jascreens.h" + #include "text.h" + #include "Merc Contract.h" + #include "LaptopSave.h" + #include "personnel.h" + #include "Auto Resolve.h" + #include "Map Screen Interface Bottom.h" + #include "Quests.h" + #include "GameSettings.h" +#endif + +#include "MessageIdentifiers.h" +#include "RakNetworkFactory.h" +#include "RakPeerInterface.h" +#include "RakNetStatistics.h" +#include "RakNetTypes.h" +#include "BitStream.h" +#include +#include +#include +#include + +#include "tactical placement gui.h" +#include "connect.h" +#include "network.h" + +#pragma pack(1) + +#include "text.h" +#include "Types.h" +#include "connect.h" +#include "message.h" +#include "Event pump.h" +#include "Soldier Init List.h" +#include "Overhead.h" +#include "weapons.h" +#include "Merc Hiring.h" +#include "soldier profile.h" + +#include"laptop.h" + #include "florist Order Form.h" +#include "prebattle interface.h" +#include "teamturns.h" +extern INT8 SquadMovementGroups[ ]; + +#include "test_space.h" +#include "soldier control.h" + +bool ovh_advance; +bool ovh_ready; + +#include "opplist.h" + +//int cnt = 40; + + +void test_func2 (void)//now bound to "0" //currently displays coordinates of the mouse +{ + ScreenMsg( FONT_LTGREEN, MSG_CHAT, L"test_func2 - function testing ground:" ); + + +SOLDIERTYPE * pSoldier=MercPtrs[ 0 ]; +//SOLDIERTYPE * pSoldier2=MercPtrs[ 127 ]; +// +////pSoldier->AdjustNoAPToFinishMove( TRUE ); +// +////pSoldier2->bVisible = 1; +//ManSeesMan(pSoldier,pSoldier2,pSoldier2->sGridNo,pSoldier2->pathing.bLevel,0,1); + + +/* +INT16 sCellX, sCellY; + sCellX = CenterX( 22163 ); + sCellY = CenterY( 22163 ); + +pSoldier->EVENT_InternalSetSoldierPosition( sCellX, sCellY ,FALSE, FALSE, FALSE );*/ + + + + +//SOLDIERTYPE * pSoldier=MercPtrs[ 0 ]; +//pSoldier->bLife=0; +//SoldierCollapse( pSoldier ); +//SoldierTakeDamage( pFirer, ANIM_CROUCH, 1, 100, TAKE_DAMAGE_BLOODLOSS, NOBODY, NOWHERE, 0, TRUE ); +//TurnSoldierIntoCorpse( pFirer, FALSE, FALSE ); + +//SOLDIERTYPE * pSoldier=MercPtrs[ 0 ]; +//// +//pSoldier->fNoAPToFinishMove = TRUE; +// +// +//fInterfacePanelDirty = DIRTYLEVEL2; + + + +////EVENT_InitNewSoldierAnim(pSoldier,3,0,0); +//pSoldier->ubDesiredHeight = ANIM_CROUCH; + +//SOLDIERTYPE * pSoldier=MercPtrs[ 0 ]; +//pSoldier->usAnimState=50; +//TurnSoldierIntoCorpse( pSoldier, TRUE, TRUE ); + +//gTacticalStatus.uiFlags |= SHOW_ALL_MERCS; +//BeginTeamTurn (0); + + + +; + +//gTacticalStatus.ubCurrentTeam = OUR_TEAM; +//guiPendingOverrideEvent = LA_ENDUIOUTURNLOCK; +//ExitCombatMode(); +//fInterfacePanelDirty = DIRTYLEVEL2; + + +//InitPlayerUIBar( FALSE ); + + +//UIHandleLUIEndLock( NULL ); +//if( (gTacticalStatus.uiFlags & TURNBASED) && (gTacticalStatus.uiFlags & INCOMBAT) ) +// ScreenMsg( FONT_LTGREEN, MSG_CHAT, L"combat turn based" ); +//else +// ScreenMsg( FONT_LTGREEN, MSG_CHAT, L"not" ); + + +//SOLDIERTYPE * pSoldier=MercPtrs[ 0 ]; +// +// if ( ( gAnimControl[ pSoldier->usAnimState ].uiFlags &( ANIM_FIREREADY | ANIM_FIRE ) ) ) +// { +// ScreenMsg( FONT_LTGREEN, MSG_CHAT, L"Ready" ); +// } +// else +// ScreenMsg( FONT_LTGREEN, MSG_CHAT, L"Not" ); + +////fInterfacePanelDirty = DIRTYLEVEL2; +////guiPendingOverrideEvent = LU_ENDUILOCK; +////guiPendingOverrideEvent = LA_ENDUIOUTURNLOCK; +// +// +// +// ClearIntList(); +// //guiPendingOverrideEvent = LU_ENDUILOCK; +// guiPendingOverrideEvent = LA_ENDUIOUTURNLOCK; +// fInterfacePanelDirty = DIRTYLEVEL2; +// +// if ( gusSelectedSoldier != NOBODY ) +// { +// SlideTo( NOWHERE, gusSelectedSoldier, NOBODY ,SETLOCATOR); +// MercPtrs[ gusSelectedSoldier ]->DoMercBattleSound( BATTLE_SOUND_ATTN1 ); +// } +// InitPlayerUIBar( 0 ); +//HandleTacticalUI( ); +//guiPendingOverrideEvent = LA_BEGINUIOURTURNLOCK; +//int n = 0; +//for(cnt=40+n ; cnt < 40+5+n ; cnt++) +//{ +// +//QuickCreateProfileMerc( CIV_TEAM, cnt );jk +// +//RecruitRPC( cnt ); +//Sleep(3000); +//} +//QuickCreateProfileMerc( CIV_TEAM, cnt ); +//RecruitRPC( cnt ); +//cnt++; + + +//HandleDoorChangeFromGridNo( pSoldier, 18451, FALSE ); + +//OBJECTTYPE Object; +//for (cnt=0; cnt<20;cnt++) +//{ +//CreateItem( 201, 100, &Object ); +// +//AutoPlaceObject( pSoldier, &Object, TRUE ); +// +// + + + + +//INT16 sCellX, sCellY; +////ConvertGridNoToCellXY( 13576, &sCellX, &sCellY ); +// +// sCellX = CenterX( 13576 ); +// sCellY = CenterY( 13576 ); +// +// //pSoldier->dXPos = sCellX; +// //pSoldier->dYPos = sCellY; +// +// //pSoldier->sX = (INT16)sCellX; +// //pSoldier->sY = (INT16)sCellY; +// EVENT_InitNewSoldierAnim( pSoldier, 6, 0, FALSE ); + + //EVENT_SetSoldierPositionForceDelete( pSoldier, (FLOAT)sCellX, (FLOAT)sCellY ); + +//HaultSoldierFromSighting( pSoldier, 1 ); +//pSoldier->sScheduledStop=7961; +//// +////EVENT_SetSoldierPosition( pSoldier, 1140, 1170 ); +//AdjustNoAPToFinishMove( pSoldier, TRUE ); +//pSoldier->fTurningFromPronePosition = FALSE; +// +////HaultSoldierFromSighting( pSoldier, 1 ); + + + + +//UINT16 usPathData[30]; +//usPathData[0]=3; +//usPathData[1]=5; +//usPathData[2]=7; +// +//pSoldier->sFinalDestination = 8446; +// +//pSoldier->usPathDataSize=3; +//pSoldier->usPathIndex=0; +// +//memcpy(pSoldier->usPathingData,usPathData,sizeof(UINT16)*30); + + +//INT16 sNewGridNo; + +//sNewGridNo = NewGridNo( (UINT16)pSoldier->sGridNo, DirectionInc( (UINT8)pSoldier->usPathingData[ pSoldier->usPathDataSize ] ) ); + +//pSoldier->sFinalDestination = sNewGridNo; + +//EVENT_InitNewSoldierAnim( pSoldier, 0, 0, FALSE ); + + + +//ovh_advance=true; +// +// +// CHAR16 string[255]; +// memcpy(string,TeamTurnString[ 7 ], sizeof( CHAR16) * 255 ); +// +// CHAR16 name[255]; +// mbstowcs( name, CLIENT_NAME, sizeof (char)*30 ); +// +// CHAR16 full[255]; +// swprintf(full, L"%s - '%s'",string,name); +//// +//// +// memcpy( TeamTurnString[ 7 ] , full, sizeof( CHAR16) * 255 ); + + +} + + + +//BOOLEAN fMadeCorpse; +// SOLDIERTYPE * pSoldier=MercPtrs[ 0 ]; +//pSoldier->bLife = 0; +// HandleSoldierDeath( pSoldier, &fMadeCorpse ); + +//guiPendingOverrideEvent = LA_BEGINUIOURTURNLOCK; +// +//guiPendingOverrideEvent = CA_MERC_SHOOT; +// +//guiPendingOverrideEvent = G_GETTINGITEM; +// +//guiPendingOverrideEvent = LU_ON_TERRAIN; +// +//guiPendingOverrideEvent = ET_ON_TERRAIN; +// +//guiPendingOverrideEvent = A_CHANGE_TO_MOVE; + + + + + + + + + + + +//HandleTacticalUI( ); + + + + //CHAR8 string[60]; + // wcscpy( string, "GetVideoObject" ); + //sprintf( string, "hello"); + /* char szDefault[255]; + sprintf(szDefault, "%s","hello"); + + + ScreenMsg( FONT_LTGREEN, MSG_CHAT, L"%S has connected.",szDefault );*/ + + //manual overide + //manual_overide(); + //allow_bullet=1; + // + + //if(1) + //{ + // stage=0; + // ScreenMsg( FONT_MCOLOR_LTYELLOW, MSG_INTERFACE, L"1" ); + // //FireBulletGivenTarget( MercPtrs[0], 875, 995, 1, 11, -74, 0, 0 ); + // + // + // INT32 iBullet; + // BULLET * pBullet; + + // iBullet = CreateBullet( 0, 0, 0,11 ); + // if (iBullet == -1) + // { + // ScreenMsg( FONT_YELLOW, MSG_CHAT, L"Failed to create bullet"); + // } + // pBullet = GetBulletPtr( iBullet ); + + // //ScreenMsg( FONT_YELLOW, MSG_CHAT, L"Created Bullet"); + + // pBullet->fCheckForRoof=0; + // pBullet->qIncrX=-917769; + // pBullet->qIncrY=-507159; + // pBullet->qIncrZ=-537679; + // pBullet->sHitBy=-30; + // pBullet->ddHorizAngle=-2.5959375990628013; + // pBullet->fAimed=1; + // pBullet->ubItemStatus=0; + // pBullet->qCurrX=1231159031; + // pBullet->qCurrY=1221083881; + // pBullet->qCurrZ=182963121; + // pBullet->iImpact=28; + // pBullet->iRange=200; + // pBullet->sTargetGridNo=15929; + // pBullet->bStartCubesAboveLevelZ=2; + // pBullet->bEndCubesAboveLevelZ=0; + // pBullet->iDistanceLimit=328; + + + // SOLDIERTYPE * pFirer=MercPtrs[ 0 ]; + + // //FireBullet( pFirer, pBullet, FALSE ); + // if(is_client)send_bullet( pBullet, 11 );//hayden + + +//} + //else + //{ + // stage=1; + // ScreenMsg( FONT_MCOLOR_LTYELLOW, MSG_INTERFACE, L"0" ); + // FireBulletGivenTarget( MercPtrs[0], 875, 995, 1, 11, -74, 0, 0 ); + //} \ No newline at end of file diff --git a/Multiplayer/test_space.h b/Multiplayer/test_space.h new file mode 100644 index 00000000..978085b7 --- /dev/null +++ b/Multiplayer/test_space.h @@ -0,0 +1,13 @@ +#pragma once + +#define ENABLE_COLLISION (is_server && pBullet->pFirer->ubID<120) || (!is_server && is_client && pBullet->pFirer->ubID<20) || (!is_server && !is_client) + +void send_bullet( BULLET * pBullet, UINT16 usHandItem); + +INT8 FireBullet( SOLDIERTYPE * pFirer, BULLET * pBullet, BOOLEAN fFake ); + +#define NOCDCHECK + +extern bool ovh_advance; +extern bool ovh_ready; +void request_ovh(UINT8 ubID); diff --git a/Options Screen.cpp b/Options Screen.cpp index efce3947..6e090688 100644 --- a/Options Screen.cpp +++ b/Options Screen.cpp @@ -39,6 +39,7 @@ #include "SmokeEffects.h" #endif +#include "connect.h" #include "WorldMan.h" ///////////////////////////////// @@ -1173,6 +1174,14 @@ void ConfirmQuitToMainMenuMessageBoxCallBack( UINT8 bExitValue ) gfExitOptionsAfterMessageBox = TRUE; SetOptionsExitScreen( MAINMENU_SCREEN ); + if (is_networked) + { + // haydent + server_disconnect(); + client_disconnect(); + + } + //We want to reinitialize the game ReStartingGame(); } diff --git a/SaveLoadGame.cpp b/SaveLoadGame.cpp index 100bab80..b8b76fcd 100644 --- a/SaveLoadGame.cpp +++ b/SaveLoadGame.cpp @@ -122,6 +122,8 @@ #include "Rain.h" //end rain +#include "connect.h" + ///////////////////////////////////////////////////// // // Local Defines @@ -1791,7 +1793,12 @@ BOOLEAN InitSaveDir() // The locale-specific save dir location is of the form L"..\\SavedGames" // This has not changed; instead, we strip the ".." at the beginning - sprintf( gSaveDir, "%s%S", dataDir.c_str(), pMessageStrings[ MSG_SAVEDIRECTORY ] + 2 ); + if(is_networked) + { + sprintf( gSaveDir, "%s%S", dataDir.c_str(), pMessageStrings[ MSG_MPSAVEDIRECTORY ] + 2 ); + } + else + sprintf( gSaveDir, "%s%S", dataDir.c_str(), pMessageStrings[ MSG_SAVEDIRECTORY ] + 2 ); // This was moved here from SaveGame //Check to see if the save directory exists @@ -1919,6 +1926,12 @@ BOOLEAN SaveGame( UINT8 ubSaveGameID, STR16 pGameDesc ) SaveGameHeader.uiDay = GetWorldDay(); SaveGameHeader.ubHour = (UINT8)GetWorldHour(); SaveGameHeader.ubMin = (UINT8)guiMin; + if(is_networked) + { + SaveGameHeader.uiDay = CLIENT_NUM; + SaveGameHeader.ubHour = MAX_CLIENTS; + SaveGameHeader.ubMin = MAX_MERCS; + } //copy over the initial game options memcpy( &SaveGameHeader.sInitialGameOptions, &gGameOptions, sizeof( GAME_OPTIONS ) ); diff --git a/SaveLoadGame.h b/SaveLoadGame.h index dda6b7e8..c47b4de6 100644 --- a/SaveLoadGame.h +++ b/SaveLoadGame.h @@ -58,6 +58,8 @@ typedef struct UINT8 ubFiller[109]; + + } SAVED_GAME_HEADER; diff --git a/SaveLoadScreen.cpp b/SaveLoadScreen.cpp index d2fd091e..7d192ebc 100644 --- a/SaveLoadScreen.cpp +++ b/SaveLoadScreen.cpp @@ -39,6 +39,7 @@ #endif #include "Campaign Init.h" +#include "connect.h" BOOLEAN gfSchedulesHosed = FALSE; extern UINT32 guiBrokenSaveGameVersion; @@ -525,6 +526,17 @@ BOOLEAN EnterSaveLoadScreen() usPosX, SLG_CANCEL_POS_Y, BUTTON_TOGGLE, MSYS_PRIORITY_HIGH, DEFAULT_MOVE_CALLBACK, BtnSlgCancelCallback ); + //load mp game + /*UINT16 MPusPosX = SLG_LOAD_CANCEL_POS_X-39; + + UINT32 MPguiSlgCancelBtn = CreateIconAndTextButton( guiSlgButtonImage, zSaveLoadText[SLG_CANCEL], OPT_BUTTON_FONT, + OPT_BUTTON_ON_COLOR, DEFAULT_SHADOW, + OPT_BUTTON_OFF_COLOR, DEFAULT_SHADOW, + TEXT_CJUSTIFIED, + usPosX, SLG_CANCEL_POS_Y, BUTTON_TOGGLE, MSYS_PRIORITY_HIGH, + DEFAULT_MOVE_CALLBACK, BtnSlgCancelCallback );*/ + + //Either the save or load button if( gfSaveGame ) @@ -1361,7 +1373,10 @@ BOOLEAN DisplaySaveGameEntry( INT8 bEntryID )//, UINT16 usPosY ) else { //Create the string for the Data - swprintf( zDateString, L"%s %d, %02d:%02d", pMessageStrings[ MSG_DAY ], SaveGameHeader.uiDay, SaveGameHeader.ubHour, SaveGameHeader.ubMin ); + if(is_networked) + swprintf( zDateString, L"%s %d / %d", pMessageStrings[ MSG_CLIENT ], SaveGameHeader.uiDay, SaveGameHeader.ubHour ); + else + swprintf( zDateString, L"%s %d, %02d:%02d", pMessageStrings[ MSG_DAY ], SaveGameHeader.uiDay, SaveGameHeader.ubHour, SaveGameHeader.ubMin ); //Create the string for the current location if( SaveGameHeader.sSectorX == -1 && SaveGameHeader.sSectorY == -1 || SaveGameHeader.bSectorZ < 0 ) @@ -1383,7 +1398,8 @@ BOOLEAN DisplaySaveGameEntry( INT8 bEntryID )//, UINT16 usPosY ) // // Number of mercs on the team // - +if(!is_networked) +{ //if only 1 merc is on the team if( SaveGameHeader.ubNumOfMercsOnPlayersTeam == 1 ) { @@ -1395,7 +1411,25 @@ BOOLEAN DisplaySaveGameEntry( INT8 bEntryID )//, UINT16 usPosY ) //use "mercs" swprintf( zNumMercsString, L"%d %s", SaveGameHeader.ubNumOfMercsOnPlayersTeam, pMessageStrings[ MSG_MERCS ] ); } +} +else +{ + // + // Number of mercs on the team + // + //if only 1 merc is on the team + if( SaveGameHeader.ubMin == 1 ) + { + //use "merc" + swprintf( zNumMercsString, L"%d / %d %s", SaveGameHeader.ubNumOfMercsOnPlayersTeam,SaveGameHeader.ubMin, MercAccountText[ MERC_ACCOUNT_MERC ] ); + } + else + { + //use "mercs" + swprintf( zNumMercsString, L"%d / %d %s", SaveGameHeader.ubNumOfMercsOnPlayersTeam,SaveGameHeader.ubMin, pMessageStrings[ MSG_MERCS ] ); + } +} //Get the current balance swprintf( zBalanceString, L"%d", SaveGameHeader.iCurrentBalance); InsertCommasForDollarFigure( zBalanceString ); @@ -1418,7 +1452,7 @@ BOOLEAN DisplaySaveGameEntry( INT8 bEntryID )//, UINT16 usPosY ) DrawTextToScreen( zNumMercsString, (UINT16)(usPosX+SLG_NUM_MERCS_OFFSET_X), (UINT16)(usPosY+SLG_NUM_MERCS_OFFSET_Y), 0, uiFont, ubFontColor, FONT_MCOLOR_BLACK, FALSE, LEFT_JUSTIFIED ); //The balance - DrawTextToScreen( zBalanceString, (UINT16)(usPosX+SLG_BALANCE_OFFSET_X), (UINT16)(usPosY+SLG_BALANCE_OFFSET_Y), 0, uiFont, ubFontColor, FONT_MCOLOR_BLACK, FALSE, LEFT_JUSTIFIED ); + if(!is_networked)DrawTextToScreen( zBalanceString, (UINT16)(usPosX+SLG_BALANCE_OFFSET_X), (UINT16)(usPosY+SLG_BALANCE_OFFSET_Y), 0, uiFont, ubFontColor, FONT_MCOLOR_BLACK, FALSE, LEFT_JUSTIFIED ); if( gbSaveGameArray[ bEntryID ] || ( gfSaveGame && !gfUserInTextInputMode && ( gbSelectedSaveLocation == bEntryID ) ) ) { @@ -1544,6 +1578,9 @@ void BtnSlgCancelCallback(GUI_BUTTON *btn,INT32 reason) else if( guiPreviousOptionScreen == MAINMENU_SCREEN ) SetSaveLoadExitScreen( MAINMENU_SCREEN ); + else if( guiPreviousOptionScreen == GAME_INIT_OPTIONS_SCREEN )//hayden + SetSaveLoadExitScreen( GAME_INIT_OPTIONS_SCREEN ); + else SetSaveLoadExitScreen( OPTIONS_SCREEN ); diff --git a/Standard Gaming Platform/SGP_2005Express.vcproj b/Standard Gaming Platform/SGP_2005Express.vcproj index c485677e..6fd3274f 100644 --- a/Standard Gaming Platform/SGP_2005Express.vcproj +++ b/Standard Gaming Platform/SGP_2005Express.vcproj @@ -1,7 +1,7 @@ pSoldier, pTarget->pSoldier, ubAccuracy, (BOOLEAN)(fKnife || fClaw) ); } - // WANNE: Why is impact here always set to 0? The impact was calculated a few lines before! //iImpact = 0; // WANNE: Just for safty. if (iImpact < 0) iImpact = 0; - iNewLife = pTarget->pSoldier->stats.bLife - iImpact; if( pAttacker->uiFlags & CELL_MERC ) diff --git a/Strategic/Campaign Init.cpp b/Strategic/Campaign Init.cpp index 2a5cd6c1..d8190d5b 100644 --- a/Strategic/Campaign Init.cpp +++ b/Strategic/Campaign Init.cpp @@ -19,6 +19,8 @@ #include "Tactical Save.h" #endif +#include "connect.h" + extern BOOLEAN InitStrategicMovementCosts(); void InitKnowFacilitiesFlags( ); @@ -386,6 +388,7 @@ void TrashUndergroundSectorInfo() void BuildUndergroundSectorInfoList() { UNDERGROUND_SECTORINFO *curr; + SECTORINFO *pSector = NULL; TrashUndergroundSectorInfo(); @@ -582,8 +585,9 @@ void InitNewCampaign() BuildUndergroundSectorInfoList(); - // allow overhead view of omerta A9 on game onset - SetSectorFlag( 9, 1, 0, SF_ALREADY_VISITED ); + if (!is_networked) + // allow overhead view of omerta A9 on game onset + SetSectorFlag( 9, 1, 0, SF_ALREADY_VISITED ); //hayden //Generates the initial forces in a new campaign. The idea is to randomize numbers and sectors //so that no two games are the same. diff --git a/Strategic/Creature Spreading.cpp b/Strategic/Creature Spreading.cpp index 6bd14dbb..9c4079a5 100644 --- a/Strategic/Creature Spreading.cpp +++ b/Strategic/Creature Spreading.cpp @@ -33,6 +33,9 @@ #include "Map Information.h" #endif +#include "connect.h" + + #ifdef JA2BETAVERSION BOOLEAN gfClearCreatureQuest = FALSE; extern UINT32 uiMeanWhileFlags; @@ -933,7 +936,13 @@ void CreatureAttackTown( UINT8 ubSectorID, BOOLEAN fOverrideTest ) InitPreBattleInterface( NULL, TRUE ); break; case CREATURE_BATTLE_CODE_TACTICALLYADD: - PrepareCreaturesForBattle(); + if (is_networked) + { + if(is_server && CREATURE_ENABLED) + PrepareCreaturesForBattle(); + } + else + PrepareCreaturesForBattle(); break; } InterruptTime(); diff --git a/Strategic/Game Init.cpp b/Strategic/Game Init.cpp index 352deba8..d3126776 100644 --- a/Strategic/Game Init.cpp +++ b/Strategic/Game Init.cpp @@ -63,7 +63,8 @@ #include "Interface Panels.h" #endif -//forward declarations of common classes to eliminate includes +#include "text.h" +#include "connect.h" class OBJECTTYPE; class SOLDIERTYPE; @@ -418,7 +419,7 @@ BOOLEAN InitNewGame( BOOLEAN fReset ) ClearTacticalMessageQueue( ); // clear mapscreen messages - FreeGlobalMessageList(); + if(!is_networked)FreeGlobalMessageList(); //hayden // IF our first time, go into laptop! if ( gubScreenCount == 0 ) @@ -435,6 +436,8 @@ BOOLEAN InitNewGame( BOOLEAN fReset ) // this is for the "mercs climbing down from a rope" animation, NOT Skyrider!! ResetHeliSeats( ); + if(!is_networked) + { // Setup two new messages! AddPreReadEmail(OLD_ENRICO_1,OLD_ENRICO_1_LENGTH,MAIL_ENRICO, GetWorldTotalMin() ); AddPreReadEmail(OLD_ENRICO_2,OLD_ENRICO_2_LENGTH,MAIL_ENRICO, GetWorldTotalMin() ); @@ -446,6 +449,7 @@ BOOLEAN InitNewGame( BOOLEAN fReset ) { AddEmail(MERC_INTRO, MERC_INTRO_LENGTH, SPECK_FROM_MERC, GetWorldTotalMin( ), -1 ); } + } @@ -509,8 +513,21 @@ BOOLEAN InitNewGame( BOOLEAN fReset ) #endif + if(is_networked) + { + SetLaptopExitScreen( MAP_SCREEN ); //hayden + SetPendingNewScreen( MAP_SCREEN ); + ScreenMsg( MSG_FONT_WHITE, MSG_CHAT, L"------------------------------------------------------"); + ScreenMsg( MSG_FONT_WHITE, MSG_CHAT, MPHelp[0]); + ScreenMsg( MSG_FONT_WHITE, MSG_CHAT, L"------------------------------------------------------"); + ScreenMsg( MSG_FONT_WHITE, MSG_CHAT, MPHelp[1]); + + } + else + { SetLaptopExitScreen( INIT_SCREEN ); SetPendingNewScreen(LAPTOP_SCREEN); + } gubScreenCount = 1; //Set the fact the game is in progress diff --git a/Strategic/Hourly Update.cpp b/Strategic/Hourly Update.cpp index d277258a..6b600cc1 100644 --- a/Strategic/Hourly Update.cpp +++ b/Strategic/Hourly Update.cpp @@ -20,6 +20,7 @@ #include "Dialogue Control.h" #endif +#include "connect.h" void HourlyQuestUpdate( void ); void HourlyLarryUpdate( void ); @@ -42,6 +43,8 @@ void HandleHourlyUpdate() //if the game hasnt even started yet ( we havent arrived in the sector ) dont process this if ( DidGameJustStart() ) return; + if(is_networked) + return; // hourly update of town loyalty HandleTownLoyalty(); diff --git a/Strategic/Map Screen Interface Bottom.cpp b/Strategic/Map Screen Interface Bottom.cpp index 76d00d2c..f322f90d 100644 --- a/Strategic/Map Screen Interface Bottom.cpp +++ b/Strategic/Map Screen Interface Bottom.cpp @@ -51,6 +51,8 @@ #include "SaveLoadScreen.h" #endif +#include "connect.h" + /* CHRISL: Adjusted settings to allow new Map_Screen_Bottom_800x600.sti to work. This is needed if we want to have the new inventory panel not overlap the message text area. */ #define MAP_BOTTOM_X 0 @@ -292,13 +294,15 @@ void RenderMapScreenInterfaceBottom( BOOLEAN fForceMapscreenFullRender ) // render whole panel // HEADROCK Changed this line to accept outside influence through the new boolean: - if ( fForceMapscreenFullRender == TRUE || fMapScreenBottomDirty == TRUE ) + if ( fForceMapscreenFullRender == TRUE || fMapScreenBottomDirty == TRUE) { // get and blt panel - GetVideoObject(&hHandle, guiMAPBOTTOMPANEL ); - BltVideoObject( guiSAVEBUFFER , hHandle, 0, MAP_BOTTOM_X, MAP_BOTTOM_Y, VO_BLT_SRCTRANSPARENCY,NULL ); + GetVideoObject(&hHandle, guiMAPBOTTOMPANEL ); + BltVideoObject( guiSAVEBUFFER , hHandle, 0, MAP_BOTTOM_X, MAP_BOTTOM_Y, VO_BLT_SRCTRANSPARENCY,NULL ); - if( GetSectorFlagStatus( sSelMapX, sSelMapY, ( UINT8 )iCurrentMapSectorZ, SF_ALREADY_VISITED ) == TRUE ) + // WANNE - MP: Radarmap image should be displayed on every sector in multiplayer game + if( GetSectorFlagStatus( sSelMapX, sSelMapY, ( UINT8 )iCurrentMapSectorZ, SF_ALREADY_VISITED ) == TRUE + || is_networked) { GetMapFileName( sSelMapX, sSelMapY, ( UINT8 )iCurrentMapSectorZ, bFilename, TRUE, TRUE ); LoadRadarScreenBitmap( bFilename ); @@ -1286,6 +1290,12 @@ void EnableDisAbleMapScreenOptionsButton( BOOLEAN fEnable ) BOOLEAN AllowedToTimeCompress( void ) { + // WANNE - MP: In multiplayer mode we do not allow compress time, for now. + if (is_networked) + { + return ( FALSE ); + } + // if already leaving, disallow any other attempts to exit if ( fLeavingMapScreen ) { @@ -1759,6 +1769,10 @@ BOOLEAN AllowedToExitFromMapscreenTo( INT8 bExitToWhere ) { return( FALSE ); } + if ( (( sSelMapX != gWorldSectorX ) || ( sSelMapY != gWorldSectorY ) || (( UINT8 )iCurrentMapSectorZ ) != gbWorldSectorZ ) && is_client) //hayden (PBI only) + { + return (FALSE); + } } //if we are map screen sector inventory @@ -1768,6 +1782,13 @@ BOOLEAN AllowedToExitFromMapscreenTo( INT8 bExitToWhere ) return( FALSE ); } + //hayden + if( bExitToWhere == MAP_EXIT_TO_LAPTOP && !allowlaptop && is_networked /*&& (is_client || is_server)*/) + { + //dont allow it + return( FALSE ); + } + // OK to go there, passed all the checks return( TRUE ); } diff --git a/Strategic/Map Screen Interface Map Inventory.cpp b/Strategic/Map Screen Interface Map Inventory.cpp index a464125c..56b626ab 100644 --- a/Strategic/Map Screen Interface Map Inventory.cpp +++ b/Strategic/Map Screen Interface Map Inventory.cpp @@ -589,7 +589,6 @@ void CreateDestroyMapInventoryPoolButtons( BOOLEAN fExitFromMapScreen ) { DeleteItemDescriptionBox(); } - //DEF: added to remove the 'item blip' from staying on the radar map iCurrentlyHighLightedItem = -1; @@ -840,16 +839,16 @@ void MapInvenPoolSlots(MOUSE_REGION * pRegion, INT32 iReason ) { if(OK_CONTROLLABLE_MERC( MercPtrs[gCharactersList[bSelectedInfoChar].usSolID] )) { - if(ItemSlotLimit( &twItem->object, STACK_SIZE_LIMIT ) == 1) - { - fShowInventoryFlag = TRUE; - MAPInternalInitItemDescriptionBox( &twItem->object, 0, MercPtrs[gCharactersList[bSelectedInfoChar].usSolID] ); - } - else if(gpItemPointer == NULL || gpItemPointer->usItem == twItem->object.usItem || ValidAttachment(gpItemPointer->usItem, twItem->object.usItem) == TRUE || ValidAmmoType(twItem->object.usItem, gpItemPointer->usItem) == TRUE) - { - InitSectorStackPopup( MercPtrs[gCharactersList[bSelectedInfoChar].usSolID], twItem, iCounter, 0, INV_REGION_Y, 261, ( SCREEN_HEIGHT - PLAYER_INFO_Y ) ); - fTeamPanelDirty=TRUE; - fInterfacePanelDirty = DIRTYLEVEL2; + if(ItemSlotLimit( &twItem->object, STACK_SIZE_LIMIT ) == 1) + { + fShowInventoryFlag = TRUE; + MAPInternalInitItemDescriptionBox( &twItem->object, 0, MercPtrs[gCharactersList[bSelectedInfoChar].usSolID] ); + } + else if(gpItemPointer == NULL || gpItemPointer->usItem == twItem->object.usItem || ValidAttachment(gpItemPointer->usItem, twItem->object.usItem) == TRUE || ValidAmmoType(twItem->object.usItem, gpItemPointer->usItem) == TRUE) + { + InitSectorStackPopup( MercPtrs[gCharactersList[bSelectedInfoChar].usSolID], twItem, iCounter, 0, INV_REGION_Y, 261, ( SCREEN_HEIGHT - PLAYER_INFO_Y ) ); + fTeamPanelDirty=TRUE; + fInterfacePanelDirty = DIRTYLEVEL2; } } } diff --git a/Strategic/Map Screen Interface Map.cpp b/Strategic/Map Screen Interface Map.cpp index 5a5b9cd6..eea99e77 100644 --- a/Strategic/Map Screen Interface Map.cpp +++ b/Strategic/Map Screen Interface Map.cpp @@ -45,6 +45,8 @@ #include "Air Raid.h" #endif +#include "connect.h" + // zoom x and y coords for map scrolling INT32 iZoomX = 0; INT32 iZoomY = 0; @@ -756,41 +758,44 @@ UINT32 DrawMap( void ) for ( cnt2 = 1; cnt2 < MAP_WORLD_Y - 1; cnt2++ ) { // LATE DESIGN CHANGE: darken sectors not yet visited, instead of those under known enemy control - if( GetSectorFlagStatus( cnt, cnt2, ( UINT8 ) iCurrentMapSectorZ, SF_ALREADY_VISITED ) == FALSE ) -// if ( IsTheSectorPerceivedToBeUnderEnemyControl( cnt, cnt2, ( INT8 )( iCurrentMapSectorZ ) ) ) + if(!is_networked) //hayden - dont darken anything { - if( fShowAircraftFlag && !iCurrentMapSectorZ ) + if( GetSectorFlagStatus( cnt, cnt2, ( UINT8 ) iCurrentMapSectorZ, SF_ALREADY_VISITED ) == FALSE ) + // if ( IsTheSectorPerceivedToBeUnderEnemyControl( cnt, cnt2, ( INT8 )( iCurrentMapSectorZ ) ) ) { - if( !StrategicMap[ cnt + cnt2 * WORLD_MAP_X ].fEnemyAirControlled ) + if( fShowAircraftFlag && !iCurrentMapSectorZ ) { - // sector not visited, not air controlled - ShadeMapElem( cnt, cnt2, MAP_SHADE_DK_GREEN ); + if( !StrategicMap[ cnt + cnt2 * WORLD_MAP_X ].fEnemyAirControlled ) + { + // sector not visited, not air controlled + ShadeMapElem( cnt, cnt2, MAP_SHADE_DK_GREEN ); + } + else + { + // sector not visited, controlled and air not + ShadeMapElem( cnt, cnt2, MAP_SHADE_DK_RED ); + } } else { - // sector not visited, controlled and air not - ShadeMapElem( cnt, cnt2, MAP_SHADE_DK_RED ); + // not visited + ShadeMapElem( cnt, cnt2, MAP_SHADE_BLACK ); } } else { - // not visited - ShadeMapElem( cnt, cnt2, MAP_SHADE_BLACK ); - } - } - else - { - if( fShowAircraftFlag && !iCurrentMapSectorZ ) - { - if( !StrategicMap[ cnt + cnt2 * WORLD_MAP_X ].fEnemyAirControlled ) + if( fShowAircraftFlag && !iCurrentMapSectorZ ) { - // sector visited and air controlled - ShadeMapElem( cnt, cnt2, MAP_SHADE_LT_GREEN); - } - else - { - // sector visited but not air controlled - ShadeMapElem( cnt, cnt2, MAP_SHADE_LT_RED ); + if( !StrategicMap[ cnt + cnt2 * WORLD_MAP_X ].fEnemyAirControlled ) + { + // sector visited and air controlled + ShadeMapElem( cnt, cnt2, MAP_SHADE_LT_GREEN); + } + else + { + // sector visited but not air controlled + ShadeMapElem( cnt, cnt2, MAP_SHADE_LT_RED ); + } } } } diff --git a/Strategic/Map Screen Interface.cpp b/Strategic/Map Screen Interface.cpp index 25938819..71d91e36 100644 --- a/Strategic/Map Screen Interface.cpp +++ b/Strategic/Map Screen Interface.cpp @@ -7,7 +7,7 @@ #include "Render Dirty.h" #include "Font Control.h" #include "Assignments.h" - + #include "Soldier Control.h" #include "Overhead.h" #include "Squads.h" #include "Sound Control.h" @@ -55,6 +55,8 @@ #include "Render Fun.h" #endif +#include "connect.h" + //forward declarations of common classes to eliminate includes class OBJECTTYPE; class SOLDIERTYPE; @@ -5593,20 +5595,38 @@ BOOLEAN HandleTimeCompressWithTeamJackedInAndGearedToGo( void ) return( FALSE ); } - // select starting sector (A9 - Omerta) - ChangeSelectedMapSector( 9, 1, 0 ); - - // load starting sector - if ( !SetCurrentWorldSector( 9, 1, 0 ) ) + if (!is_networked) + // select starting sector (A9 - Omerta) + ChangeSelectedMapSector( 9, 1, 0 ); + + if (is_networked) { - return( FALSE ); - } + // load starting sector + if ( !SetCurrentWorldSector( gsMercArriveSectorX, gsMercArriveSectorY, 0 ) ) + { + return( FALSE ); + } - //Setup variables in the PBI for this first battle. We need to support the + gubPBSectorX = (UINT8)gsMercArriveSectorX; + gubPBSectorY = (UINT8)gsMercArriveSectorY; + } + else + { + // load starting sector + if ( !SetCurrentWorldSector( 9, 1, 0 ) ) + { + return( FALSE ); + } + + gubPBSectorX = 9; + gubPBSectorY = 1; + } + + + //Setup variables in the PBI for this first battle. We need to support the //non-persistant PBI in case the user goes to mapscreen. gfBlitBattleSectorLocator = TRUE; - gubPBSectorX = 9; - gubPBSectorY = 1; + gubPBSectorZ = 0; gubEnemyEncounterCode = ENTERING_ENEMY_SECTOR_CODE; diff --git a/Strategic/Merc Contract.cpp b/Strategic/Merc Contract.cpp index 64402c7f..ba7c25ad 100644 --- a/Strategic/Merc Contract.cpp +++ b/Strategic/Merc Contract.cpp @@ -41,6 +41,8 @@ #include "email.h" #endif +#include "GameSettings.h" +#include "connect.h" void CalculateMedicalDepositRefund( SOLDIERTYPE *pSoldier ); void NotifyPlayerOfMercDepartureAndPromptEquipmentPlacement( SOLDIERTYPE *pSoldier, BOOLEAN fAddRehireButton ); @@ -1488,7 +1490,16 @@ UINT32 GetHourWhenContractDone( SOLDIERTYPE *pSoldier ) UINT32 uiArriveHour; // Get the arrival hour - that will give us when they arrived.... - uiArriveHour = ( ( pSoldier->uiTimeSoldierWillArrive ) - ( ( ( pSoldier->uiTimeSoldierWillArrive ) / 1440 ) * 1440 ) ) / 60; + if (!is_networked) + { + uiArriveHour = ( ( pSoldier->uiTimeSoldierWillArrive ) - ( ( ( pSoldier->uiTimeSoldierWillArrive ) / 1440 ) * 1440 ) ) / 60; + } + else + { + // WANNE - MP: For multiplayer game, the merc arrive hour is always the game starting time which is now in multiplayer = GameStartingTime + FirstArrivalDelay + // Default value: 07:00 + uiArriveHour = (gGameExternalOptions.iGameStartingTime + gGameExternalOptions.iFirstArrivalDelay - NUM_SEC_IN_DAY) / 3600; + } return( uiArriveHour ); } diff --git a/Strategic/MilitiaSquads.cpp b/Strategic/MilitiaSquads.cpp index 0b70f75e..a5c21e2b 100644 --- a/Strategic/MilitiaSquads.cpp +++ b/Strategic/MilitiaSquads.cpp @@ -28,6 +28,7 @@ #include "Tactical Save.h" #endif +#include "connect.h" #include "MilitiaSquads.h" #include "Reinforcement.h" @@ -765,10 +766,18 @@ void DoMilitiaHelpFromAdjacentSectors( INT16 sMapX, INT16 sMapY ) } } - // If militia have been moved here, no reason to reset--just add them. If militia have not moved, then no strategic - // changes were made. Either case, this flag should be false. - gfStrategicMilitiaChangesMade = FALSE; + if (is_networked) + { + if (gfStrategicMilitiaChangesMade) + { + RemoveMilitiaFromTactical(); + if(is_server && MILITIA_ENABLED) + PrepareMilitiaForTactical(FALSE); + } } + + gfStrategicMilitiaChangesMade = FALSE; +} void MSCallBack( UINT8 ubResult ) { diff --git a/Strategic/PreBattle Interface.cpp b/Strategic/PreBattle Interface.cpp index 224854f7..1026d9e8 100644 --- a/Strategic/PreBattle Interface.cpp +++ b/Strategic/PreBattle Interface.cpp @@ -58,6 +58,7 @@ extern BOOLEAN gfExitViewer; extern BOOLEAN fZoomFlag; extern BOOLEAN fMapScreenBottomDirty; +#include "connect.h" BOOLEAN gfTacticalTraversal = FALSE; GROUP *gpTacticalTraversalGroup = NULL; @@ -696,7 +697,7 @@ void InitPreBattleInterface( GROUP *pBattleGroup, BOOLEAN fPersistantPBI ) if( gfAutomaticallyStartAutoResolve || !fRetreatAnOption || gubEnemyEncounterCode == ENEMY_AMBUSH_CODE || gubEnemyEncounterCode == BLOODCAT_AMBUSH_CODE || - gubEnemyEncounterCode == CREATURE_ATTACK_CODE ) + gubEnemyEncounterCode == CREATURE_ATTACK_CODE || is_client) { DisableButton( iPBButton[ 2 ] ); SetButtonFastHelpText( iPBButton[ 2 ], gzNonPersistantPBIText[ 9 ] ); diff --git a/Strategic/Queen Command.cpp b/Strategic/Queen Command.cpp index 18e245a8..16fb8642 100644 --- a/Strategic/Queen Command.cpp +++ b/Strategic/Queen Command.cpp @@ -49,6 +49,7 @@ extern BOOLEAN gfClearCreatureQuest; #endif +#include "connect.h" #include "Reinforcement.h" #include "MilitiaSquads.h" @@ -200,6 +201,9 @@ UINT8 NumEnemiesInSector( INT16 sSectorX, INT16 sSectorY ) pSector = &SectorInfo[ SECTOR( sSectorX, sSectorY ) ]; ubNumTroops = (UINT8)(pSector->ubNumAdmins + pSector->ubNumTroops + pSector->ubNumElites); + + if (is_networked) + ubNumTroops += numenemyLAN((UINT8)sSectorX,(UINT8)sSectorY ); //hayden pGroup = gpGroupList; while( pGroup ) @@ -885,7 +889,12 @@ DebugMsg (TOPIC_JA2,DBG_LEVEL_3,"QueenCommand"); if( pGroup->ubGroupSize <= iMaxEnemyGroupSize && pGroup->pEnemyGroup->ubNumTroops != pGroup->pEnemyGroup->ubTroopsInBattle && !gfPendingEnemies || pGroup->ubGroupSize > iMaxEnemyGroupSize || pGroup->pEnemyGroup->ubNumTroops > 50 || pGroup->pEnemyGroup->ubTroopsInBattle > 50 ) { - DoScreenIndependantMessageBox( L"Group troop counters are bad. What were the last 2-3 things to die, and how? Save game and send to KM with info!!!", MSG_BOX_FLAG_OK, NULL ); + // haydent + if (!is_client) + { + DoScreenIndependantMessageBox( L"Group troop counters are bad. What were the last 2-3 things to die, and how? Save game and send to KM with info!!!", MSG_BOX_FLAG_OK, NULL ); + + } } } #endif @@ -986,7 +995,8 @@ DebugMsg (TOPIC_JA2,DBG_LEVEL_3,"QueenCommand"); !pSector->ubNumTroops || !pSector->ubTroopsInBattle || pSector->ubNumTroops > 100 || pSector->ubTroopsInBattle > 32 ) { - DoScreenIndependantMessageBox( L"Sector troop counters are bad. What were the last 2-3 things to die, and how? Save game and send to KM with info!!!", MSG_BOX_FLAG_OK, NULL ); + if(!is_client)DoScreenIndependantMessageBox( L"Sector troop counters are bad. What were the last 2-3 things to die, and how? Save game and send to KM with info!!!", MSG_BOX_FLAG_OK, NULL ); + //disabled: hayden. } } #endif @@ -1195,6 +1205,12 @@ void AddPossiblePendingEnemiesToBattle() GROUP **pGroupInSectorList; static UINT8 ubPredefinedInsertionCode = 255; + // haydent + if ((is_client && !is_server) || !ENEMY_ENABLED) + { + return; + } + // check if no world is loaded if ( !gWorldSectorX && !gWorldSectorY && (gbWorldSectorZ == -1) ) return; diff --git a/Strategic/Reinforcement.cpp b/Strategic/Reinforcement.cpp index 3a629e2f..bc2479de 100644 --- a/Strategic/Reinforcement.cpp +++ b/Strategic/Reinforcement.cpp @@ -26,6 +26,7 @@ #include "Inventory Choosing.h" #endif +#include "connect.h" #include "Reinforcement.h" #include "MilitiaSquads.h" @@ -391,6 +392,12 @@ void AddPossiblePendingMilitiaToBattle() static UINT8 ubPredefinedInsertionCode = 255; static UINT8 ubPredefinedRank = 255; + // Haydent + if ((is_client && !is_server) || !MILITIA_ENABLED) + { + return; + } + // if( !PlayerMercsInSector( (UINT8)gWorldSectorX, (UINT8)gWorldSectorY, 0 ) || !CountAllMilitiaInSector( gWorldSectorX, gWorldSectorY ) // || !NumEnemiesInSector( gWorldSectorX, gWorldSectorY ) ) return; if( !PlayerMercsInSector( (UINT8)gWorldSectorX, (UINT8)gWorldSectorY, 0 ) diff --git a/Strategic/Strategic Event Handler.cpp b/Strategic/Strategic Event Handler.cpp index 548325e3..dfd8f269 100644 --- a/Strategic/Strategic Event Handler.cpp +++ b/Strategic/Strategic Event Handler.cpp @@ -33,6 +33,8 @@ #endif #include "BobbyRMailOrder.h" +#include "connect.h" + //forward declarations of common classes to eliminate includes class OBJECTTYPE; class SOLDIERTYPE; @@ -75,6 +77,14 @@ void BobbyRayPurchaseEventCallback( UINT8 ubOrderID ) sStandardMapPos = BOBBYR_SHIPPING_DEST_GRIDNO; + // Haydent + if(gpNewBobbyrShipments[ ubOrderID ].fActive && is_client) + { + DropOffItemsInSector( ubOrderID );//hayden + return; + } + + // if the delivery is for meduna, drop the items off there instead if( gpNewBobbyrShipments[ ubOrderID ].fActive && gpNewBobbyrShipments[ ubOrderID ].ubDeliveryLoc == BR_MEDUNA ) { diff --git a/Strategic/Strategic Movement.cpp b/Strategic/Strategic Movement.cpp index da000751..1298cd3a 100644 --- a/Strategic/Strategic Movement.cpp +++ b/Strategic/Strategic Movement.cpp @@ -50,7 +50,7 @@ #endif #include "MilitiaSquads.h" - +#include "connect.h" //forward declarations of common classes to eliminate includes class OBJECTTYPE; class SOLDIERTYPE; @@ -922,7 +922,7 @@ void PrepareForPreBattleInterface( GROUP *pPlayerDialogGroup, GROUP *pInitiating pSoldier = pPlayer->pSoldier; if ( pSoldier->stats.bLife >= OKLIFE && !( pSoldier->flags.uiStatusFlags & SOLDIER_VEHICLE ) && - !AM_A_ROBOT( pSoldier ) && !AM_AN_EPC( pSoldier ) ) + !AM_A_ROBOT( pSoldier ) && !AM_AN_EPC( pSoldier ) && !is_client ) { ubMercsInGroup[ ubNumMercs ] = pSoldier->ubID; ubNumMercs++; diff --git a/Strategic/Strategic.vcproj b/Strategic/Strategic.vcproj index d5a66612..c7a712fa 100644 --- a/Strategic/Strategic.vcproj +++ b/Strategic/Strategic.vcproj @@ -22,7 +22,7 @@ flags.uiStatusFlags & SOLDIER_VEHICLE)) { - fShowMapInventoryPool = TRUE; - CreateDestroyMapInventoryPoolButtons( TRUE ); - } - if(!fShowInventoryFlag) - { - fShowInventoryFlag = TRUE; - } - if( fCtrl ) - { - //CHRISL: pickup all items to vehicle - if ( UsingNewInventorySystem() == true && fShowInventoryFlag && fShowMapInventoryPool && !(gTacticalStatus.fEnemyInSector) && gGameExternalOptions.fVehicleInventory && (pSoldier->flags.uiStatusFlags & SOLDIER_VEHICLE)) + for(unsigned int i = 0; iinv[x].exists() == true) { - if(vehicleInv[x] == FALSE) + if(pSoldier->inv[x].usItem != pInventoryPoolList[i].object.usItem) continue; - if(pSoldier->inv[x].exists() == true) - { - if(pSoldier->inv[x].usItem != pInventoryPoolList[i].object.usItem) - continue; - else - pInventoryPoolList[i].object.AddObjectsToStack(pSoldier->inv[x], -1, pSoldier, x); - } else - pInventoryPoolList[i].object.MoveThisObjectTo(pSoldier->inv[x], -1, pSoldier, x); - if(pInventoryPoolList[i].object.ubNumberOfObjects < 0) - { - //RemoveItemFromWorld(i); - break; - } + pInventoryPoolList[i].object.AddObjectsToStack(pSoldier->inv[x], -1, pSoldier, x); + } + else + pInventoryPoolList[i].object.MoveThisObjectTo(pSoldier->inv[x], -1, pSoldier, x); + if(pInventoryPoolList[i].object.ubNumberOfObjects < 0) + { + //RemoveItemFromWorld(i); + break; } } - fTeamPanelDirty = TRUE; - fMapPanelDirty = TRUE; - fInterfacePanelDirty = DIRTYLEVEL2; } + fTeamPanelDirty = TRUE; + fMapPanelDirty = TRUE; + fInterfacePanelDirty = DIRTYLEVEL2; } } - else + } + else + { + //CHRISL: drop all items + if ( bSelectedInfoChar != -1 && fShowInventoryFlag && fShowMapInventoryPool && !(gTacticalStatus.fEnemyInSector) ) { - //CHRISL: drop all items - if ( bSelectedInfoChar != -1 && fShowInventoryFlag && fShowMapInventoryPool && !(gTacticalStatus.fEnemyInSector) ) + for(int i = BODYPOSFINAL; iinv[i].exists() == true) { - if(pSoldier->inv[i].exists() == true) - { - AutoPlaceObjectInInventoryStash(&pSoldier->inv[i], pSoldier->sGridNo); - DeleteObj(&pSoldier->inv[i]); - } - fTeamPanelDirty = TRUE; - fMapPanelDirty = TRUE; - fInterfacePanelDirty = DIRTYLEVEL2; + AutoPlaceObjectInInventoryStash(&pSoldier->inv[i], pSoldier->sGridNo); + DeleteObj(&pSoldier->inv[i]); + } + fTeamPanelDirty = TRUE; + fMapPanelDirty = TRUE; + fInterfacePanelDirty = DIRTYLEVEL2; } } } @@ -6406,6 +6465,15 @@ void GetMapKeyboardInput( UINT32 *puiNewEvent ) } break; + // haydent + case 'k': + if (fAlt) + { + if (is_networked) + kick_player(); + } + break; + case 'l': if( fAlt ) { @@ -7281,11 +7349,26 @@ void PollLeftButtonInMapView( UINT32 *puiNewEvent ) // ignore left clicks in the map screen if: // game just started or we're in the prebattle interface or if we are about to hit pre-battle - if ( ( gTacticalStatus.fDidGameJustStart == TRUE ) || - ( gfPreBattleInterfaceActive == TRUE ) || - ( fDisableMapInterfaceDueToBattle == TRUE ) ) + + + if (is_networked) { - return; + if ( /*( gTacticalStatus.fDidGameJustStart == TRUE ) || */ + // commented out to allow heli drop off change @/b4 start ;) + ( gfPreBattleInterfaceActive == TRUE ) || + ( fDisableMapInterfaceDueToBattle == TRUE ) ) + { + return; + } + } + else + { + if ( ( gTacticalStatus.fDidGameJustStart == TRUE ) || + ( gfPreBattleInterfaceActive == TRUE ) || + ( fDisableMapInterfaceDueToBattle == TRUE ) ) + { + return; + } } @@ -7642,9 +7725,10 @@ void BltCharInvPanel() } else { - InitInventorySoldier(gMapScreenInvPocketXY, MAPInvMoveCallback, MAPInvClickCallback, FALSE, FALSE); //InitializeInvPanelCoordsOld(); + InitInventorySoldier(gMapScreenInvPocketXY, MAPInvMoveCallback, MAPInvClickCallback, FALSE, FALSE); } + Blt8BPPDataTo16BPPBufferTransparent( pDestBuf, uiDestPitchBYTES, hCharListHandle, PLAYER_INFO_X, PLAYER_INFO_Y, disOpt); UnLockVideoSurface( guiSAVEBUFFER ); @@ -11813,6 +11897,11 @@ void TellPlayerWhyHeCantCompressTime( void ) // no mercs hired, ever DoMapMessageBox( MSG_BOX_BASIC_STYLE, pMapScreenJustStartedHelpText[ 0 ], MAP_SCREEN, MSG_BOX_FLAG_OK, MapScreenDefaultOkBoxCallback ); } + // WANNE - MP: It is forbidden to compress time in multiplayer + else if (is_networked) + { + ScreenMsg( FONT_LTGREEN, MSG_CHAT, L"You cannot compress time in multiplayer game. Press '3' to start the battle."); + } else if ( !AnyUsableRealMercenariesOnTeam() ) { // no usable mercs left on team @@ -13515,13 +13604,36 @@ BOOLEAN CanMoveBullseyeAndClickedOnIt( INT16 sMapX, INT16 sMapY ) // if in airspace mode, and not plotting paths if( ( fShowAircraftFlag == TRUE ) && ( bSelectedDestChar == -1 ) && ( fPlotForHelicopter == FALSE ) ) { - // don't allow moving bullseye until after initial arrival - if ( gTacticalStatus.fDidGameJustStart == FALSE ) + if (is_networked) { - // if he clicked on the bullseye, and we're on the surface level - if ( ( sMapX == gsMercArriveSectorX ) && ( sMapY == gsMercArriveSectorY ) && ( iCurrentMapSectorZ == 0 ) ) + // haydent + if (!is_server && !is_client) { - return( TRUE ); + // if he clicked on the bullseye, and we're on the surface level + if ( ( sMapX == gsMercArriveSectorX ) && ( sMapY == gsMercArriveSectorY ) && ( iCurrentMapSectorZ == 0 ) ) + { + return( TRUE ); + } + } + + // haydent + else if(is_server) + { + ScreenMsg( FONT_LTGREEN, MSG_CHAT, MPServerMessage[9] ); + } + else if(is_client) + ScreenMsg( FONT_LTGREEN, MSG_CHAT, MPClientMessage[38] ); + } + else + { + // don't allow moving bullseye until after initial arrival + if ( gTacticalStatus.fDidGameJustStart == FALSE ) + { + // if he clicked on the bullseye, and we're on the surface level + if ( ( sMapX == gsMercArriveSectorX ) && ( sMapY == gsMercArriveSectorY ) && ( iCurrentMapSectorZ == 0 ) ) + { + return( TRUE ); + } } } } diff --git a/Strategic/strategicmap.cpp b/Strategic/strategicmap.cpp index d660d9a4..ec727a09 100644 --- a/Strategic/strategicmap.cpp +++ b/Strategic/strategicmap.cpp @@ -17,7 +17,7 @@ #include #include "jascreens.h" #include "worlddef.h" - + #include "Soldier Control.h" #include "overhead.h" #include "interface panels.h" #include "isometric utils.h" @@ -106,6 +106,7 @@ #include "cursors.h" #endif +#include "connect.h" //hayden added alot ""'s to get around client spawing random/different placed AI #include "SaveLoadGame.h" //forward declarations of common classes to eliminate includes @@ -1746,7 +1747,15 @@ BOOLEAN SetCurrentWorldSector( INT16 sMapX, INT16 sMapY, INT8 bMapZ ) SetPendingNewScreen(GAME_SCREEN); if( !NumEnemyInSector( ) ) { - PrepareEnemyForSectorBattle(); + if (is_networked) + { + if(is_server && ENEMY_ENABLED) + PrepareEnemyForSectorBattle(); + } + else + { + PrepareEnemyForSectorBattle(); + } } for (int i=0; ifEnemyControlled ) && ( pSAMStrategicMap->bSAMCondition >= MIN_CONDITION_FOR_SAM_SITE_TO_WORK ) ) { - fEnemyControlsAir = TRUE; + if (is_networked) + { + fEnemyControlsAir = FALSE; // disable SAM airspace restrictions... + } + else + { + fEnemyControlsAir = TRUE; + } } else { @@ -5481,6 +5546,11 @@ BOOLEAN CheckAndHandleUnloadingOfCurrentWorld() return FALSE; } + if(is_client)//hayden - if multiplayer dont kick from level, allow spectate. + { + return FALSE; + } + if( gTacticalStatus.fDidGameJustStart && gWorldSectorX == 9 && gWorldSectorY == 1 && !gbWorldSectorZ ) { return FALSE; diff --git a/Tactical/Bullets.h b/Tactical/Bullets.h index d8a7bbdc..0a9c3954 100644 --- a/Tactical/Bullets.h +++ b/Tactical/Bullets.h @@ -17,8 +17,15 @@ #define BULLET_FLAG_FLAME 0x0080 #define BULLET_FLAG_TRACER 0x0100 +//afp-start calculate line points between two point +#define BULLET_TRACER_MAX_LENGTH 60 +void PointsPath(int sx1, int sy1, int ex2, int ey2) ; +//afp-end typedef struct { + //afp-start this structure keeps tracers points + LEVELNODE* pNodes[BULLET_TRACER_MAX_LENGTH]; + //afp-end INT32 iBullet; UINT8 ubFirerID; UINT8 ubTargetID; diff --git a/Tactical/Civ Quotes.cpp b/Tactical/Civ Quotes.cpp index fe05e915..9f36f0db 100644 --- a/Tactical/Civ Quotes.cpp +++ b/Tactical/Civ Quotes.cpp @@ -33,7 +33,7 @@ #include "Strategic Mines.h" #include "Random.h" #endif - +#include "connect.h" #define DIALOGUE_DEFAULT_WIDTH 200 #define EXTREAMLY_LOW_TOWN_LOYALTY 20 @@ -242,7 +242,9 @@ void ShutDownQuoteBox( BOOLEAN fForce ) // do we need to do anything at the end of the civ quote? if ( gCivQuoteData.pCiv && gCivQuoteData.pCiv->aiData.bAction == AI_ACTION_OFFER_SURRENDER ) { - DoMessageBox( MSG_BOX_BASIC_STYLE, Message[ STR_SURRENDER ], GAME_SCREEN, ( UINT8 )MSG_BOX_FLAG_YESNO, SurrenderMessageBoxCallBack, NULL ); +// Haydent + if(!is_client)DoMessageBox( MSG_BOX_BASIC_STYLE, Message[ STR_SURRENDER ], GAME_SCREEN, ( UINT8 )MSG_BOX_FLAG_YESNO, SurrenderMessageBoxCallBack, NULL ); + else ScreenMsg( FONT_LTGREEN, MSG_CHAT, MPClientMessage[39] ); } } } diff --git a/Tactical/Dialogue Control.cpp b/Tactical/Dialogue Control.cpp index 340e7d2f..06a3e2c7 100644 --- a/Tactical/Dialogue Control.cpp +++ b/Tactical/Dialogue Control.cpp @@ -57,6 +57,8 @@ #include "qarray.h" #endif +#include "connect.h" + //forward declarations of common classes to eliminate includes class OBJECTTYPE; class SOLDIERTYPE; @@ -1288,6 +1290,11 @@ BOOLEAN TacticalCharacterDialogueWithSpecialEventEx( SOLDIERTYPE *pSoldier, UINT BOOLEAN TacticalCharacterDialogue( SOLDIERTYPE *pSoldier, UINT16 usQuoteNum ) { +// Haydent + if(is_client) + { + return(FALSE); //somewhere amongst all this it causes a puase of merc movement while making the quote which throws out the movement sync between clients... : hayden. + } if ( pSoldier->ubProfile == NO_PROFILE ) { return( FALSE ); diff --git a/Tactical/Handle Doors.cpp b/Tactical/Handle Doors.cpp index ba2be47c..f5c62f6d 100644 --- a/Tactical/Handle Doors.cpp +++ b/Tactical/Handle Doors.cpp @@ -34,7 +34,10 @@ #include "Isometric Utils.h" #include "ai.h" #include "Soldier macros.h" + #include "Event Pump.h" #endif +#include "fresh_header.h" +#include "connect.h" BOOLEAN gfSetPerceivedDoorState = FALSE; @@ -942,6 +945,7 @@ BOOLEAN HandleOpenableStruct( SOLDIERTYPE *pSoldier, INT16 sGridNo, STRUCTURE *p if ( fDoor ) { HandleDoorChangeFromGridNo( pSoldier, sGridNo, FALSE ); + if(is_client)send_door( pSoldier, sGridNo, FALSE ); } else { diff --git a/Tactical/Handle Items.cpp b/Tactical/Handle Items.cpp index 5796c8f7..c9f41c4e 100644 --- a/Tactical/Handle Items.cpp +++ b/Tactical/Handle Items.cpp @@ -1,3 +1,4 @@ +#include "connect.h" #ifdef PRECOMPILEDHEADERS #include "Tactical All.h" #else @@ -555,15 +556,21 @@ INT32 HandleItem( SOLDIERTYPE *pSoldier, INT16 sGridNo, INT8 bLevel, UINT16 usHa if ( pSoldier->sSpreadLocations[ 0 ] != 0 ) { SendBeginFireWeaponEvent( pSoldier, pSoldier->sSpreadLocations[ 0 ] ); + if(is_server || (is_client && pSoldier->ubID <20) ) send_fire( pSoldier, pSoldier->sSpreadLocations[ 0 ] ); + + ScreenMsg( FONT_MCOLOR_LTYELLOW, MSG_INTERFACE, L"Handle Items.cpp: SendBeginFireWeaponEvent" ); } else { SendBeginFireWeaponEvent( pSoldier, sTargetGridNo ); + if(is_server || (is_client && pSoldier->ubID <20) ) send_fire( pSoldier, sTargetGridNo ); + ScreenMsg( FONT_MCOLOR_LTYELLOW, MSG_INTERFACE, L"Handle Items.cpp: SendBeginFireWeaponEvent" ); } } else { SendBeginFireWeaponEvent( pSoldier, sTargetGridNo ); + if(is_server || (is_client && pSoldier->ubID <20) ) send_fire( pSoldier, sTargetGridNo ); } // ATE: Here to make cursor go back to move after LAW shot... @@ -1367,6 +1374,7 @@ INT32 HandleItem( SOLDIERTYPE *pSoldier, INT16 sGridNo, INT8 bLevel, UINT16 usHa { SendBeginFireWeaponEvent( pSoldier, sTargetGridNo ); + if(is_server || (is_client && pSoldier->ubID <20) ) send_fire( pSoldier, sTargetGridNo ); } diff --git a/Tactical/Handle UI.cpp b/Tactical/Handle UI.cpp index dbea4acc..68ba3b45 100644 --- a/Tactical/Handle UI.cpp +++ b/Tactical/Handle UI.cpp @@ -1,3 +1,4 @@ +#include "connect.h" #ifdef PRECOMPILEDHEADERS #include "Tactical All.h" #include "BuildDefines.h" @@ -88,6 +89,7 @@ #include "Soldier Control.h" #endif +#include "teamturns.h" //extern BOOLEAN gfDisplayFullCountRingBurst; extern UINT16 PickSoldierReadyAnimation( SOLDIERTYPE *pSoldier, BOOLEAN fEndReady ); @@ -1196,7 +1198,22 @@ UINT32 UIHandleEndTurn( UI_EVENT *pUIEvent ) } // End our turn! - EndTurn( gbPlayerNum + 1 ); + if (is_server || !is_client) + { + EndTurn( gbPlayerNum + 1 ); + } + if(!is_server && is_client) + { + + if (INTERRUPT_QUEUED) + { + EndTurn( gbPlayerNum + 1 );//is ending interrupt instead + } + else + { + send_EndTurn( netbTeam+1 );//for sending next netbteam rather than next local team + } + } } return( GAME_SCREEN ); @@ -5842,18 +5859,20 @@ void UnSetUIBusy( UINT8 ubID ) { if ( gfUserTurnRegionActive && (gTacticalStatus.uiFlags & INCOMBAT ) && ( gTacticalStatus.uiFlags & TURNBASED ) && ( gTacticalStatus.ubCurrentTeam == gbPlayerNum ) ) { - if ( !gTacticalStatus.fUnLockUIAfterHiddenInterrupt ) { - if ( gusSelectedSoldier == ubID ) + if ( !gTacticalStatus.fUnLockUIAfterHiddenInterrupt ) { - guiPendingOverrideEvent = LA_ENDUIOUTURNLOCK; - HandleTacticalUI( ); + if ( gusSelectedSoldier == ubID && (gTacticalStatus.ubCurrentTeam == OUR_TEAM || !is_networked))// now that mp + { + guiPendingOverrideEvent = LA_ENDUIOUTURNLOCK; + HandleTacticalUI( ); - // Set grace period... - gTacticalStatus.uiTactialTurnLimitClock = GetJA2Clock( ); + // Set grace period... + gTacticalStatus.uiTactialTurnLimitClock = GetJA2Clock( ); + } } + // player getting control back so reset all muzzle flashes } - // player getting control back so reset all muzzle flashes } } diff --git a/Tactical/Interface Items.cpp b/Tactical/Interface Items.cpp index b2643076..3ae45821 100644 --- a/Tactical/Interface Items.cpp +++ b/Tactical/Interface Items.cpp @@ -6572,7 +6572,6 @@ void DeleteItemStackPopup( ) //CHRISL: if neither item or sector stack popups are open, just return. if(!gfInItemStackPopup && !gfInSectorStackPopup) return; - //Remove DeleteVideoObjectFromIndex( guiItemPopupBoxes ); diff --git a/Tactical/Interface Panels.cpp b/Tactical/Interface Panels.cpp index d1b0f422..ebc198ff 100644 --- a/Tactical/Interface Panels.cpp +++ b/Tactical/Interface Panels.cpp @@ -7019,4 +7019,3 @@ void GoToMapScreenFromTactical( void ) - diff --git a/Tactical/Interface.cpp b/Tactical/Interface.cpp index c5c5eab9..23cc3805 100644 --- a/Tactical/Interface.cpp +++ b/Tactical/Interface.cpp @@ -58,6 +58,7 @@ #include "message.h" #endif +#include "connect.h" //const UINT32 INTERFACE_START_X = 0; //const UINT32 INTERFACE_START_Y = ( SCREEN_HEIGHT - INTERFACE_HEIGHT ); //const UINT32 INV_INTERFACE_START_Y = ( SCREEN_HEIGHT - INV_INTERFACE_HEIGHT ); @@ -2928,10 +2929,11 @@ void EndUIMessage( ) #define PLAYER_TEAM_TIMER_INTTERUPT_GRACE ( 15000 / PLAYER_TEAM_TIMER_SEC_PER_TICKS ) #define PLAYER_TEAM_TIMER_GRACE_PERIOD 1000 -#define PLAYER_TEAM_TIMER_SEC_PER_TICKS 100 +//#define PLAYER_TEAM_TIMER_SEC_PER_TICKS 100 +int PLAYER_TEAM_TIMER_SEC_PER_TICKS = 100;//hayden #define PLAYER_TEAM_TIMER_TICKS_PER_OK_MERC ( 15000 / PLAYER_TEAM_TIMER_SEC_PER_TICKS ) #define PLAYER_TEAM_TIMER_TICKS_PER_NOTOK_MERC ( 5000 / PLAYER_TEAM_TIMER_SEC_PER_TICKS ) -#define PLAYER_TEAM_TIMER_TICKS_FROM_END_TO_START_BEEP ( 5000 / PLAYER_TEAM_TIMER_SEC_PER_TICKS ) +#define PLAYER_TEAM_TIMER_TICKS_FROM_END_TO_START_BEEP ( (5000 / PLAYER_TEAM_TIMER_SEC_PER_TICKS)*1.15 ) #define PLAYER_TEAM_TIMER_TIME_BETWEEN_BEEPS ( 500 ) #define PLAYER_TEAM_TIMER_TICKS_PER_ENEMY ( 2000 / PLAYER_TEAM_TIMER_SEC_PER_TICKS ) @@ -3289,7 +3291,8 @@ void HandleTopMessages( ) if ( TIMECOUNTERDONE( giTimerTeamTurnUpdate, PLAYER_TEAM_TIMER_SEC_PER_TICKS ) ) { RESETTIMECOUNTER( giTimerTeamTurnUpdate, PLAYER_TEAM_TIMER_SEC_PER_TICKS ); - + if(!is_networked)//hayden - stop clients from updating enemy progress bar... //could have another param in here when get coop going + { // Update counter.... if ( gTacticalStatus.usTactialTurnLimitCounter < gTacticalStatus.usTactialTurnLimitMax ) { @@ -3301,6 +3304,8 @@ void HandleTopMessages( ) { gTacticalStatus.usTactialTurnLimitCounter = ( ( gubProgCurEnemy ) * PLAYER_TEAM_TIMER_TICKS_PER_ENEMY ); } + + } CreateTopMessage( gTopMessage.uiSurface, gTacticalStatus.ubTopMessageType, gTacticalStatus.zTopMessageString ); } @@ -3544,6 +3549,9 @@ void InitPlayerUIBar( BOOLEAN fInterrupt ) return; } + if (is_networked) + gTacticalStatus.usTactialTurnLimitMax = 0;//hayden , cheap hack, always calc time... + // OK, calculate time.... if ( !fInterrupt || gTacticalStatus.usTactialTurnLimitMax == 0 ) { diff --git a/Tactical/Item Types.h b/Tactical/Item Types.h index 768261b5..f324fd71 100644 --- a/Tactical/Item Types.h +++ b/Tactical/Item Types.h @@ -223,6 +223,7 @@ bool IsSlotASmallPocket(int slot); extern std::list LBEArray; + //do not alter or saves will break, create new defines if the size changes #define OLD_MAX_ATTACHMENTS_101 4 #define OLD_MAX_OBJECTS_PER_SLOT_101 8 diff --git a/Tactical/LOS.cpp b/Tactical/LOS.cpp index 6472ad6e..af575cae 100644 --- a/Tactical/LOS.cpp +++ b/Tactical/LOS.cpp @@ -1,3 +1,4 @@ +#include "connect.h" #ifdef PRECOMPILEDHEADERS #include "Tactical All.h" #else @@ -41,7 +42,8 @@ #include "Quests.h" #include "items.h" #endif - +#include "fresh_header.h" +#include "test_space.h" //forward declarations of common classes to eliminate includes class OBJECTTYPE; class SOLDIERTYPE; @@ -2325,7 +2327,23 @@ BOOLEAN BulletHitMerc( BULLET * pBullet, STRUCTURE * pStructure, BOOLEAN fIntend } // handle hit! Handle damage before deleting the bullet though - WeaponHit( SWeaponHit.usSoldierID, SWeaponHit.usWeaponIndex, SWeaponHit.sDamage, SWeaponHit.sBreathLoss, SWeaponHit.usDirection, SWeaponHit.sXPos, SWeaponHit.sYPos, SWeaponHit.sZPos, SWeaponHit.sRange, SWeaponHit.ubAttackerID, SWeaponHit.fHit, SWeaponHit.ubSpecial, SWeaponHit.ubLocation ); + //hayden + if(SWeaponHit.ubAttackerID < 20 ||(is_server && SWeaponHit.ubAttackerID < 120)|| !is_client ) // 124 last possible ai + { + if(is_client) + SWeaponHit.sDamage=(INT16)(SWeaponHit.sDamage * DAMAGE_MULTIPLIER); // adjust damage from external variable //hayden + + WeaponHit( SWeaponHit.usSoldierID, SWeaponHit.usWeaponIndex, SWeaponHit.sDamage, SWeaponHit.sBreathLoss, SWeaponHit.usDirection, SWeaponHit.sXPos, SWeaponHit.sYPos, SWeaponHit.sZPos, SWeaponHit.sRange, SWeaponHit.ubAttackerID, SWeaponHit.fHit, SWeaponHit.ubSpecial, SWeaponHit.ubLocation ); + + + if(is_server || (is_client && SWeaponHit.ubAttackerID <20) ) + { + SWeaponHit.fStopped=fStopped; + SWeaponHit.iBullet=pBullet->iBullet; + + send_hit( &SWeaponHit ); + } + } if (fStopped) { @@ -2384,17 +2402,48 @@ void BulletHitStructure( BULLET * pBullet, UINT16 usStructureID, INT32 iImpact, SStructureHit.usStructureID = usStructureID; SStructureHit.iImpact = iImpact; SStructureHit.iBullet = pBullet->iBullet; + + if (is_networked) + SStructureHit.fStopped = fStopped; + + //hayden + if(is_client) + send_hitstruct(&SStructureHit); StructureHit( SStructureHit.iBullet, SStructureHit.usWeaponIndex, SStructureHit.bWeaponStatus, SStructureHit.ubAttackerID, SStructureHit.sXPos, SStructureHit.sYPos, SStructureHit.sZPos, SStructureHit.usStructureID, SStructureHit.iImpact, fStopped ); } void BulletHitWindow( BULLET *pBullet, INT16 sGridNo, UINT16 usStructureID, BOOLEAN fBlowWindowSouth ) { + if (is_networked) + { + EV_S_WINDOWHIT SWindowHit; + SWindowHit.sGridNo = sGridNo; + SWindowHit.usStructureID = usStructureID; + SWindowHit.fBlowWindowSouth = fBlowWindowSouth; + SWindowHit.fLargeForce = FALSE; + SWindowHit.iBullet = pBullet->iBullet; + SWindowHit.ubAttackerID=pBullet->pFirer->ubID; + //hayden + if(is_client) + send_hitwindow(&SWindowHit); + } + WindowHit( sGridNo, usStructureID, fBlowWindowSouth, FALSE ); } void BulletMissed( BULLET *pBullet, SOLDIERTYPE * pFirer ) { + if (is_networked) + { + EV_S_MISS SMiss; + SMiss.iBullet=pBullet->iBullet; + SMiss.ubAttackerID=pFirer->ubID; + //hayden + if(is_client) + send_miss(&SMiss); + } + ShotMiss( pFirer->ubID, pBullet->iBullet ); } @@ -3482,7 +3531,15 @@ INT8 FireBullet( SOLDIERTYPE * pFirer, BULLET * pBullet, BOOLEAN fFake ) } else { - pBullet->usClockTicksPerUpdate = (Weapon[ pFirer->usAttackingWeapon ].ubBulletSpeed + GetBulletSpeedBonus(&pFirer->inv[pFirer->ubAttackingHand]) ) / 10; + //afp-start //always a fast bullet + if ( pBullet->usFlags & ( BULLET_FLAG_CREATURE_SPIT | BULLET_FLAG_KNIFE | BULLET_FLAG_MISSILE | BULLET_FLAG_SMALL_MISSILE | BULLET_FLAG_TANK_CANNON | BULLET_FLAG_FLAME /*| BULLET_FLAG_TRACER*/ ) ) + pBullet->usClockTicksPerUpdate = (Weapon[ pFirer->usAttackingWeapon ].ubBulletSpeed + GetBulletSpeedBonus(&pFirer->inv[pFirer->ubAttackingHand]) ) / 10; + else + if (gGameExternalOptions.gbBulletTracer) + pBullet->usClockTicksPerUpdate = (Weapon[ pFirer->usAttackingWeapon ].ubBulletSpeed + GetBulletSpeedBonus(&pFirer->inv[pFirer->ubAttackingHand]) ) / 10; + else + pBullet->usClockTicksPerUpdate = 1; + //afp-end } //DebugMsg(TOPIC_JA2,DBG_LEVEL_3,String("FireBullet: handle flags")); @@ -3773,6 +3830,8 @@ INT8 FireBulletGivenTarget( SOLDIERTYPE * pFirer, FLOAT dEndX, FLOAT dEndY, FLOA // // this is an error!! // ubLoop = ubLoop; // } + //hayden + if(is_client)send_bullet( pBullet, usHandItem ); FireBullet( pFirer, pBullet, FALSE ); } } @@ -3896,7 +3955,10 @@ void MoveBullet( INT32 iBullet ) // NB remove bullet only flags a bullet for deletion; we still have access to the // information in the structure RemoveBullet( pBullet->iBullet ); - BulletMissed( pBullet, pBullet->pFirer ); + + if(ENABLE_COLLISION) + BulletMissed( pBullet, pBullet->pFirer );//only if local origin + return; } @@ -3940,7 +4002,10 @@ void MoveBullet( INT32 iBullet ) { fIntended = FALSE; } - + //check for structures at target, and calc chance to hit + //hayden, disable any structure t avoid collision + if(ENABLE_COLLISION) + { while( pStructure ) { if (pStructure->fFlags & ALWAYS_CONSIDER_HIT) @@ -4140,6 +4205,7 @@ void MoveBullet( INT32 iBullet ) pStructure = pStructure->pNext; } + } // check to see if any soldiers are nearby; those soldiers // have their near-miss value incremented if (pMapElement->ubAdjacentSoldierCnt > 0) @@ -4226,6 +4292,9 @@ void MoveBullet( INT32 iBullet ) // check for collision with the ground iCurrAboveLevelZ = FIXEDPT_TO_INT32( pBullet->qCurrZ - qLandHeight ); +//hayden not hit ground + if(ENABLE_COLLISION) + { if (iCurrAboveLevelZ < 0) { // ground is in the way! @@ -4233,6 +4302,7 @@ void MoveBullet( INT32 iBullet ) BulletHitStructure( pBullet, INVALID_STRUCTURE_ID, 0, pBullet->pFirer, pBullet->qCurrX, pBullet->qCurrY, pBullet->qCurrZ, TRUE ); return; } + } // check for the existence of structures if (iNumLocalStructures == 0 && !pRoofStructure) { // no structures in this tile, AND THAT INCLUDES ROOFS! :-) @@ -4280,6 +4350,9 @@ void MoveBullet( INT32 iBullet ) // special coding (compared with other versions above) to deal with // bullets hitting the ground +//hayden, stop hit ground + if(ENABLE_COLLISION) + { if (pBullet->qCurrZ + pBullet->qIncrZ * iStepsToTravel < qLandHeight) { iStepsToTravel = __min( iStepsToTravel, abs( (pBullet->qCurrZ - qLandHeight) / pBullet->qIncrZ ) ); @@ -4291,6 +4364,7 @@ void MoveBullet( INT32 iBullet ) BulletHitStructure( pBullet, INVALID_STRUCTURE_ID, 0, pBullet->pFirer, pBullet->qCurrX, pBullet->qCurrY, pBullet->qCurrZ, TRUE ); return; } + } if (( pBullet->usFlags & ( BULLET_FLAG_MISSILE | BULLET_FLAG_SMALL_MISSILE | BULLET_FLAG_TANK_CANNON | BULLET_FLAG_FLAME | BULLET_FLAG_CREATURE_SPIT /*| BULLET_FLAG_TRACER*/ ) ) || fTracer == TRUE) { @@ -4544,7 +4618,8 @@ void MoveBullet( INT32 iBullet ) { pBullet->qCurrX += pBullet->qIncrX; pBullet->qCurrY += pBullet->qIncrY; - if (pRoofStructure) +//no hit on lan//pRoofStructure//hayden + if (is_networked && pRoofStructure) { qLastZ = pBullet->qCurrZ; pBullet->qCurrZ += pBullet->qIncrZ; @@ -4609,7 +4684,7 @@ void MoveBullet( INT32 iBullet ) { // bullet outside of world! RemoveBullet( pBullet->iBullet ); - BulletMissed( pBullet, pBullet->pFirer ); + if(ENABLE_COLLISION)BulletMissed( pBullet, pBullet->pFirer );//hayden: only play event if local return; } diff --git a/Tactical/Merc Hiring.cpp b/Tactical/Merc Hiring.cpp index c5628fda..1f8391cf 100644 --- a/Tactical/Merc Hiring.cpp +++ b/Tactical/Merc Hiring.cpp @@ -59,7 +59,7 @@ #include "Quests.h" #include "GameSettings.h" #endif - +#include "connect.h" //forward declarations of common classes to eliminate includes class OBJECTTYPE; class SOLDIERTYPE; @@ -102,7 +102,7 @@ INT8 HireMerc( MERC_HIRE_STRUCT *pHireMerc) if( ( pMerc->bMercStatus != 0 ) && (pMerc->bMercStatus != MERC_ANNOYED_BUT_CAN_STILL_CONTACT ) && ( pMerc->bMercStatus != MERC_HIRED_BUT_NOT_ARRIVED_YET ) ) return( MERC_HIRE_FAILED ); - if( NumberOfMercsOnPlayerTeam() >= 18 ) + if( NumberOfMercsOnPlayerTeam() >= 18 || (is_client && NumberOfMercsOnPlayerTeam() >= MAX_MERCS)) //hayden, 7 member team limit setable in ini return( MERC_HIRE_OVER_18_MERCS_HIRED ); // ATE: if we are to use landing zone, update to latest value @@ -123,6 +123,9 @@ INT8 HireMerc( MERC_HIRE_STRUCT *pHireMerc) MercCreateStruct.bSectorZ = pHireMerc->bSectorZ; MercCreateStruct.bTeam = SOLDIER_CREATE_AUTO_TEAM; MercCreateStruct.fCopyProfileItemsOver= pHireMerc->fCopyProfileItemsOver; + + if(!ALLOW_EQUIP && is_networked) + MercCreateStruct.fCopyProfileItemsOver=0;//hayden : server overide if ( !TacticalCreateSoldier( &MercCreateStruct, &iNewIndex ) ) { @@ -192,36 +195,50 @@ INT8 HireMerc( MERC_HIRE_STRUCT *pHireMerc) //Set the type of merc - if( DidGameJustStart() ) + if (!is_networked) { - // Set time of initial merc arrival in minutes - pHireMerc->uiTimeTillMercArrives = ( gGameExternalOptions.iGameStartingTime + gGameExternalOptions.iFirstArrivalDelay ) / NUM_SEC_IN_MIN; + if( DidGameJustStart() ) + { + pHireMerc->uiTimeTillMercArrives = ( gGameExternalOptions.iGameStartingTime + gGameExternalOptions.iFirstArrivalDelay ) / NUM_SEC_IN_MIN; - // Set insertion for first time in chopper - pHireMerc->ubInsertionCode = INSERTION_CODE_CHOPPER; + // Set insertion for first time in chopper + pHireMerc->ubInsertionCode = INSERTION_CODE_CHOPPER; - //set when the merc's contract is finished - pSoldier->iEndofContractTime = GetMidnightOfFutureDayInMinutes( pSoldier->iTotalContractLength ) + ( GetHourWhenContractDone( pSoldier ) * 60 ); + //set when the merc's contract is finished + pSoldier->iEndofContractTime = GetMidnightOfFutureDayInMinutes( pSoldier->iTotalContractLength ) + ( GetHourWhenContractDone( pSoldier ) * 60 ); + } + else + { + //set when the merc's contract is finished ( + 1 cause it takes a day for the merc to arrive ) + pSoldier->iEndofContractTime = GetMidnightOfFutureDayInMinutes( 1 + pSoldier->iTotalContractLength ) + ( GetHourWhenContractDone( pSoldier ) * 60 ); + } } + // WANNE - MP: We need this, so the merc contract is correct! else { - //set when the merc's contract is finished ( + 1 cause it takes a day for the merc to arrive ) - pSoldier->iEndofContractTime = GetMidnightOfFutureDayInMinutes( 1 + pSoldier->iTotalContractLength ) + ( GetHourWhenContractDone( pSoldier ) * 60 ); + pSoldier->iEndofContractTime = GetMidnightOfFutureDayInMinutes( pSoldier->iTotalContractLength ) + ( GetHourWhenContractDone( pSoldier ) * 60 ); } //Set the time and ID of the last hired merc will arrive LaptopSaveInfo.sLastHiredMerc.iIdOfMerc = pHireMerc->ubProfileID; LaptopSaveInfo.sLastHiredMerc.uiArrivalTime = pHireMerc->uiTimeTillMercArrives; - - //if we are trying to hire a merc that should arrive later, put the merc in the queue - if( pHireMerc->uiTimeTillMercArrives != 0 ) + if (!is_client) { - AddStrategicEvent( EVENT_DELAYED_HIRING_OF_MERC, pHireMerc->uiTimeTillMercArrives, pSoldier->ubID ); - - //specify that the merc is hired but hasnt arrived yet - pMerc->bMercStatus = MERC_HIRED_BUT_NOT_ARRIVED_YET; + //if we are trying to hire a merc that should arrive later, put the merc in the queue + if( pHireMerc->uiTimeTillMercArrives != 0 ) + { + AddStrategicEvent( EVENT_DELAYED_HIRING_OF_MERC, pHireMerc->uiTimeTillMercArrives, pSoldier->ubID ); + + //specify that the merc is hired but hasnt arrived yet + pMerc->bMercStatus = MERC_HIRED_BUT_NOT_ARRIVED_YET; + } + } + else + { + if(is_client)send_hire( iNewIndex, ubCurrentSoldier, pHireMerc->iTotalContractLength, MercCreateStruct.fCopyProfileItemsOver ); + //send off hire info to network, also avail possibility for net-game exclusive hired pSoldier changes... } @@ -265,7 +282,7 @@ INT8 HireMerc( MERC_HIRE_STRUCT *pHireMerc) //Set starting conditions for the merc pSoldier->iStartContractTime = GetWorldDay( ); - AddHistoryToPlayersLog(HISTORY_HIRED_MERC_FROM_MERC, ubCurrentSoldier, GetWorldTotalMin(), -1, -1 ); + if(!is_client)AddHistoryToPlayersLog(HISTORY_HIRED_MERC_FROM_MERC, ubCurrentSoldier, GetWorldTotalMin(), -1, -1 ); } //If the merc is from IMP, (ie a player character) else if( ( ubCurrentSoldier >= 51 ) && ( ubCurrentSoldier < 57 ) ) @@ -294,13 +311,19 @@ void MercArrivesCallback( UINT8 ubSoldierID ) SOLDIERTYPE *pSoldier; UINT32 uiTimeOfPost; - if( !DidGameJustStart() && gsMercArriveSectorX == 9 && gsMercArriveSectorY == 1 ) - { //Mercs arriving in A9. This sector has been deemed as the always safe sector. - //Seeing we don't support entry into a hostile sector (except for the beginning), - //we will nuke any enemies in this sector first. - if( gWorldSectorX != 9 || gWorldSectorY != 1 || gbWorldSectorZ ) - { - EliminateAllEnemies( (UINT8)gsMercArriveSectorX, (UINT8)gsMercArriveSectorY ); + + if (!is_networked) + { + // hayden - maybe you want to duke it out in omerta ;) + if( !DidGameJustStart() && gsMercArriveSectorX == 9 && gsMercArriveSectorY == 1 ) + { + //Mercs arriving in A9. This sector has been deemed as the always safe sector. + //Seeing we don't support entry into a hostile sector (except for the beginning), + //we will nuke any enemies in this sector first. + if( gWorldSectorX != 9 || gWorldSectorY != 1 || gbWorldSectorZ ) + { + EliminateAllEnemies( (UINT8)gsMercArriveSectorX, (UINT8)gsMercArriveSectorY ); + } } } diff --git a/Tactical/Morale.cpp b/Tactical/Morale.cpp index ada0dd7b..143c61a8 100644 --- a/Tactical/Morale.cpp +++ b/Tactical/Morale.cpp @@ -20,8 +20,11 @@ #include "Campaign.h" #include "mapscreen.h" #include "Soldier macros.h" + #include "Event Pump.h" #endif +#include "connect.h" +#include "fresh_header.h" #define MORALE_MOD_MAX 50 // morale *mod* range is -50 to 50, if you change this, check the decay formulas! #define DRUG_EFFECT_MORALE_MOD 150 @@ -322,6 +325,11 @@ void UpdateSoldierMorale( SOLDIERTYPE * pSoldier, UINT8 ubType, INT8 bMoraleMod { return; } + + if(DISABLE_MORALE && is_networked) + { + return; + }//hayden pProfile = &(gMercProfiles[ pSoldier->ubProfile ]); diff --git a/Tactical/Overhead Types.h b/Tactical/Overhead Types.h index 608dd80c..9ceb7a32 100644 --- a/Tactical/Overhead Types.h +++ b/Tactical/Overhead Types.h @@ -23,7 +23,7 @@ #define MIN_AMB_LEVEL_FOR_MERC_LIGHTS 9 -#define MAXTEAMS 6 +#define MAXTEAMS 11 //hayden #define MAXMERCS MAX_NUM_SOLDIERS //TACTICAL OVERHEAD STUFF @@ -274,9 +274,14 @@ enum WorldDirections #define CREATURE_TEAM 2 #define MILITIA_TEAM 3 #define CIV_TEAM 4 -#define LAST_TEAM CIV_TEAM +#define LAST_TEAM LAN_TEAM_FOUR #define PLAYER_PLAN 5 +#define LAN_TEAM_ONE 6 +#define LAN_TEAM_TWO 7 +#define LAN_TEAM_THREE 8 +#define LAN_TEAM_FOUR 9 +//hayden //----------------------------------------------- // diff --git a/Tactical/Overhead.cpp b/Tactical/Overhead.cpp index d5bc4bcc..4ac1e3fc 100644 --- a/Tactical/Overhead.cpp +++ b/Tactical/Overhead.cpp @@ -112,8 +112,10 @@ #include "PreBattle Interface.h" #include "Militia Control.h" #include "Lua Interpreter.h" +#include "bullets.h" #endif - +#include "test_space.h" +#include "connect.h" //forward declarations of common classes to eliminate includes class OBJECTTYPE; @@ -123,6 +125,7 @@ extern void HandleBestSightingPositionInRealtime(); extern UINT8 gubAICounter; +#include "fresh_header.h" #define RT_DELAY_BETWEEN_AI_HANDLING 50 #define RT_AI_TIMESLICE 10 @@ -324,24 +327,44 @@ CHAR8 gzDirectionStr[][ 30 ] = }; // TEMP VALUES FOR TEAM DEAFULT POSITIONS -UINT8 bDefaultTeamRanges[ MAXTEAMS ][ 2 ] = +UINT8 bDefaultTeamRanges[ MAXTEAMS ][ 2 ] = + { - 0, 19, //20 US - 20, 51, //32 ENEMY - 52, 83, //32 CREATURE - 84, 115, //32 REBELS ( OUR GUYS ) - 116, MAX_NUM_SOLDIERS - 1, //32 CIVILIANS - MAX_NUM_SOLDIERS, TOTAL_SOLDIERS - 1 // PLANNING SOLDIERS + 0, 19, //20 US + 20, 51, //32 ENEMY + 52, 52, //kulled off to make room ;) //32 CREATURE + 53, 84, //32 REBELS ( OUR GUYS ) + 85, 116, //32 CIVILIANS + 117, 119, // PLANNING SOLDIERS (reduced) + 120, 126, //1 //new sides //hayden // 7 each + 127, 133, //2 + 134, 140, //3 + 141, MAX_NUM_SOLDIERS - 1, //4 + MAX_NUM_SOLDIERS, TOTAL_SOLDIERS - 1 // PLANNING SOLDIERS }; -COLORVAL bDefaultTeamColors[ MAXTEAMS ] = +//{ +// 0, 19, //20 US +// 20, 51, //32 ENEMY +// 52, 83, //32 CREATURE +// 84, 115, //32 REBELS ( OUR GUYS ) +// 116, MAX_NUM_SOLDIERS - 1, //32 CIVILIANS +//MAX_NUM_SOLDIERS, TOTAL_SOLDIERS - 1 // PLANNING SOLDIERS +//}; + +COLORVAL bDefaultTeamColors[ MAXTEAMS ] = { FROMRGB( 255, 255, 0 ), FROMRGB( 255, 0, 0 ), FROMRGB( 255, 0, 255 ), FROMRGB( 0, 255, 0 ), FROMRGB( 255, 255, 255 ), - FROMRGB( 0, 0, 255 ) + FROMRGB( 0, 0, 255 ), + FROMRGB( 255, 156, 49 ), //hayden //team 1 (radar colours) + FROMRGB( 49, 255, 207 ), //2 + FROMRGB( 193, 85, 255 ), //3 + FROMRGB( 0, 255, 115 ) //4 + }; @@ -684,7 +707,12 @@ BOOLEAN InitOverhead( ) gTacticalStatus.uiCountdownToRestart = GetJA2Clock(); gTacticalStatus.fGoingToEnterDemo = FALSE; gTacticalStatus.fNOTDOLASTDEMO = FALSE; - gTacticalStatus.fDidGameJustStart = TRUE; + + if (is_networked) + gTacticalStatus.fDidGameJustStart = FALSE; //hayden + else + gTacticalStatus.fDidGameJustStart = TRUE; + gTacticalStatus.ubLastRequesterTargetID = NO_PROFILE; for ( cnt = 0; cnt < NUM_PANIC_TRIGGERS; cnt++ ) @@ -1124,6 +1152,7 @@ BOOLEAN ExecuteOverhead( ) // Handle animation update counters // ATE: Added additional check here for special value of anispeed that pauses all updates + { #ifndef BOUNDS_CHECKER if ( TIMECOUNTERDONE( pSoldier->timeCounters.UpdateCounter, pSoldier->sAniDelay ) && pSoldier->sAniDelay != 10000 ) #endif @@ -1169,6 +1198,16 @@ BOOLEAN ExecuteOverhead( ) { continue; } + //hayden - holt at scheduled grid + + if (is_networked) + { + if(pSoldier->sGridNo==pSoldier->sScheduledStop) + { + pSoldier->HaultSoldierFromSighting( 1 ); + pSoldier->sScheduledStop=NULL; + } + } if ( !( gAnimControl[ pSoldier->usAnimState ].uiFlags & ANIM_SPECIALMOVE ) ) { @@ -1594,6 +1633,19 @@ BOOLEAN ExecuteOverhead( ) } } } + //if(is_client)//hayden + //{ + // if(pSoldier->flags.fIsSoldierDelayed==TRUE) + // { + // continue;//in position but waiting on other clients + // } + // else + // { + // //ovh_advance=false; + // pSoldier->flags.fIsSoldierDelayed=TRUE; + // request_ovh(pSoldier->ubID); + // } + //} } if ( ( pSoldier->flags.uiStatusFlags & SOLDIER_PAUSEANIMOVE ) ) @@ -1601,8 +1653,21 @@ BOOLEAN ExecuteOverhead( ) fKeepMoving = FALSE; } + BOOLEAN executeCondition = FALSE; + + if (is_networked) + { + if ( !pSoldier->flags.fPausedMove && fKeepMoving && !pSoldier->flags.fNoAPToFinishMove ) + executeCondition = TRUE; + } + else + { + if ( !pSoldier->flags.fPausedMove && fKeepMoving ) + executeCondition = TRUE; + } + // DO WALKING - if ( !pSoldier->flags.fPausedMove && fKeepMoving ) + if ( executeCondition ) { // Determine deltas // dDeltaX = pSoldier->pathing.sDestXPos - pSoldier->dXPos; @@ -1642,8 +1707,12 @@ BOOLEAN ExecuteOverhead( ) if (pSoldier->flags.fSoldierUpdatedFromNetwork) UpdateSoldierFromNetwork(pSoldier); #endif +//haydens network soldier update ->> + if(is_client)UpdateSoldierToNetwork ( pSoldier ); +// } + } if ( !gfPauseAllAI && ( ((gTacticalStatus.uiFlags & TURNBASED) && (gTacticalStatus.uiFlags & INCOMBAT)) || (fHandleAI && guiAISlotToHandle == cnt) || (pSoldier->aiData.fAIFlags & AI_HANDLE_EVERY_FRAME) || gTacticalStatus.fAutoBandageMode ) ) { @@ -5564,7 +5633,16 @@ void EnterCombatMode( UINT8 ubStartingTeam ) } DebugMsg (TOPIC_JA2,DBG_LEVEL_3,"EnterCombatMode continuing... calling startplayerteamturn"); - StartPlayerTeamTurn( FALSE, TRUE ); + if (!is_client || is_server) //hayden + { + StartPlayerTeamTurn( FALSE, TRUE ); + if(is_client)send_EndTurn( ubStartingTeam ); //hayden + } + else + { + //ScreenMsg( FONT_YELLOW, MSG_CHAT, L"client skipped EnterCombatMode"); + if(is_client)startCombat(ubStartingTeam);//clients other than server meet and send request for combat for server + } } else { @@ -5856,6 +5934,10 @@ BOOLEAN CheckForEndOfCombatMode( BOOLEAN fIncrementTurnsNotSeen ) { return( FALSE ); } + //if (is_server || is_client) + //{ + // return(FALSE); // cheap band-aid to prevent return from turn based action in multiplayer, atleast until further dev... : hayden. + //} // if we're boxing NEVER end combat mode if ( gTacticalStatus.bBoxingState == BOXING ) @@ -5927,8 +6009,17 @@ BOOLEAN CheckForEndOfCombatMode( BOOLEAN fIncrementTurnsNotSeen ) // If we have reach a point where a cons. number of turns gone by.... if ( gTacticalStatus.bConsNumTurnsNotSeen > 1 ) { - gTacticalStatus.bConsNumTurnsNotSeen = 0; + if(is_networked && !getReal)//hayden + { + //ScreenMsg( FONT_MCOLOR_LTYELLOW, MSG_INTERFACE, MPClientMessage[32] ); + + sendRT(); + + return(FALSE); + } + gTacticalStatus.bConsNumTurnsNotSeen = 0; + // Exit mode! ExitCombatMode(); @@ -5993,7 +6084,14 @@ BOOLEAN CheckForEndOfCombatMode( BOOLEAN fIncrementTurnsNotSeen ) void DeathNoMessageTimerCallback( void ) { - CheckAndHandleUnloadingOfCurrentWorld(); + //CheckAndHandleUnloadingOfCurrentWorld(); + if(!is_client)CheckAndHandleUnloadingOfCurrentWorld(); + else + { + ScreenMsg( FONT_LTGREEN, MSG_CHAT, MPClientMessage[40] ); + gTacticalStatus.uiFlags |= SHOW_ALL_MERCS;//hayden + ScreenMsg( FONT_YELLOW, MSG_CHAT, MPClientMessage[41] ); + } } void RemoveStaticEnemiesFromSectorInfo( INT16 sMapX, INT16 sMapY ) @@ -6103,6 +6201,9 @@ BOOLEAN CheckForEndOfBattle( BOOLEAN fAnEnemyRetreated ) // Play death music SetMusicMode( MUSIC_TACTICAL_DEATH ); SetCustomizableTimerCallbackAndDelay( 10000, DeathNoMessageTimerCallback, FALSE ); + + if (is_networked) + ScreenMsg( FONT_MCOLOR_LTYELLOW, MSG_INTERFACE, MPClientMessage[42] ); if ( CheckFact( FACT_FIRST_BATTLE_BEING_FOUGHT, 0 ) ) { @@ -7404,8 +7505,9 @@ SOLDIERTYPE *InternalReduceAttackBusyCount( ) { DebugMsg( TOPIC_JA2, DBG_LEVEL_3, String("!!!!!!! &&&&&&& Problem with attacker busy count decrementing past 0.... preventing wrap-around." ) ); #ifdef JA2BETAVERSION - ScreenMsg( FONT_MCOLOR_LTYELLOW, MSG_BETAVERSION, L"Attack busy problem. Save, exit and send debug.txt + save file to Sir-Tech." ); + if(!is_networked)ScreenMsg( FONT_MCOLOR_LTYELLOW, MSG_BETAVERSION, L"Attack busy problem. Save, exit and send debug.txt + save file to Sir-Tech." ); DebugAttackBusy( "Attack Busy Problem\n"); + //cheap hack to suppress message in MP - hayden. #endif } } @@ -7454,6 +7556,12 @@ SOLDIERTYPE *InternalReduceAttackBusyCount( ) // would work quite well. If only I could close all the holes that the UI opens so that one routine could handle everything. if (!pSoldier) { + if (is_networked) + { + if(gusSelectedSoldier==156) + return( NULL ); + } + pSoldier = MercPtrs[ gusSelectedSoldier ]; } @@ -8046,7 +8154,13 @@ void DoneFadeOutDueToDeath( void ) void EndBattleWithUnconsciousGuysCallback( UINT8 bExitValue ) { // Enter mapscreen..... - CheckAndHandleUnloadingOfCurrentWorld(); + if(!is_client)CheckAndHandleUnloadingOfCurrentWorld(); + else + { + ScreenMsg( FONT_LTGREEN, MSG_CHAT, MPClientMessage[40] ); + gTacticalStatus.uiFlags |= SHOW_ALL_MERCS;//hayden + ScreenMsg( FONT_YELLOW, MSG_CHAT, MPClientMessage[41] ); + } } diff --git a/Tactical/PATHAI.cpp b/Tactical/PATHAI.cpp index bb8a2f40..c785158d 100644 --- a/Tactical/PATHAI.cpp +++ b/Tactical/PATHAI.cpp @@ -42,7 +42,7 @@ #include "gamesettings.h" #include "Buildings.h" #endif - +#include "connect.h" #include "PathAIDebug.h" //forward declarations of common classes to eliminate includes class OBJECTTYPE; @@ -581,7 +581,7 @@ int AStarPathfinder::GetPath(SOLDIERTYPE *s , else if (!GridNoOnVisibleWorldTile( StartNode ) ) { #ifdef JA2BETAVERSION - ScreenMsg( FONT_MCOLOR_RED, MSG_TESTVERSION, L"ERROR! Trying to calculate path from non-visible gridno %d to %d", StartNode, DestNode ); + if(!is_networked)ScreenMsg( FONT_MCOLOR_RED, MSG_TESTVERSION, L"ERROR! Trying to calculate path from non-visible gridno %d to %d", StartNode, DestNode ); #endif return( 0 ); } @@ -2411,7 +2411,7 @@ INT32 FindBestPath(SOLDIERTYPE *s , INT16 sDestination, INT8 ubLevel, INT16 usMo else if (!GridNoOnVisibleWorldTile( (INT16) iOrigination ) ) { #ifdef JA2BETAVERSION - ScreenMsg( FONT_MCOLOR_RED, MSG_TESTVERSION, L"ERROR! Trying to calculate path from non-visible gridno %d to %d", iOrigination, sDestination ); + if(!is_networked)ScreenMsg( FONT_MCOLOR_RED, MSG_TESTVERSION, L"ERROR! Trying to calculate path from non-visible gridno %d to %d", iOrigination, sDestination ); #endif return( 0 ); } diff --git a/Tactical/Points.cpp b/Tactical/Points.cpp index 231a6cc9..c3b00713 100644 --- a/Tactical/Points.cpp +++ b/Tactical/Points.cpp @@ -34,7 +34,7 @@ #include "Map Information.h" #include "Interface Items.h" #endif - +#include "connect.h" //rain //#define BREATH_GAIN_REDUCTION_PER_RAIN_INTENSITY 25 //end rain @@ -537,7 +537,6 @@ BOOLEAN EnoughPoints( SOLDIERTYPE *pSoldier, INT16 sAPCost, INT32 iBPCost, BOOLE //CHRISL: if we don't have soldier information, assume we have enough points. if(pSoldier == NULL) return( TRUE ); - // If this guy is on a special move... don't care about APS, OR BPSs! if ( pSoldier->ubWaitActionToDo ) { @@ -563,6 +562,14 @@ BOOLEAN EnoughPoints( SOLDIERTYPE *pSoldier, INT16 sAPCost, INT32 iBPCost, BOOLE } #endif + if (is_networked) + { + if(pSoldier->ubID > 119 || (!is_server && pSoldier->ubID > 20)) + { + return(TRUE); + }//hayden , if soldier replication, allow. + } + // Get New points sNewAP = pSoldier->bActionPoints - sAPCost; @@ -623,8 +630,21 @@ void DeductPoints( SOLDIERTYPE *pSoldier, INT16 sAPCost, INT32 iBPCost,BOOLEAN f // NB: iBPCost > 0 - breath loss, iBPCost < 0 - breath gain if (iBPCost) { - // Adjust breath changes due to spending or regaining of energy - iBPCost = AdjustBreathPts(pSoldier, iBPCost); + if (is_networked) + { + // Adjust breath changes due to spending or regaining of energy + if(!pSoldier->bActive) + { + //ScreenMsg( FONT_MCOLOR_LTYELLOW, MSG_INTERFACE, L"test_func2" ); + } + else + iBPCost = AdjustBreathPts(pSoldier, iBPCost); + } + else + { + iBPCost = AdjustBreathPts(pSoldier, iBPCost); + } + // Snap: award some health and strength for exertion // Do 4 StatChange rolls for health (2 for strength) per 10 breath points spent? diff --git a/Tactical/Soldier Add.cpp b/Tactical/Soldier Add.cpp index 398a2011..f5f648f7 100644 --- a/Tactical/Soldier Add.cpp +++ b/Tactical/Soldier Add.cpp @@ -23,7 +23,7 @@ #include "Exit Grids.h" #endif - +#include "connect.h" //forward declarations of common classes to eliminate includes class OBJECTTYPE; class SOLDIERTYPE; @@ -1162,8 +1162,13 @@ BOOLEAN InternalAddSoldierToSector( UINT8 ubID, BOOLEAN fCalculateDirection, BOO } else { - sGridNo = FindGridNoFromSweetSpot( pSoldier, pSoldier->sInsertionGridNo, 7, &ubCalculatedDirection ); - + if(is_client && (pSoldier->ubStrategicInsertionCode == INSERTION_CODE_GRIDNO)) + { + sGridNo = pSoldier->sInsertionGridNo; + ubCalculatedDirection = pSoldier->ubDirection; + } + else sGridNo = FindGridNoFromSweetSpot( pSoldier, pSoldier->sInsertionGridNo, 7, &ubCalculatedDirection ); + //hayden // ATE: Error condition - if nowhere use insertion gridno! if ( sGridNo == NOWHERE ) { diff --git a/Tactical/Soldier Ani.cpp b/Tactical/Soldier Ani.cpp index ac5f8605..4d3826ef 100644 --- a/Tactical/Soldier Ani.cpp +++ b/Tactical/Soldier Ani.cpp @@ -66,8 +66,8 @@ //forward declarations of common classes to eliminate includes class OBJECTTYPE; class SOLDIERTYPE; - - +#include "connect.h" +#include "fresh_header.h" #define NO_JUMP 0 #define MAX_ANIFRAMES_PER_FLASH 2 //#define TIME_FOR_RANDOM_ANIM_CHECK 10 @@ -367,8 +367,13 @@ BOOLEAN AdjustToNextAnimationFrame( SOLDIERTYPE *pSoldier ) SFireWeapon.sTargetGridNo = pSoldier->sTargetGridNo; SFireWeapon.bTargetLevel = pSoldier->bTargetLevel; SFireWeapon.bTargetCubeLevel= pSoldier->bTargetCubeLevel; + if((is_server && pSoldier->ubID<120) || (!is_server && is_client && pSoldier->ubID<20) || (!is_server && !is_client) ) + {//only carry on if own werc AddGameEvent( S_FIREWEAPON, 0, &SFireWeapon ); - + + //hayden + if(is_server || (is_client && pSoldier->ubID <20) ) send_fireweapon( &SFireWeapon ); + } //DIGICRAB: Burst UnCap //Loop around in the animation if we still have burst rounds to fire if (pSoldier->bDoBurst && (pSoldier->bDoBurst <= ((pSoldier->bDoAutofire)?(pSoldier->bDoAutofire):(GetShotsPerBurst(&pSoldier->inv[HANDPOS]))) || (( pSoldier->bWeaponMode == WM_ATTACHED_GL_BURST && pSoldier->bDoBurst <= Weapon[GetAttachedGrenadeLauncher(&pSoldier->inv[HANDPOS])].ubShotsPerBurst)) )) @@ -3209,6 +3214,12 @@ BOOLEAN HandleSoldierDeath( SOLDIERTYPE *pSoldier , BOOLEAN *pfMadeCorpse ) if ( pSoldier->stats.bLife == 0 && !( pSoldier->flags.uiStatusFlags & SOLDIER_DEAD ) ) { + // Haydent + if (is_networked) + //send death info + send_death(pSoldier);//quickfix + + // Cancel services here... pSoldier->ReceivingSoldierCancelServices( ); pSoldier->GivingSoldierCancelServices( ); diff --git a/Tactical/Soldier Control.cpp b/Tactical/Soldier Control.cpp index 967b5207..87107cf7 100644 --- a/Tactical/Soldier Control.cpp +++ b/Tactical/Soldier Control.cpp @@ -97,7 +97,7 @@ #include "Strategic Pathing.h" #endif - +#include "fresh_header.h" //forward declarations of common classes to eliminate includes class OBJECTTYPE; @@ -122,6 +122,7 @@ extern INT16 DirIncrementer[8]; #define MIN_SUBSEQUENT_SNDS_DELAY 2000 +#include "connect.h" // Enumerate extended directions enum @@ -1649,6 +1650,34 @@ void SOLDIERTYPE::AdjustNoAPToFinishMove( BOOLEAN fSet ) // this->DeleteSoldierLight( ); } + + //send it on + if (is_networked && this->ubID < 120) + { + //if(this->ubID>=120) + // return;//hayden + EV_S_STOP_MERC SStopMerc; + + SStopMerc.sGridNo = this->sGridNo; + SStopMerc.ubDirection = this->ubDirection; + SStopMerc.usSoldierID = this->ubID; + SStopMerc.fset=fSet; + SStopMerc.sXPos=this->sX; + SStopMerc.sYPos=this->sY; + + //AddGameEvent( S_STOP_MERC, 0, &SStopMerc ); //hayden. + + + if(is_client) + send_stop(&SStopMerc); + } + + + + + + + this->flags.fNoAPToFinishMove = fSet; if ( !fSet ) @@ -2484,9 +2513,20 @@ BOOLEAN SOLDIERTYPE::ChangeSoldierState( UINT16 usNewState, UINT16 usStartingAni SChangeState.uiUniqueId = this->uiUniqueSoldierIdValue; //AddGameEvent( S_CHANGESTATE, 0, &SChangeState ); + if(is_server && this->ubID < 120) + { this->EVENT_InitNewSoldierAnim( SChangeState.usNewState, SChangeState.usStartingAniCode, SChangeState.fForce ); - - + send_changestate(&SChangeState); + } + else if(is_client && !is_server && this->ubID < 20) + { + this->EVENT_InitNewSoldierAnim( SChangeState.usNewState, SChangeState.usStartingAniCode, SChangeState.fForce ); + send_changestate(&SChangeState); + } + else if (!is_client) + { + this->EVENT_InitNewSoldierAnim( SChangeState.usNewState, SChangeState.usStartingAniCode, SChangeState.fForce ); + } return( TRUE ); } @@ -4649,8 +4689,16 @@ BOOLEAN SOLDIERTYPE::InternalSoldierReadyWeapon( UINT8 sFacingDir, BOOLEAN fEndR if ( usAnimState != INVALID_ANIMATION ) { + if(is_networked) + { + ChangeSoldierState( usAnimState, 0 , FALSE );//this passes it to an area where it gets sent over the network. + } + else + { this->EVENT_InitNewSoldierAnim( usAnimState, 0 , FALSE ); + } fReturnVal = TRUE; + } if ( !fEndReady ) @@ -5906,7 +5954,11 @@ BOOLEAN SOLDIERTYPE::EVENT_InternalGetNewSoldierPath( INT16 sDestGridNo, UINT16 this->usDontUpdateNewGridNoOnMoveAnimChange = TRUE; this->EVENT_InitNewSoldierAnim( usMoveAnimState, 0, FALSE ); + if(is_server || (is_client && this->ubID <20) ) send_path( this, sDestGridNo, usMoveAnimState , 0 , FALSE ); + + return( TRUE ); } + if(is_server || (is_client && this->ubID <20) ) send_path( this, sDestGridNo, this->usAnimState , 255 , FALSE ); return( TRUE ); } @@ -5964,11 +6016,13 @@ BOOLEAN SOLDIERTYPE::EVENT_InternalGetNewSoldierPath( INT16 sDestGridNo, UINT16 { this->EVENT_InitNewSoldierAnim( usAnimState, 0, FALSE ); this->usPendingAnimation = usMoveAnimState; + if(is_server || (is_client && this->ubID <20) ) send_path( this, sDestGridNo, usAnimState , 0 , FALSE ); } else { // Call local copy for change soldier state! this->EVENT_InitNewSoldierAnim( usMoveAnimState, 0, fForceRestartAnim ); + if(is_server || (is_client && this->ubID <20) ) send_path( this, sDestGridNo, usMovementAnim , 0 , fForceRestartAnim ); } @@ -7539,6 +7593,8 @@ void SetSoldierAniSpeed( SOLDIERTYPE *pSoldier ) // ATE: If we are an enemy and are not visible...... // Set speed to 0 + if(!is_client) + { if ( ( gTacticalStatus.uiFlags & TURNBASED && ( gTacticalStatus.uiFlags & INCOMBAT ) ) || gTacticalStatus.fAutoBandageMode ) { if ( ( ( pSoldier->bVisible == -1 && pSoldier->bVisible == pSoldier->bLastRenderVisibleValue ) || gTacticalStatus.fAutoBandageMode ) && pSoldier->usAnimState != MONSTER_UP ) @@ -7555,6 +7611,7 @@ void SetSoldierAniSpeed( SOLDIERTYPE *pSoldier ) return; } } + } // Default stats soldier to same as normal soldier..... pStatsSoldier = pSoldier; @@ -7882,7 +7939,11 @@ void SOLDIERTYPE::BeginSoldierClimbUpRoof( void ) } INT8 bNewDirection; UINT8 ubWhoIsThere; - + if(is_client) + { + ScreenMsg( FONT_MCOLOR_LTYELLOW, MSG_INTERFACE, MPClientMessage[43] ); + return;//hayden disable climbing roof + } if ( FindHeigherLevel( this, this->sGridNo, this->ubDirection, &bNewDirection ) && ( this->pathing.bLevel == 0 ) ) { if ( EnoughPoints( this, GetAPsToClimbRoof( this, FALSE ), 0, TRUE ) ) @@ -9749,6 +9810,7 @@ void SendSoldierSetDesiredDirectionEvent( SOLDIERTYPE *pSoldier, UINT16 usDesire SSetDesiredDirection.uiUniqueId = pSoldier->uiUniqueSoldierIdValue; AddGameEvent( S_SETDESIREDDIRECTION, 0, &SSetDesiredDirection ); + if(is_server || (is_client && pSoldier->ubID <20) ) send_dir( pSoldier, usDesiredDirection ); } @@ -9783,8 +9845,10 @@ void SendChangeSoldierStanceEvent( SOLDIERTYPE *pSoldier, UINT8 ubNewStance ) AddGameEvent( S_CHANGESTANCE, 0, &SChangeStance ); #endif - + if((pSoldier->ubID > 19) && is_networked) + return; pSoldier->ChangeSoldierStance( ubNewStance ); + if(is_server || (is_client && pSoldier->ubID <20) ) send_stance( pSoldier, ubNewStance ); } @@ -10905,12 +10969,17 @@ void SOLDIERTYPE::HaultSoldierFromSighting( BOOLEAN fFromSightingEnemy ) { DebugMsg( TOPIC_JA2, DBG_LEVEL_3, String("HaultSoldierFromSighting") ); // SEND HUALT EVENT! - //EV_S_STOP_MERC SStopMerc; + EV_S_STOP_MERC SStopMerc; - //SStopMerc.sGridNo = this->sGridNo; - //SStopMerc.bDirection = this->ubDirection; - //SStopMerc.usSoldierID = this->ubID; - //AddGameEvent( S_STOP_MERC, 0, &SStopMerc ); + SStopMerc.sGridNo = this->sGridNo; + SStopMerc.ubDirection = this->ubDirection; + SStopMerc.usSoldierID = this->ubID; + SStopMerc.fset=TRUE; + SStopMerc.sXPos=this->sX; + SStopMerc.sYPos=this->sY; + //AddGameEvent( S_STOP_MERC, 0, &SStopMerc ); //hayden. + if(this->ubID>=120) return;//hayden + if(is_client)send_stop(&SStopMerc); // If we are a 'specialmove... ignore... if ( ( gAnimControl[ this->usAnimState ].uiFlags & ANIM_SPECIALMOVE ) ) diff --git a/Tactical/Soldier Control.h b/Tactical/Soldier Control.h index 33fe0741..e56a4a60 100644 --- a/Tactical/Soldier Control.h +++ b/Tactical/Soldier Control.h @@ -907,6 +907,7 @@ public: UINT32 uiSoldierUpdateNumber; BYTE ubSoldierUpdateType; + UINT16 sScheduledStop; //hayden, used for scheduling a grid to stop //END INT32 iStartOfInsuranceContract; diff --git a/Tactical/Soldier Create.cpp b/Tactical/Soldier Create.cpp index 3ae8cef4..165804ce 100644 --- a/Tactical/Soldier Create.cpp +++ b/Tactical/Soldier Create.cpp @@ -47,6 +47,7 @@ #include "math.h" #endif +#include "connect.h" // THESE 3 DIFFICULTY FACTORS MUST ALWAYS ADD UP TO 100% EXACTLY!!! #define DIFF_FACTOR_PLAYER_PROGRESS 50 @@ -428,6 +429,42 @@ SOLDIERTYPE* TacticalCreateSoldier( SOLDIERCREATE_STRUCT *pCreateStruct, UINT8 * *pubID = NOBODY; DebugMsg(TOPIC_JA2,DBG_LEVEL_3,String("TacticalCreateSoldier")); + INT8 tbTeam; + BOOLEAN tfPP; + tbTeam=pCreateStruct->bTeam; + tfPP=pCreateStruct->fPlayerPlan; //used as temp indicator of struct sent from the server //hayden. + + if(is_client && !is_server && (tbTeam >0 && tbTeam < 5) && tfPP==0) + { + return NULL; // pure client to not spawn AI unless from server, Hayden. + //gTacticalStatus.Team[ tbTeam ].bTeamActive=0; + } + //if(is_server && tbTeam>0 && tbTeam<5) + if(is_server && tbTeam>0 && tbTeam<5) + { + //if(tbTeam==1 && !ENEMY_ENABLED) + //{ + // return NULL; + //} + //if(tbTeam==2 && !CREATURE_ENABLED) + //{ + // return NULL; + //} + //if(tbTeam==3 && !MILITIA_ENABLED) + //{ + // return NULL; + //} + //if(tbTeam==4 && !CIV_ENABLED) + //{ + // return NULL; + //} + send_AI(pCreateStruct,pubID); + } + if(is_client && !is_server && tfPP==1) + { + pCreateStruct->fPlayerPlan = 0; + } + //hayden //Kris: //Huge no no! See the header file for description of static detailed placements. //If this expression ever evaluates to true, then it will expose serious problems. diff --git a/Tactical/Soldier Create.h b/Tactical/Soldier Create.h index ab32a81f..35565889 100644 --- a/Tactical/Soldier Create.h +++ b/Tactical/Soldier Create.h @@ -272,6 +272,7 @@ public: BOOLEAN fUseGivenVehicle; INT8 bUseGivenVehicleID; BOOLEAN fHasKeys; + INT8 PADDINGSLOTS[ 14 ]; // // New and OO stuff goes after here. Above this point any changes will goof up reading from files. diff --git a/Tactical/Soldier Profile.cpp b/Tactical/Soldier Profile.cpp index 3eb954d1..f8bea8b7 100644 --- a/Tactical/Soldier Profile.cpp +++ b/Tactical/Soldier Profile.cpp @@ -56,6 +56,7 @@ #include "strategic.h" #endif +#include "connect.h" #ifdef JA2EDITOR extern BOOLEAN gfProfileDataLoaded; #endif @@ -447,7 +448,7 @@ BOOLEAN LoadMercProfiles(void) DecideActiveTerrorists(); // initialize mercs' status - StartSomeMercsOnAssignment( ); + if(!is_networked)StartSomeMercsOnAssignment( ); // initial recruitable mercs' reputation in each town InitializeProfilesForTownReputation( ); @@ -988,11 +989,22 @@ SOLDIERTYPE *ChangeSoldierTeam( SOLDIERTYPE *pSoldier, UINT8 ubTeam ) pNewSoldier->bLastRenderVisibleValue = pSoldier->bLastRenderVisibleValue; pNewSoldier->bVisible = pSoldier->bVisible; // 0verhaul: Need to pass certain flags over. COWERING is one of them. Others to be determined. - pNewSoldier->flags.uiStatusFlags |= pSoldier->flags.uiStatusFlags & (SOLDIER_COWERING | SOLDIER_MUTE | SOLDIER_GASSED); + + // copy uiStatusFlags, etc. - hayden :) + if (is_networked) + { + pNewSoldier->flags.uiStatusFlags = pSoldier->flags.uiStatusFlags; + pNewSoldier->ubProfile = pSoldier->ubProfile; + } + else + { + pNewSoldier->flags.uiStatusFlags |= pSoldier->flags.uiStatusFlags & (SOLDIER_COWERING | SOLDIER_MUTE | SOLDIER_GASSED); + } + if ( ubTeam == gbPlayerNum ) { - pNewSoldier->bVisible = 1; + pNewSoldier->bVisible= 1; } //CHRISL: Rather then resorting the profile, which recreates all the items, what if we simply try and sort the diff --git a/Tactical/Soldier macros.h b/Tactical/Soldier macros.h index 7a81fc70..8380c1b3 100644 --- a/Tactical/Soldier macros.h +++ b/Tactical/Soldier macros.h @@ -15,7 +15,7 @@ #define AM_A_ROBOT( p ) ( ( p->ubProfile == NO_PROFILE ) ? FALSE : ( gMercProfiles[ p->ubProfile ].ubBodyType == ROBOTNOWEAPON ) ) -#define OK_ENEMY_MERC( p ) ( !p->aiData.bNeutral && (p->bSide != gbPlayerNum ) && p->stats.bLife >= OKLIFE ) +#define OK_ENEMY_MERC( p ) ( !p->aiData.bNeutral && (p->bSide != gbPlayerNum ) && p->stats.bLife >= OKLIFE && (p->bTeam < 5 )) // Checks if our guy can be controllable .... checks bInSector, team, on duty, etc... #define OK_CONTROLLABLE_MERC( p ) ( p->stats.bLife >= OKLIFE && p->bActive && p->bInSector && p->bTeam == gbPlayerNum && p->bAssignment < ON_DUTY ) diff --git a/Tactical/Tactical.vcproj b/Tactical/Tactical.vcproj index 290d45c5..e1d763a1 100644 --- a/Tactical/Tactical.vcproj +++ b/Tactical/Tactical.vcproj @@ -333,7 +333,7 @@ 4 || (is_client && !is_server )) //hayden + { + + InitEnemyUIBar( 0, 0 ); + fInterfacePanelDirty = DIRTYLEVEL2; + AddTopMessage( COMPUTER_TURN_MESSAGE, TeamTurnString[ ubTeam ] ); + /*if(is_server && !net_turn) send_EndTurn(ubTeam); + if(net_turn == true) net_turn = false;*/ + if(is_server) send_EndTurn(ubTeam); + + + + //return; + break; + } + else { #ifdef NETWORKED // Only the host should do this if(!gfAmIHost) break; #endif + if( is_client && !is_server ) //hayden //disable independant client AI + break; - // Set First enemy merc to AI control + + // Set First enemy merc to AI control if ( BuildAIListForTeam( ubTeam ) ) { @@ -515,6 +562,10 @@ void BeginTeamTurn( UINT8 ubTeam ) AddTopMessage( COMPUTER_TURN_MESSAGE, TeamTurnString[ ubTeam ] ); } StartNPCAI( MercPtrs[ ubID ] ); + /*if(is_server && !net_turn) send_EndTurn(ubTeam); + if(net_turn == true) net_turn = false;*/ + if(is_server) send_EndTurn(ubTeam); + return; } } @@ -544,7 +595,14 @@ void DisplayHiddenInterrupt( SOLDIERTYPE * pSoldier ) SlideTo( NOWHERE, pSoldier->ubID, NOBODY ,SETLOCATOR); } - guiPendingOverrideEvent = LU_BEGINUILOCK; + if(is_client) + { + guiPendingOverrideEvent = LA_BEGINUIOURTURNLOCK; + } + else + { + guiPendingOverrideEvent = LU_BEGINUILOCK; + } // Dirty panel interface! fInterfacePanelDirty = DIRTYLEVEL2; @@ -765,6 +823,10 @@ void StartInterrupt( void ) // Signal UI done enemy's turn guiPendingOverrideEvent = LU_ENDUILOCK; + + if (is_networked) + guiPendingOverrideEvent = LA_ENDUIOUTURNLOCK; + HandleTacticalUI( ); InitPlayerUIBar( TRUE ); @@ -831,7 +893,7 @@ void StartInterrupt( void ) ubFirstInterrupter = ubInterrupter; } } - + { // here we have to rebuilt the AI list! BuildAIListForTeam( bTeam ); @@ -855,11 +917,16 @@ void StartInterrupt( void ) gTacticalStatus.ubCurrentTeam = pSoldier->bTeam; - #ifdef JA2BETAVERSION + //#ifdef JA2BETAVERSION + + if (is_networked) ScreenMsg( FONT_MCOLOR_LTYELLOW, MSG_TESTVERSION, L"Interrupt ( could be hidden )" ); - #endif - + + //#endif + //send_interrupt( pSoldier );//hayden StartNPCAI( pSoldier ); + + } } if ( !gfHiddenInterrupt ) @@ -919,7 +986,46 @@ void EndInterrupt( BOOLEAN fMarkInterruptOccurred ) gfHiddenInterrupt = FALSE; // resume interrupted interrupt - StartInterrupt(); + //hayden + if (is_networked) + { + UINT8 nubFirstInterrupter; + INT8 nbTeam; + SOLDIERTYPE * npSoldier; + + nubFirstInterrupter = LATEST_INTERRUPT_GUY; + npSoldier = MercPtrs[nubFirstInterrupter]; + nbTeam = npSoldier->bTeam; + ScreenMsg( FONT_MCOLOR_LTYELLOW, MSG_INTERFACE, L"unchecked interrupt call area:(resume interrupted interrupt)..."); + + if ((nbTeam > 0) && (nbTeam <6 ) && is_server) //is AI and are server + { + send_interrupt( npSoldier ); + StartInterrupt(); + + } + else if(nbTeam == 0) //its an interrupt for own merc team + { + //ScreenMsg( FONT_MCOLOR_LTYELLOW, MSG_INTERFACE, L"interrupt for our team"); + //hayden + StartInterrupt(); + send_interrupt( npSoldier ); // + } + else + { + //ScreenMsg( FONT_MCOLOR_LTYELLOW, MSG_INTERFACE, L"interrupt for another team"); //may need more work. + //ClearIntList(); + //hayden + StartInterrupt(); + send_interrupt( npSoldier ); // + + } + } + else + { + StartInterrupt(); + } + } else { @@ -1020,6 +1126,10 @@ void EndInterrupt( BOOLEAN fMarkInterruptOccurred ) // both hidden interrupts as well - NOT good because // hidden interrupts should leave it locked if it was already... guiPendingOverrideEvent = LU_ENDUILOCK; + + if (is_networked) + guiPendingOverrideEvent = LA_ENDUIOUTURNLOCK; + HandleTacticalUI( ); if ( gusSelectedSoldier != NOBODY ) @@ -1044,7 +1154,7 @@ void EndInterrupt( BOOLEAN fMarkInterruptOccurred ) } } - else + else if(pSoldier->bTeam < 6)//hayden : is Ai or LAN ? { // this could be set to true for AI-vs-AI interrupts gfHiddenInterrupt = FALSE; @@ -1109,7 +1219,14 @@ void EndInterrupt( BOOLEAN fMarkInterruptOccurred ) } // Signal UI done enemy's turn - guiPendingOverrideEvent = LU_BEGINUILOCK; + if(is_client) + { + guiPendingOverrideEvent = LA_BEGINUIOURTURNLOCK; + } + else + { + guiPendingOverrideEvent = LU_BEGINUILOCK; + } ClearIntList(); } @@ -1126,7 +1243,14 @@ void EndInterrupt( BOOLEAN fMarkInterruptOccurred ) } // Signal UI done enemy's turn - guiPendingOverrideEvent = LU_BEGINUILOCK; + if(is_client) + { + guiPendingOverrideEvent = LA_BEGINUIOURTURNLOCK; + } + else + { + guiPendingOverrideEvent = LU_BEGINUILOCK; + } // must clear int list before ending turn ClearIntList(); @@ -1134,6 +1258,24 @@ void EndInterrupt( BOOLEAN fMarkInterruptOccurred ) } } + else //its going to another Lan client..//hayden + { + + gTacticalStatus.ubCurrentTeam = pSoldier->bTeam; + AddTopMessage( COMPUTER_TURN_MESSAGE, TeamTurnString[ gTacticalStatus.ubCurrentTeam ] ); + if(is_client) + { + guiPendingOverrideEvent = LA_BEGINUIOURTURNLOCK; + } + else + { + guiPendingOverrideEvent = LU_BEGINUILOCK; + } + + // must clear int list before ending turn + ClearIntList(); + + } // Reset our interface! fInterfacePanelDirty = DIRTYLEVEL2; @@ -1336,7 +1478,7 @@ BOOLEAN StandardInterruptConditionsMet( SOLDIERTYPE * pSoldier, UINT8 ubOpponent } else { - if ( !(pOpponent->flags.uiStatusFlags & SOLDIER_UNDERAICONTROL) && (pSoldier->bSide != pOpponent->bSide)) + if ( !(is_client || (pOpponent->flags.uiStatusFlags & SOLDIER_UNDERAICONTROL)) && (pSoldier->bSide != pOpponent->bSide)) { return( FALSE ); } @@ -1494,6 +1636,16 @@ INT8 CalcInterruptDuelPts( SOLDIERTYPE * pSoldier, UINT8 ubOpponentID, BOOLEAN f iPoints--; } + //hayden, multiplayer add advantage for a ready'd reapon + if(is_networked) + { + if ( ( gAnimControl[ pSoldier->usAnimState ].uiFlags &( ANIM_FIREREADY | ANIM_FIRE ) )) + { + iPoints=(iPoints+WEAPON_READIED_BONUS); + + } + } + // if soldier is still in shock from recent injuries, that penalizes him iPoints -= pSoldier->aiData.bShock; @@ -1599,8 +1751,11 @@ INT8 CalcInterruptDuelPts( SOLDIERTYPE * pSoldier, UINT8 ubOpponentID, BOOLEAN f #ifdef DEBUG_INTERRUPTS DebugMsg( TOPIC_JA2, DBG_LEVEL_3, String("Calculating int pts for %d vs %d, number is %d", pSoldier->ubID, ubOpponentID, iPoints ) ); #endif - - +if(is_networked) +{ + SOLDIERTYPE *pOpp = &Menptr[ubOpponentID]; + ScreenMsg( FONT_MCOLOR_LTYELLOW, MSG_CHAT, L"Interrupt: '%s' vs '%s' = %d points.",pSoldier->name,pOpp->name, iPoints ); +} DebugMsg (TOPIC_JA2,DBG_LEVEL_3,"CalcInterruptDuelPts done"); return( (INT8)iPoints ); } @@ -1858,7 +2013,63 @@ void DoneAddingToIntList( SOLDIERTYPE * pSoldier, BOOLEAN fChange, UINT8 ubInter } else { - StartInterrupt(); + if (is_networked) + { + UINT8 nubFirstInterrupter; + INT8 nbTeam; + SOLDIERTYPE * npSoldier; + + nubFirstInterrupter = LATEST_INTERRUPT_GUY; + npSoldier = MercPtrs[nubFirstInterrupter]; + nbTeam = npSoldier->bTeam; + + + if ((nbTeam > 0) && (nbTeam <6 ) && is_server) //is AI and are server + { + ScreenMsg( FONT_MCOLOR_LTYELLOW, MSG_INTERFACE, L"interrupt for AI team"); + send_interrupt( npSoldier ); + StartInterrupt(); + + } + else if(nbTeam == 0 && gTacticalStatus.ubCurrentTeam == 0) //its an interrupt for own merc team && its our turn + { + + //hayden + StartInterrupt(); + send_interrupt( npSoldier ); // + ScreenMsg( FONT_MCOLOR_LTYELLOW, MSG_INTERFACE, L"interrupt for my team"); + } + else if(gTacticalStatus.ubCurrentTeam == 0)//its our turn (we are moving) + { + //StartInterrupt(); + send_interrupt( npSoldier ); // + ScreenMsg( FONT_MCOLOR_LTYELLOW, MSG_INTERFACE, L"interrupt for another team"); + { + // ScreenMsg( FONT_MCOLOR_LTYELLOW, MSG_INTERFACE, L"Interrupted" ); + //stop moving merc who was interrupted and init UI bar + SOLDIERTYPE* pMerc = MercPtrs[ gusSelectedSoldier ]; + //AdjustNoAPToFinishMove( pMerc, TRUE ); + pMerc->HaultSoldierFromSighting(TRUE); + //pMerc->fTurningFromPronePosition = FALSE;// hmmm ?? + FreezeInterfaceForEnemyTurn(); + InitEnemyUIBar( 0, 0 ); + fInterfacePanelDirty = DIRTYLEVEL2; + AddTopMessage( COMPUTER_TURN_MESSAGE, TeamTurnString[ nbTeam ] ); + gTacticalStatus.fInterruptOccurred = TRUE; + + } + //ClearIntList(); + + } + else + { + ClearIntList();//no interrupt to be awarded, clear generated list. + } + } + else + { + StartInterrupt(); + } } } } diff --git a/Tactical/TeamTurns.h b/Tactical/TeamTurns.h index c5974d77..1d14dbcf 100644 --- a/Tactical/TeamTurns.h +++ b/Tactical/TeamTurns.h @@ -4,6 +4,7 @@ #include "Soldier Control.h" extern UINT8 gubOutOfTurnPersons; +extern UINT8 gubOutOfTurnOrder[MAXMERCS] ; extern BOOLEAN gfHiddenInterrupt; extern BOOLEAN gfHiddenTurnbased; @@ -17,6 +18,7 @@ extern BOOLEAN InterruptDuel( SOLDIERTYPE * pSoldier, SOLDIERTYPE * pOpponent); extern void AddToIntList( UINT8 ubID, BOOLEAN fGainControl, BOOLEAN fCommunicate ); extern void DoneAddingToIntList( SOLDIERTYPE * pSoldier, BOOLEAN fChange, UINT8 ubInterruptType); +void FreezeInterfaceForEnemyTurn( void ); void ClearIntList( void ); BOOLEAN SaveTeamTurnsToTheSaveGameFile( HWFILE hFile ); @@ -24,6 +26,7 @@ BOOLEAN SaveTeamTurnsToTheSaveGameFile( HWFILE hFile ); BOOLEAN LoadTeamTurnsFromTheSavedGameFile( HWFILE hFile ); void EndAllAITurns( void ); +void EndTurnEvents( void ); BOOLEAN NPCFirstDraw( SOLDIERTYPE * pSoldier, SOLDIERTYPE * pTargetSoldier ); diff --git a/Tactical/Turn Based Input.cpp b/Tactical/Turn Based Input.cpp index 983a81dd..81fce4bc 100644 --- a/Tactical/Turn Based Input.cpp +++ b/Tactical/Turn Based Input.cpp @@ -117,7 +117,7 @@ #endif #include "Quest Debug System.h" - +#include "connect.h" //forward declarations of common classes to eliminate includes class OBJECTTYPE; class SOLDIERTYPE; @@ -188,7 +188,7 @@ BOOLEAN gfNextFireJam = FALSE; extern INT16 ITEMDESC_START_X; extern INT16 ITEMDESC_START_Y; - +#include "fresh_header.h" //Little functions called by keyboard input void SwapGoggles(SOLDIERTYPE *pTeamSoldier); @@ -1530,7 +1530,7 @@ void GetKeyboardInput( UINT32 *puiNewEvent ) } - /// Allow to save everywhere + /// Allow to load everywhere if ((InputEvent.usEvent == KEY_DOWN )&& ( InputEvent.usParam == 'l') ) { if( InputEvent.usKeyState & ALT_DOWN ) @@ -1557,6 +1557,91 @@ void GetKeyboardInput( UINT32 *puiNewEvent ) } } } + if (is_networked) + { + + if ((InputEvent.usEvent == KEY_DOWN )&& ( InputEvent.usParam == 's') )//allow saving 'always'//hayden + { + if( InputEvent.usKeyState & ALT_DOWN ) + { + if( !fDisableMapInterfaceDueToBattle && !( gTacticalStatus.uiFlags & ENGAGED_IN_CONV ) ) + { + //if the game CAN be saved + if( CanGameBeSaved() ) + { + guiPreviousOptionScreen = GAME_SCREEN; + //guiPreviousOptionScreen = guiCurrentScreen; + DoQuickSave(); + } + else + { + //Display a message saying the player cant save now + DoMessageBox( MSG_BOX_BASIC_STYLE, zNewTacticalMessages[ TCTL_MSG__IRON_MAN_CANT_SAVE_NOW ], GAME_SCREEN, ( UINT8 )MSG_BOX_FLAG_OK, NULL, NULL ); + } + } + } + else if( InputEvent.usKeyState & CTRL_DOWN ) + { + if( !fDisableMapInterfaceDueToBattle && !( gTacticalStatus.uiFlags & ENGAGED_IN_CONV ) ) + { + //if the game CAN be saved + if( CanGameBeSaved() ) + { + gfSaveGame = TRUE; + gfCameDirectlyFromGame = TRUE; + + guiPreviousOptionScreen = GAME_SCREEN; + LeaveTacticalScreen( SAVE_LOAD_SCREEN ); + } + else + { + //Display a message saying the player cant save now + DoMessageBox( MSG_BOX_BASIC_STYLE, zNewTacticalMessages[ TCTL_MSG__IRON_MAN_CANT_SAVE_NOW ], GAME_SCREEN, ( UINT8 )MSG_BOX_FLAG_OK, NULL, NULL); + } + } + } + } + + + + if ((InputEvent.usEvent == KEY_DOWN )&& ( InputEvent.usParam == '0') ) + { + //if( InputEvent.usKeyState & ALT_DOWN ) + { + if ( !( gTacticalStatus.uiFlags & ENGAGED_IN_CONV ) ) + { + test_func2(); + } + } + + } + + + + + if ((InputEvent.usEvent == KEY_DOWN )&& ( InputEvent.usParam == 'e') ) + { + if( InputEvent.usKeyState & ALT_DOWN ) + { + if ( !( gTacticalStatus.uiFlags & ENGAGED_IN_CONV ) ) + { + overide_turn(); + } + } + + } + + if ((InputEvent.usEvent == KEY_DOWN )&& ( InputEvent.usParam == 'k') ) + { + if( InputEvent.usKeyState & ALT_DOWN ) + { + if ( !( gTacticalStatus.uiFlags & ENGAGED_IN_CONV ) ) + { + kick_player(); + } + } + } + } // Break of out IN CONV... @@ -2186,7 +2271,12 @@ void GetKeyboardInput( UINT32 *puiNewEvent ) } } else + { ChangeCurrentSquad( 4 ); + + if (is_networked) + grid_display();//hayden + } break; case '6': @@ -2203,10 +2293,16 @@ void GetKeyboardInput( UINT32 *puiNewEvent ) case '9': ChangeCurrentSquad( 8 ); + + if (is_networked) + cheat_func(); break; case '0': ChangeCurrentSquad( 9 ); + + if (is_networked) + //test_func2(); break; case 'x': @@ -3474,7 +3570,7 @@ void GetKeyboardInput( UINT32 *puiNewEvent ) if ( fAlt ) RemoveCharacterFromSquads(MercPtrs[gusSelectedSoldier]); - else if( !fDisableMapInterfaceDueToBattle && !( gTacticalStatus.uiFlags & ENGAGED_IN_CONV ) ) + else if( !fDisableMapInterfaceDueToBattle && !( gTacticalStatus.uiFlags & ENGAGED_IN_CONV ) && !is_networked) { //if the game CAN be saved if( CanGameBeSaved() ) @@ -3495,7 +3591,7 @@ void GetKeyboardInput( UINT32 *puiNewEvent ) else if( fAlt ) { - if( !fDisableMapInterfaceDueToBattle && !( gTacticalStatus.uiFlags & ENGAGED_IN_CONV ) ) + if( !fDisableMapInterfaceDueToBattle && !( gTacticalStatus.uiFlags & ENGAGED_IN_CONV )&& !is_networked ) { //if the game CAN be saved if( CanGameBeSaved() ) diff --git a/Tactical/Weapons.cpp b/Tactical/Weapons.cpp index 4f9acdcd..9970d3be 100644 --- a/Tactical/Weapons.cpp +++ b/Tactical/Weapons.cpp @@ -51,7 +51,7 @@ //forward declarations of common classes to eliminate includes class OBJECTTYPE; class SOLDIERTYPE; - +#include "connect.h" //rain //#define WEAPON_RELIABILITY_REDUCTION_PER_RAIN_INTENSITY 0 @@ -1924,9 +1924,16 @@ BOOLEAN UseGun( SOLDIERTYPE *pSoldier , INT16 sTargetGridNo ) return( FALSE ); } } - - - FireBulletGivenTarget( pSoldier, dTargetX, dTargetY, dTargetZ, pSoldier->usAttackingWeapon, (UINT16) (uiHitChance - uiDiceRoll), fBuckshot, FALSE ); + //hayden + if((is_server && pSoldier->ubID<120) || (!is_server && is_client && pSoldier->ubID<20) || (!is_server && !is_client) ) + { + FireBulletGivenTarget( pSoldier, dTargetX, dTargetY, dTargetZ, pSoldier->usAttackingWeapon, (UINT16) (uiHitChance - uiDiceRoll), fBuckshot, FALSE ); + } + else + { + FireBulletGivenTarget( pSoldier, dTargetX, dTargetY, dTargetZ, pSoldier->usAttackingWeapon, (UINT16) (uiHitChance - uiDiceRoll), fBuckshot, TRUE ); + } + //bottom one is fake (ie not in my control) ubVolume = Weapon[ pSoldier->usAttackingWeapon ].ubAttackVolume; @@ -5962,5 +5969,3 @@ INT8 GetAPsToReload( OBJECTTYPE *pObj ) - - diff --git a/Tactical/bullets.cpp b/Tactical/bullets.cpp index 29d96572..2c1e88b7 100644 --- a/Tactical/bullets.cpp +++ b/Tactical/bullets.cpp @@ -40,6 +40,10 @@ BULLET gBullets[ NUM_BULLET_SLOTS ]; UINT32 guiNumBullets = 0; BOOLEAN fTracer = FALSE; +//afp-start +int gXPATH[BULLET_TRACER_MAX_LENGTH]; // positions between bullet +int gYPATH[BULLET_TRACER_MAX_LENGTH]; // positions between bullet +//afp-end INT32 GetFreeBullet(void) { @@ -106,6 +110,10 @@ INT32 CreateBullet( UINT8 ubFirerID, BOOLEAN fFake, UINT16 usFlags,UINT16 fromIt DebugAttackBusy( String( "Creating a new bullet for %d. ABC now %d\n", ubFirerID, gTacticalStatus.ubAttackBusyCount) ); } + //afp-start each bullet carry its tail + for (int i = 0; i < BULLET_TRACER_MAX_LENGTH; i++) + pBullet->pNodes[i] = NULL; + //afp-end return( iBulletIndex ); } @@ -172,6 +180,15 @@ void RemoveBullet( INT32 iBullet ) { CHECKV( iBullet < NUM_BULLET_SLOTS ); + //afp-start + // remove any tail first if exists + for (int i = 0; i < BULLET_TRACER_MAX_LENGTH; i++) + if (gBullets[iBullet].pNodes[i] != NULL) + { + RemoveStructFromLevelNode(gBullets[ iBullet ].sGridNo, gBullets[iBullet].pNodes[i]); + gBullets[iBullet].pNodes[i] = NULL; + } + //afp-end // decrease soldier's bullet count if (gBullets[ iBullet ].fReal) @@ -275,6 +292,18 @@ void UpdateBullets( ) RemoveStruct( gBullets[ uiCount ].sGridNo, BULLETTILE2 ); } } + //afp-start + // remove old tail first if exists + FIXEDPT lastX = gBullets[uiCount].qCurrX; + FIXEDPT lastY = gBullets[uiCount].qCurrY; + FIXEDPT lastZ = gBullets[uiCount].qCurrZ; + for (int i = 0; i < BULLET_TRACER_MAX_LENGTH; i++) + if (gBullets[uiCount].pNodes[i] != NULL) + { + RemoveStructFromLevelNode(gBullets[ uiCount ].sGridNo, gBullets[uiCount].pNodes[i]); + gBullets[uiCount].pNodes[i] = NULL; + } + //afp-end MoveBullet( uiCount ); if ( gBullets[ uiCount ].fToDelete ) @@ -335,7 +364,56 @@ void UpdateBullets( ) pNode->sRelativeY = (INT16) FIXEDPT_TO_INT32( gBullets[ uiCount ].qCurrY ); pNode->sRelativeZ = (INT16) CONVERT_HEIGHTUNITS_TO_PIXELS( FIXEDPT_TO_INT32( gBullets[ uiCount ].qCurrZ ) ); + //afp-start - add new tail /tracer + if (gGameExternalOptions.gbBulletTracer) + { + if ((lastX != 0) || (lastY != 0)) + { + // qIncrX can be used to calculate slope and make the tracer longer if necessary + PointsPath((INT16) FIXEDPT_TO_INT32( gBullets[ uiCount ].qCurrX), + (INT16) FIXEDPT_TO_INT32( gBullets[ uiCount ].qCurrY), + (INT16) FIXEDPT_TO_INT32( lastX), + (INT16) FIXEDPT_TO_INT32( lastY)); + + // compute valid points allong the fire line + int pointsCount = 0; + for (int i = 0; i < BULLET_TRACER_MAX_LENGTH; i++) + { + pointsCount = i; + if (gXPATH[i] == 0) + if (gYPATH[i] == 0) + break; + } + if (pointsCount <= 0) + pointsCount = 30; + + + for (int i = 0; i < BULLET_TRACER_MAX_LENGTH; i++) + { + if (gXPATH[i] == 0) + if (gYPATH[i] == 0) + break; + + // add all points along the path between bullets as bullets + pNode = AddStructToTail( gBullets[ uiCount ].sGridNo, BULLETTILE1 ); + pNode->ubShadeLevel=DEFAULT_SHADE_LEVEL; + pNode->ubNaturalShadeLevel=DEFAULT_SHADE_LEVEL; + pNode->uiFlags |= ( LEVELNODE_USEABSOLUTEPOS | LEVELNODE_IGNOREHEIGHT ); + pNode->sRelativeX = gXPATH[i]; + pNode->sRelativeY = gYPATH[i]; + FIXEDPT relativeZ = lastZ - ((i + 1) * ((gBullets[ uiCount ].qCurrZ - lastZ) / (pointsCount))); + pNode->sRelativeZ = (INT16) CONVERT_HEIGHTUNITS_TO_PIXELS( FIXEDPT_TO_INT32( relativeZ)); + + // store structure pointer to clear image at the next bullet position + gBullets[uiCount].pNodes[i] = pNode; + } + } + } + //afp-end // Display shadow + // afp - no more shadow if tracer enabled + if (!gGameExternalOptions.gbBulletTracer) + { pNode = AddStructToTail( gBullets[ uiCount ].sGridNo, BULLETTILE2 ); pNode->ubShadeLevel=DEFAULT_SHADE_LEVEL; pNode->ubNaturalShadeLevel=DEFAULT_SHADE_LEVEL; @@ -343,6 +421,7 @@ void UpdateBullets( ) pNode->sRelativeX = (INT16) FIXEDPT_TO_INT32( gBullets[ uiCount ].qCurrX ); pNode->sRelativeY = (INT16) FIXEDPT_TO_INT32( gBullets[ uiCount ].qCurrY ); pNode->sRelativeZ = (INT16)gpWorldLevelData[ gBullets[ uiCount ].sGridNo ].sHeight; + } } } } @@ -582,3 +661,91 @@ void DeleteAllBullets( ) RecountBullets( ); } +//afp-start adapted function, no much time for cosmetics +void PointsPath(int sx1, int sy1, int ex2, int ey2) +{ + for (int i = 0; i < BULLET_TRACER_MAX_LENGTH; i++) + { + gXPATH[i] = 0; + gYPATH[i] = 0; + } + + int counter = 0; + gXPATH[counter] = sx1; + gYPATH[counter] = sy1; + + int x0 = sx1; + int y0 = sy1; + int x1 = ex2; + int y1 = ey2; + int dy = y1 - y0; + int dx = x1 - x0; + int stepx, stepy; + int gridX, gridY; + + if (dy < 0) + { + dy = -dy; + stepy = -1; + } + else + stepy = 1; + + if (dx < 0) + { + dx = -dx; + stepx = -1; + } + else + stepx = 1; + + dy <<= 1; + dx <<= 1; + gridX = x0 >> 3; + gridY = y0 >> 3; + + if ((sx1==ex2) &&(sy1=ey2)) + return; + + if (dx > dy) + { + int fraction = dy - (dx >> 1); + while (x0 != x1) + { + if (fraction >= 0) + { + y0 += stepy; + fraction -= dx; + } + x0 += stepx; + fraction += dy; + + counter++; + if (counter >= BULLET_TRACER_MAX_LENGTH) + return; + gXPATH[counter] = x0; + gYPATH[counter] = y0; + } + } + else + { + int fraction = dx - (dy >> 1); + while (y0 != y1) + { + if (fraction >= 0) + { + x0 += stepx; + fraction -= dy; + } + y0 += stepy; + fraction += dx; + counter++; + if (counter >= BULLET_TRACER_MAX_LENGTH) + return; + gXPATH[counter] = x0; + gYPATH[counter] = y0; + } + } + return; +} +//afp-end diff --git a/TacticalAI/AIMain.cpp b/TacticalAI/AIMain.cpp index cabdf5cc..57ee2fc4 100644 --- a/TacticalAI/AIMain.cpp +++ b/TacticalAI/AIMain.cpp @@ -11,6 +11,7 @@ #include "overhead.h" #include "math.h" #include "Event Pump.h" +#include "Soldier Control.h" #include "Overhead Types.h" #include "sys globals.h" #include "opplist.h" @@ -55,6 +56,8 @@ #include "cheats.h" #endif +#include "connect.h" + extern void PauseAITemporarily( void ); extern void UpdateEnemyUIBar( void ); extern void DisplayHiddenTurnbased( SOLDIERTYPE * pActingSoldier ); @@ -808,8 +811,16 @@ void StartNPCAI(SOLDIERTYPE *pSoldier) if(!gfAmIHost) return; #endif - //pSoldier->flags.uiStatusFlags |= SOLDIER_UNDERAICONTROL; - pSoldier->SetSoldierAsUnderAiControl( ); + ////pSoldier->flags.uiStatusFlags |= SOLDIER_UNDERAICONTROL; + //if (!(pSoldier->flags.uiStatusFlags & SOLDIER_PC)) + + //{ + //SetSoldierAsUnderAiControl( pSoldier ); + //} + + if (!is_networked) + pSoldier->SetSoldierAsUnderAiControl( ); + pSoldier->flags.fTurnInProgress = TRUE; diff --git a/TacticalAI/Movement.cpp b/TacticalAI/Movement.cpp index 6b543123..9b4a7aec 100644 --- a/TacticalAI/Movement.cpp +++ b/TacticalAI/Movement.cpp @@ -17,7 +17,7 @@ #include "Soldier macros.h" #include "Render Fun.h" #endif - +#include "connect.h" //forward declarations of common classes to eliminate includes class OBJECTTYPE; class SOLDIERTYPE; @@ -878,6 +878,24 @@ void HaltMoveForSoldierOutOfPoints(SOLDIERTYPE *pSoldier) return; } + if (is_networked) + { + EV_S_STOP_MERC SStopMerc; + + SStopMerc.sGridNo = pSoldier->sGridNo; + SStopMerc.ubDirection = pSoldier->ubDirection; + SStopMerc.usSoldierID = pSoldier->ubID; + SStopMerc.fset=TRUE; + SStopMerc.sXPos=pSoldier->sX; + SStopMerc.sYPos=pSoldier->sY; + + //AddGameEvent( S_STOP_MERC, 0, &SStopMerc ); //hayden. + if(pSoldier->ubID>=120) + return;//hayden + + if(is_client) + send_stop(&SStopMerc); + } // record that this merc can no longer animate and why... pSoldier->AdjustNoAPToFinishMove( TRUE ); diff --git a/TacticalAI/TacticalAI.vcproj b/TacticalAI/TacticalAI.vcproj index cd6ccbad..333bffdb 100644 --- a/TacticalAI/TacticalAI.vcproj +++ b/TacticalAI/TacticalAI.vcproj @@ -131,7 +131,7 @@ bVisible == -1 && !(gTacticalStatus.uiFlags&SHOW_ALL_MERCS) && !(pSoldier->ubMiscSoldierFlags & SOLDIER_MISC_XRAYED) ) { - continue; + //hayden + if(is_networked && pSoldier->bSide==0) + { + } + else + { + continue;// ie dont render + } } // Don't render guys if they are dead! diff --git a/TileEngine/Tactical Placement GUI.cpp b/TileEngine/Tactical Placement GUI.cpp index c54dd0ec..69208e8e 100644 --- a/TileEngine/Tactical Placement GUI.cpp +++ b/TileEngine/Tactical Placement GUI.cpp @@ -1,5 +1,7 @@ #include "builddefines.h" +// WANNE 2 + #ifdef PRECOMPILEDHEADERS #include "TileEngine All.h" #include "PreBattle Interface.h" @@ -43,6 +45,9 @@ #include "WordWrap.h" #include "Game Clock.h" #endif +#include "connect.h" +#include "saveloadscreen.h" + typedef struct MERCPLACEMENT { @@ -70,6 +75,7 @@ extern BOOLEAN GetOverheadMouseGridNo( INT16 *psGridNo ); extern UINT16 iOffsetHorizontal; extern UINT16 iOffsetVertical; +int islocked; UINT8 gubDefaultButton = CLEAR_BUTTON; BOOLEAN gfTacticalPlacementGUIActive = FALSE; @@ -119,6 +125,8 @@ void SelectNextUnplacedUnit(); BOOLEAN gfNorthValid, gfEastValid, gfSouthValid, gfWestValid; BOOLEAN gfChangedEntrySide = FALSE; + + void FindValidInsertionCode( UINT8 *pubStrategicInsertionCode ) { if( gMapInformation.sNorthGridNo == -1 && @@ -216,6 +224,7 @@ void CheckForValidMapEdge( UINT8 *pubStrategicInsertionCode ) void InitTacticalPlacementGUI() { + islocked=0;//hayden VOBJECT_DESC VObjectDesc; INT32 i, xp, yp; UINT8 ubFaceIndex; @@ -414,7 +423,8 @@ void InitTacticalPlacementGUI() MSYS_DefineRegion( &gMercPlacement[ i ].region, (UINT16)xp, (UINT16)yp, (UINT16)(xp + 54), (UINT16)(yp + 62), MSYS_PRIORITY_HIGH, 0, MercMoveCallback, MercClickCallback ); } - PlaceMercs(); + + if(!is_client)PlaceMercs();//hayden if( gubDefaultButton == GROUP_BUTTON ) { @@ -662,6 +672,39 @@ void EnsureDoneButtonStatus() } } +void lockui (bool unlock) //lock onluck ui for lan //hayden +{ + if(unlock==0 && islocked==0 && is_client) + { + islocked=1; + DisableButton( iTPButtons[ DONE_BUTTON ] ); + DisableButton( iTPButtons[ SPREAD_BUTTON ] ); + DisableButton( iTPButtons[ GROUP_BUTTON ] ); + DisableButton( iTPButtons[ CLEAR_BUTTON ] ); + + SGPRect CenterRect = { 100, 100, SCREEN_WIDTH - 100, 300 }; + DoMessageBox( MSG_BOX_BASIC_STYLE, MPServerMessage[8], guiCurrentScreen, MSG_BOX_FLAG_OK | MSG_BOX_FLAG_USE_CENTERING_RECT, DialogRemoved, &CenterRect ); + + //send loaded + send_loaded(); + } + + if(unlock) //oh yeah ! :) + { + islocked=3; + EnableButton( iTPButtons[ SPREAD_BUTTON ] ); + EnableButton( iTPButtons[ GROUP_BUTTON ] ); + EnableButton( iTPButtons[ CLEAR_BUTTON ] ); + + ButtonList[ iTPButtons[ GROUP_BUTTON ] ]->uiFlags &= ~BUTTON_CLICKED_ON; + ButtonList[ iTPButtons[ GROUP_BUTTON ] ]->uiFlags |= BUTTON_DIRTY; + gubDefaultButton = CLEAR_BUTTON; + PlaceMercs(); + gMsgBox.bHandled = MSG_BOX_RETURN_OK; //close if still open + + } +} + void TacticalPlacementHandle() { InputAtom InputEvent; @@ -669,6 +712,9 @@ void TacticalPlacementHandle() EnsureDoneButtonStatus(); RenderTacticalPlacementGUI(); + + if (is_networked) + lockui(0);//lockui before placement while clients loading //hayden if( gfRightButtonState ) { @@ -691,24 +737,42 @@ void TacticalPlacementHandle() case ENTER: if( ButtonList[ iTPButtons[ DONE_BUTTON ] ]->uiFlags & BUTTON_ENABLED ) { - KillTacticalPlacementGUI(); + if(!is_client)KillTacticalPlacementGUI(); + //if(is_client)send_donegui(0); only by mouse //hayden } break; case 'c': - ClearPlacementsCallback( ButtonList[ iTPButtons[ CLEAR_BUTTON ] ], MSYS_CALLBACK_REASON_LBUTTON_UP ); - break; + if(islocked!=1)ClearPlacementsCallback( ButtonList[ iTPButtons[ CLEAR_BUTTON ] ], MSYS_CALLBACK_REASON_LBUTTON_UP ); + break; case 'g': - GroupPlacementsCallback( ButtonList[ iTPButtons[ GROUP_BUTTON ] ], MSYS_CALLBACK_REASON_LBUTTON_UP ); - break; + if(islocked!=1)GroupPlacementsCallback( ButtonList[ iTPButtons[ GROUP_BUTTON ] ], MSYS_CALLBACK_REASON_LBUTTON_UP ); + break; case 's': - SpreadPlacementsCallback( ButtonList[ iTPButtons[ SPREAD_BUTTON ] ], MSYS_CALLBACK_REASON_LBUTTON_UP ); - break; + if(islocked!=1)SpreadPlacementsCallback( ButtonList[ iTPButtons[ SPREAD_BUTTON ] ], MSYS_CALLBACK_REASON_LBUTTON_UP ); + break; case 'x': if( InputEvent.usKeyState & ALT_DOWN ) { HandleShortCutExitState(); } break; + case 'l'://hayden + if( InputEvent.usKeyState & ALT_DOWN ) + { + if (is_networked) + { + KillTacticalPlacementGUI(); + DoQuickLoad(); + } + } + break; + case '7': + if (is_networked) + { + if(is_server) + manual_overide(); + } + break; } } } @@ -765,7 +829,12 @@ void TacticalPlacementHandle() } if( gfKillTacticalGUI == 1 ) { - KillTacticalPlacementGUI(); + if(is_client) + { + gfKillTacticalGUI = FALSE; + send_donegui(0); + } + if(!is_client)KillTacticalPlacementGUI(); } else if( gfKillTacticalGUI == 2 ) { @@ -966,6 +1035,8 @@ void MercMoveCallback( MOUSE_REGION *reg, INT32 reason ) void MercClickCallback( MOUSE_REGION *reg, INT32 reason ) { + if(islocked != 1)//hayden + { if( reason & MSYS_CALLBACK_REASON_LBUTTON_DWN ) { INT8 i; @@ -984,6 +1055,7 @@ void MercClickCallback( MOUSE_REGION *reg, INT32 reason ) } return; } + } } } } @@ -1178,11 +1250,26 @@ void PutDownMercPiece( INT32 iPlacement ) if( sGridNo != NOWHERE ) { ConvertGridNoToCellXY( sGridNo, &sCellX, &sCellY ); - pSoldier->EVENT_SetSoldierPosition( (FLOAT)sCellX, (FLOAT)sCellY ); + + FLOAT scX = (FLOAT)sCellX; + FLOAT scY = (FLOAT)sCellY;//hayden + if (is_networked) + { + pSoldier->EVENT_SetSoldierPosition( scX, scY ); + } + else + { + pSoldier->EVENT_SetSoldierPosition( (FLOAT)sCellX, (FLOAT)sCellY ); + } + + pSoldier->EVENT_SetSoldierDirection( ubDirection ); pSoldier->ubInsertionDirection = pSoldier->ubDirection; gMercPlacement[ iPlacement ].fPlaced = TRUE; gMercPlacement[ iPlacement ].pSoldier->bInSector = TRUE; +//hayden + if(is_client)send_gui_pos(pSoldier, scX, scY); + if(is_client)send_gui_dir(pSoldier, ubDirection); } } diff --git a/TileEngine/TileEngine.vcproj b/TileEngine/TileEngine.vcproj index 1a7af45c..ee17f512 100644 --- a/TileEngine/TileEngine.vcproj +++ b/TileEngine/TileEngine.vcproj @@ -130,7 +130,7 @@ FavorSizeOrSpeed="1" OptimizeForProcessor="3" OptimizeForWindowsApplication="TRUE" - AdditionalIncludeDirectories=""..\Standard Gaming Platform";..\;..\Tactical;..\Utils;..\tacticalai;..\Editor;..\strategic;..\Laptop;.\" + AdditionalIncludeDirectories="..\Multiplayer;"..\Standard Gaming Platform";..\;..\Tactical;..\Utils;..\tacticalai;..\Editor;..\strategic;..\Laptop;.\" PreprocessorDefinitions="CALLBACKTIMER;PRECOMPILEDHEADERS;NDEBUG;WIN32;_WINDOWS;JA2;XML_STATIC;CINTERFACE" StringPooling="TRUE" RuntimeLibrary="0" @@ -287,7 +287,7 @@ #endif +#include "connect.h" + #ifdef JA2EDITOR #include "Soldier Init List.h" extern SOLDIERINITNODE *gpSelected; @@ -1180,6 +1182,7 @@ void RenderOverheadOverlays() { //loop through all soldiers. end = MAX_NUM_SOLDIERS; } + if(is_networked)end = MAX_NUM_SOLDIERS; for( i = 0; i < end; i++ ) { @@ -1200,7 +1203,14 @@ void RenderOverheadOverlays() if( !gfTacticalPlacementGUIActive && pSoldier->bLastRenderVisibleValue == -1 && !(gTacticalStatus.uiFlags&SHOW_ALL_MERCS) ) { - continue; + //hayden + if(is_networked && pSoldier->bSide==0) + { + } + else + { + continue;// ie dont render + } } if ( pSoldier->sGridNo == NOWHERE ) @@ -1263,6 +1273,16 @@ void RenderOverheadOverlays() #endif if( !gfTacticalPlacementGUIActive ) { //normal + if(is_networked) + { + if(pSoldier->bTeam!=0) + { + if(pSoldier->bSide==1)Blt8BPPDataTo16BPPBufferTransparent((UINT16*)pDestBuf, uiDestPitchBYTES, hVObject, sX, sY, 1 ); + if(pSoldier->bSide==0)Blt8BPPDataTo16BPPBufferTransparent((UINT16*)pDestBuf, uiDestPitchBYTES, hVObject, sX, sY, 3 ); + } + else Blt8BPPDataTo16BPPBufferTransparent((UINT16*)pDestBuf, uiDestPitchBYTES, hVObject, sX, sY, pSoldier->bTeam ); + } + else Blt8BPPDataTo16BPPBufferTransparent((UINT16*)pDestBuf, uiDestPitchBYTES, hVObject, sX, sY, pSoldier->bTeam ); RegisterBackgroundRect(BGND_FLAG_SINGLE, NULL, sX, sY, (INT16)(sX + 3), (INT16)(sY + 9)); } @@ -1287,6 +1307,16 @@ void RenderOverheadOverlays() } else { //normal + if(is_networked) + { + if(pSoldier->bTeam!=0) + { + if(pSoldier->bSide==1)continue;//dont render enemy + if(pSoldier->bSide==0)Blt8BPPDataTo16BPPBufferTransparent((UINT16*)pDestBuf, uiDestPitchBYTES, hVObject, sX, sY, 3 ); + } + else Blt8BPPDataTo16BPPBufferTransparent((UINT16*)pDestBuf, uiDestPitchBYTES, hVObject, sX, sY, pSoldier->bTeam ); + } + else Blt8BPPDataTo16BPPBufferTransparent((UINT16*)pDestBuf, uiDestPitchBYTES, hVObject, sX, sY, pSoldier->bTeam ); RegisterBackgroundRect(BGND_FLAG_SINGLE, NULL, sX, sY, (INT16)(sX + 3), (INT16)(sY + 9)); } diff --git a/Utils/Event Pump.cpp b/Utils/Event Pump.cpp index f541f637..19b8de00 100644 --- a/Utils/Event Pump.cpp +++ b/Utils/Event Pump.cpp @@ -1224,7 +1224,7 @@ BOOLEAN ExecuteGameEvent( EVENT *pEvent ) // Call soldier function DebugMsg( TOPIC_JA2, DBG_LEVEL_3, String("Event Pump: Stop Merc at Gridno %d", SStopMerc.sGridNo )); - pSoldier->EVENT_StopMerc( SStopMerc.sGridNo, SStopMerc.bDirection ); + pSoldier->EVENT_StopMerc( SStopMerc.sGridNo, SStopMerc.ubDirection ); break; diff --git a/Utils/Event Pump.h b/Utils/Event Pump.h index 13898e92..3c43fd3f 100644 --- a/Utils/Event Pump.h +++ b/Utils/Event Pump.h @@ -2,6 +2,7 @@ #define EVENT_PROCESSOR_H #include "Event Manager.h" +#include "Overhead Types.h" #define NETWORK_PATH_DATA_SIZE 6 @@ -164,6 +165,8 @@ typedef struct BOOLEAN fHit; UINT8 ubSpecial; UINT8 ubLocation; + INT32 iBullet; + BOOLEAN fStopped; } EV_S_WEAPONHIT; @@ -178,6 +181,7 @@ typedef struct UINT16 usStructureID; INT32 iImpact; INT32 iBullet; + BOOLEAN fStopped;//hayden } EV_S_STRUCTUREHIT; @@ -187,11 +191,14 @@ typedef struct UINT16 usStructureID; BOOLEAN fBlowWindowSouth; BOOLEAN fLargeForce; + INT8 ubAttackerID; + INT32 iBullet; } EV_S_WINDOWHIT; typedef struct { UINT8 ubAttackerID; + INT32 iBullet; } EV_S_MISS; typedef struct @@ -209,10 +216,11 @@ typedef struct { UINT16 usSoldierID; UINT32 uiUniqueId; - INT8 bDirection; + UINT8 ubDirection; INT16 sGridNo; INT16 sXPos; INT16 sYPos; + BOOLEAN fset; } EV_S_STOP_MERC; @@ -221,26 +229,34 @@ typedef struct typedef struct { UINT8 usSoldierID; - UINT32 uiUniqueId; - UINT8 usPathDataSize; // Size of Path +// UINT32 uiUniqueId; + UINT16 usPathDataSize; // Size of Path INT16 sAtGridNo; // Owner merc is at this tile when sending packet - UINT8 usCurrentPathIndex; // Index the owner of the merc is at when sending packet - UINT8 usPathData[ NETWORK_PATH_DATA_SIZE ]; // make define // Next X tile to go to - UINT8 ubNewState; // new movment Anim + UINT16 usCurrentPathIndex; // Index the owner of the merc is at when sending packet + UINT16 usPathData[ MAX_PATH_LIST_SIZE ]; // make define // Next X tile to go to + UINT16 ubNewState; // new movment Anim + INT16 sDestGridNo; // INT8 bActionPoints; // INT8 bBreath; // current breath value // INT8 bDesiredDirection; + // maybe send current action & breath points } EV_S_SENDPATHTONETWORK; typedef struct { UINT8 usSoldierID; - UINT32 uiUniqueId; + //UINT32 uiUniqueId; INT16 sAtGridNo; // Owner merc is at this tile when sending packet INT8 bActionPoints; // current A.P. value INT8 bBreath; // current breath value + //hayden + INT8 bLife; + INT8 bBleeding; + UINT16 usTactialTurnLimitCounter; + UINT16 usTactialTurnLimitMax; + UINT8 ubDirection; } EV_S_UPDATENETWORKSOLDIER; diff --git a/Utils/Multi Language Graphic Utils.cpp b/Utils/Multi Language Graphic Utils.cpp index abb2aa4f..6af13f4f 100644 --- a/Utils/Multi Language Graphic Utils.cpp +++ b/Utils/Multi Language Graphic Utils.cpp @@ -89,6 +89,9 @@ BOOLEAN GetMLGFilename( SGPFILENAME filename, UINT16 usMLGGraphicID ) case MLG_TITLETEXT: sprintf( filename, "LOADSCREENS\\titletext.sti" ); return TRUE; + case MLG_TITLETEXT_MP: + sprintf( filename, "LOADSCREENS\\titletext_mp.sti" ); + return TRUE; case MLG_TOALUMNI: sprintf( filename, "LAPTOP\\ToAlumni.sti" ); return TRUE; @@ -197,6 +200,9 @@ BOOLEAN GetMLGFilename( SGPFILENAME filename, UINT16 usMLGGraphicID ) case MLG_TITLETEXT: sprintf( filename, "GERMAN\\titletext_german.sti" ); return TRUE; + case MLG_TITLETEXT_MP: + sprintf( filename, "GERMAN\\titletext_mp_german.sti" ); + return TRUE; case MLG_TOALUMNI: sprintf( filename, "GERMAN\\ToAlumni_german.sti" ); return TRUE; @@ -337,6 +343,9 @@ BOOLEAN GetMLGFilename( SGPFILENAME filename, UINT16 usMLGGraphicID ) case MLG_TITLETEXT: sprintf( filename, "%s\\titletext_%s.sti", zLanguage, zLanguage ); break; + case MLG_TITLETEXT_MP: + sprintf( filename, "%s\\titletext_mp_%s.sti", zLanguage, zLanguage ); + return TRUE; case MLG_TOALUMNI: sprintf( filename, "%s\\ToAlumni_%s.sti", zLanguage, zLanguage ); break; @@ -445,6 +454,9 @@ BOOLEAN GetMLGFilename( SGPFILENAME filename, UINT16 usMLGGraphicID ) case MLG_TITLETEXT: sprintf( filename, "LOADSCREENS\\titletext.sti" ); return TRUE; + case MLG_TITLETEXT_MP: + sprintf( filename, "LOADSCREENS\\titletext_mp.sti" ); + return TRUE; case MLG_TOALUMNI: sprintf( filename, "LAPTOP\\ToAlumni.sti" ); return TRUE; diff --git a/Utils/Multi Language Graphic Utils.h b/Utils/Multi Language Graphic Utils.h index 0ba99c6d..b8829352 100644 --- a/Utils/Multi Language Graphic Utils.h +++ b/Utils/Multi Language Graphic Utils.h @@ -37,6 +37,7 @@ enum MLG_TOSTATS, MLG_WARNING, MLG_YOURAD13, + MLG_TITLETEXT_MP, // ROMAN: Additional multiplayer text }; BOOLEAN GetMLGFilename( SGPFILENAME filename, UINT16 usMLGGraphicID ); diff --git a/Utils/Text.h b/Utils/Text.h index 354c6fed..43ce851c 100644 --- a/Utils/Text.h +++ b/Utils/Text.h @@ -258,6 +258,9 @@ enum #ifdef JA2BETAVERSION MSG_END_TURN_AUTO_SAVE, #endif + MSG_MPSAVEDIRECTORY,//84 + MSG_CLIENT + }; extern STR16 pMessageStrings[]; @@ -1564,6 +1567,11 @@ enum //CHRISL: NewInv messages extern STR16 NewInvMessage[]; +// WANNE - MP: New multiplayer messages +extern STR16 MPServerMessage[]; +extern STR16 MPClientMessage[]; +extern STR16 MPHelp[]; + enum { NIV_CAN_NOT_PICKUP, diff --git a/Utils/Utils.vcproj b/Utils/Utils.vcproj index e4a6e5ae..947449b2 100644 --- a/Utils/Utils.vcproj +++ b/Utils/Utils.vcproj @@ -76,7 +76,7 @@ (|S|p|a|c|e) - -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. - - EX: L"Clears all the mercs' positions,\nand allows you to re-enter them manually." - - Would appear as: - - Clears all the mercs' positions, - and allows you to re-enter them manually. - - NOTE: It is important that you don't pad the characters adjacent to the \n with spaces. If we did this - 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." - - Would appear as: (the second line is moved in a character) - - Clears all the mercs' positions, - and allows you to re-enter them manually. - - -@@@ NOTATION -************ - - 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. - -!!! NOTATION -************ - - As described above, the "!!!" notation should be used by Topware to ask questions and address problems as - SirTech uses the "@@@" notation. - -*/ - -STR16 pCreditsJA2113[] = -{ - L"@T,{;Разработчики JA2 v1.13", - L"@T,C144,R134,{;Программирование", - L"@T,C144,R134,{;Графика и звук", - L"@};(Многое было взято из других модов!)", - L"@T,C144,R134,{;Предметы", - L"@T,C144,R134,{;Также помогали", - L"@};(И многие другие, предложившие хорошие идеи и высказавшие важные замечания!)", -}; - -CHAR16 ItemNames[MAXITEMS][80] = -{ - L"" -}; - - -CHAR16 ShortItemNames[MAXITEMS][80] = -{ - L"" -}; - -// Different weapon calibres -// CAWS is Close Assault Weapon System and should probably be left as it is -// NATO is the North Atlantic Treaty Organization -// WP is Warsaw Pact -// cal is an abbreviation for calibre -CHAR16 AmmoCaliber[MAXITEMS][20];// = -//{ -// L"0", -// L",38 кал", -// L"9мм", -// L",45 кал", -// L",357 кал", -// L"12 кал", -// L"ОББ", -// L"5,45мм", -// L"5,56мм", -// L"7,62мм НАТО", -// L"7,62мм ВД", -// L"4,7мм", -// L"5,7мм", -// L"Монстр", -// L"Ракета", -// L"", // дротик -// L"", // пламя -//// L".50 cal", // barrett -//// L"9mm Hvy", // Val silent -//}; - -// 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 -// WP is Warsaw Pact -// cal is an abbreviation for calibre -CHAR16 BobbyRayAmmoCaliber[MAXITEMS][20] ;//= -//{ -// L"0", -// L",38 кал", -// L"9мм", -// L",45 кал", -// L",357 кал", -// L"12 кал", -// L"ОББ", -// L"5,45мм", -// L"5,56мм", -// L"7,62мм Н.", -// L"7,62мм ВД", -// L"4,7мм", -// L"5.7мм", -// L"Монстр", -// L"Ракета", -// L"", // дротик -//// L"", // flamethrower -//// L".50 cal", // barrett -//// L"9mm Hvy", // Val silent -//}; - - -CHAR16 WeaponType[][30] = -{ - L"", //Other - L"Пистолет", //Pistol - L"Авт.пистолет", //MP //'Автоматический пистолет' - L"ПП", //SMG //'Пистолет-пулемет' - L"Винтовка", //Rifle - L"Сн.винтовка", //Sniper rifle //'Снайперская винтовка' - L"Шт.винтовка", //Assault rifle //'Штурмовая винтовка' - L"Ручной пулемет", //LMG //'Ручной пулемет' - L"Ружье" //Shotgun //'Гладкоствольное ружье' -}; - -CHAR16 TeamTurnString[][STRING_LENGTH] = -{ - L"Ход Игрока", // player's turn - L"Ход Противника", - L"Ход Тварей", - L"Ход Ополчения", - L"Ход Гражданских" - // planning turn -}; - -CHAR16 Message[][STRING_LENGTH] = -{ - L"", - - // In the following 8 strings, the %s is the merc's name, and the %d (if any) is a number. - - L"%s получает ранение в голову и теряет в интеллекте!", - L"%s получает ранение в плечо и теряет в ловкости!", - L"%s получает ранение в грудь и теряет в силе!", - L"%s получает ранение в ногу и теряет в проворности!", - L"%s получает ранение в голову и теряет %d очков интеллекта!", - L"%s получает ранение в плечо и теряет %d очков ловкости!", - L"%s получает ранение в грудь и теряет %d очков силы!", - L"%s получает ранение в ногу и теряет %d очков проворности!", - L"Перехват!", - - // The first %s is a merc's name, the second is a string from pNoiseVolStr, - // the third is a string from pNoiseTypeStr, and the last is a string from pDirectionStr - - L"", //OBSOLETE - L"К вам на помощь прибыло подкрепление!", - - // In the following four lines, all %s's are merc names - - L"%s перезаряжает оружие.", - L"%s недостаточно очков действия!", - L"%s оказывает первую помощь (любая клавиша - отмена).", - L"%s и %s оказывают первую помощь (любая клавиша - отмена).", - // the following 17 strings are used to create lists of gun advantages and disadvantages - // (separated by commas) - L"надежен", - L"ненадежен", - L"простой ремонт", - L"сложный ремонт", - L"большой урон", - L"малый урон", - L"скорострельный", - L"нескоростр.", - L"дальний бой", - L"ближний бой", - L"легкий", - L"тяжелый", - L"компактный", - L"очередями", - L"", //нет отсечки очереди - L"бол.магазин", - L"мал.магазин", - - // In the following two lines, all %s's are merc names - - L"%s: камуфляжная краска стерлась.", - L"%s: камуфляжная краска смылась.", - - // The first %s is a merc name and the second %s is an item name - - L"Второе оружие: закончились патроны!", - L"%s крадет %s.", - - // The %s is a merc name - - L"%s: оружие не стреляет очередями.", - - L"Уже установлено!", //не используется, применялось при приаттачивании аттача когда такой же уже приаттачен - L"Объединить?", //используется если предметом-аттачем на курсоре кликнуть на предмет, лежащий в слоте руки - - // Both %s's are item names - - L"Нельзя присоединить %s к %s.", - - L"Ничего", - L"Разрядить", - L"Навеска", - - //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"Нельзя использовать %s и %s одновременно.", - - L"Этот предмет можно присоединить к другим предметам, поместив его в одно из четырех мест для приспособлений.", - L"Этот предмет можно присоединить к другим предметам, поместив его в одно из четырех мест для приспособлений. (Однако эти предметы несовместимы)", - L"В секторе еще остались враги!", - L"%s требует полную оплату, нужно заплатить еще %s", - L"%s: попадание в голову!", - L"Покинуть битву?", - L"Это несъемное приспособление. Установить его?", - L"%s чувствует прилив энергии!", - L"%s поскальзывается на стеклянных шариках!", - L"%s не удалось отобрать %s у врага!", - L"%s чинит %s", - L"Перехватили ход: ", //при перехвате хода у врага - L"Сдаться?", - L"Человек отверг вашу помощь.", - L"Вам это надо?", //появляется при попытке перевязать жука или кошку - L"Чтобы воспользоваться вертолетом Небесного Всадника выберите 'Машина/Вертолет'.", - L"%s успевает зарядить только одно оружие.", //%s only had enough time to reload ONE gun - L"Ход Кошек-Убийц", //Bloodcats' turn - L"автоматический", //full auto - L"неавтоматический", //no full auto - L"точный", //accurate - L"неточный", //inaccurate - L"нет одиночных", //no semi auto - L"Враг обобран до нитки!", - L"У врага в руках ничего нет!", -}; - - -// the names of the towns in the game - -CHAR16 pTownNames[MAX_TOWNS][MAX_TOWN_NAME_LENGHT] = -{ - L"", - L"Омерта", - L"Драссен", - L"Альма", - L"Грам", - L"Тикса", - L"Камбрия", - L"Сан-Мона", - L"Эстони", - L"Орта", - L"Балайм", - L"Медуна", - L"Читзена", -}; - -// the types of time compression. For example: is the timer paused? at normal speed, 5 minutes per second, etc. -// min is an abbreviation for minutes - -STR16 sTimeStrings[] = -{ - L"Пауза", - L"Норма", //есть подозрение, что в игре этого не увидиш - L"5 мин", - L"30 мин", - L"60 мин", - L"6 часов", //есть подозрение, что в игре этого не увидиш -}; - - -// 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[] = -{ - L"Отряд 1", - L"Отряд 2", - L"Отряд 3", - L"Отряд 4", - L"Отряд 5", - L"Отряд 6", - L"Отряд 7", - L"Отряд 8", - L"Отряд 9", - L"Отряд 10", - L"Отряд 11", - L"Отряд 12", - L"Отряд 13", - L"Отряд 14", - L"Отряд 15", - L"Отряд 16", - L"Отряд 17", - L"Отряд 18", - L"Отряд 19", - L"Отряд 20", - L"На службе", // on active duty //SB: коряво - L"Медик", // оказывает медпомощь - L"Пациент", //принимает медпомощь - L"Транспорт", // in a vehicle - L"В пути", //транзитом - сокращение - L"Ремонт", // ремонтируются - L"Практика", // тренируются - L"Ополчение", //готовят восстание среди горожан - L"Тренер", // training a teammate - L"Ученик", // being trained by someone else - L"Мертв", // мертв - L"Недеесп.", // abbreviation for incapacitated - L"В плену", // Prisoner of war - captured - L"Госпиталь", // patient in a hospital - L"Пуст", // Vehicle is empty -}; - - -STR16 pMilitiaString[] = -{ - L"Ополчение", // the title of the militia box - L"Запас", //the number of unassigned militia troops - L"Нельзя перераспределять ополчение, когда враг находится в этом районе!", -}; - - -STR16 pMilitiaButtonString[] = -{ - L"Авто", // auto place the militia troops for the player - L"Готово", // done placing militia troops -}; - -STR16 pConditionStrings[] = -{ - L"Отличное", //состояние солдата..отличное здоровье - L"Хорошее", //хорошее здоровье - L"Сносное", //нормальное здоровье - L"Ранен", //раны - L"Устал", // усталый - L"Кровотечение", // истекает кровью - L"Без сознания", // в обмороке - L"Умирает", //умирает - L"Мертв", // мертв -}; - -STR16 pEpcMenuStrings[] = -{ - L"Сражаться", // set merc on active duty //это строки из меню ТОЛЬКО для эскортируемых - L"Пациент", // set as a patient to receive medical aid - L"Транспорт", // tell merc to enter vehicle - L"Без эскорта", // охрана покидает героя - L"Отмена", // выход из этого меню -}; - - -// look at pAssignmentString above for comments - -STR16 pPersonnelAssignmentStrings[] = -{ - L"Отряд 1", - L"Отряд 2", - L"Отряд 3", - L"Отряд 4", - L"Отряд 5", - L"Отряд 6", - L"Отряд 7", - L"Отряд 8", - L"Отряд 9", - L"Отряд 10", - L"Отряд 11", - L"Отряд 12", - L"Отряд 13", - L"Отряд 14", - L"Отряд 15", - L"Отряд 16", - L"Отряд 17", - L"Отряд 18", - L"Отряд 19", - L"Отряд 20", - L"На службе", - L"Медик", - L"Пациент", - L"Транспорт", - L"В пути", - L"Ремонт", - L"Практика", - L"Ополчение", - L"Тренер", - L"Ученик", - L"Мертв", - L"Недеесп.", - L"В плену", - L"Госпиталь", - L"Пуст", // Vehicle is empty -}; - - -// refer to above for comments - -STR16 pLongAssignmentStrings[] = -{ - L"Отряд 1", - L"Отряд 2", - L"Отряд 3", - L"Отряд 4", - L"Отряд 5", - L"Отряд 6", - L"Отряд 7", - L"Отряд 8", - L"Отряд 9", - L"Отряд 10", - L"Отряд 11", - L"Отряд 12", - L"Отряд 13", - L"Отряд 14", - L"Отряд 15", - L"Отряд 16", - L"Отряд 17", - L"Отряд 18", - L"Отряд 19", - L"Отряд 20", - L"На службе", - L"Медик", - L"Пациент", - L"Транспорт", - L"В пути", - L"Ремонт", - L"Практика", - L"Ополчение", - L"Тренер", - L"Ученик", - L"Мертв", - L"Недеесп.", - L"В плену", - L"Госпиталь", // patient in a hospital - L"Пуст", // Vehicle is empty -}; - - -// the contract options - -STR16 pContractStrings[] = -{ - L"Изменение контракта:", - L"", // a blank line, required - L"Продлить на 1 день", // offer merc a one day contract extension - L"Продлить на 7 дней", // 1 week - L"Продлить на 14 дней", // 2 week - L"Уволить", // end merc's contract - L"Отмена", // stop showing this menu -}; - -STR16 pPOWStrings[] = -{ - L"В плену", //an acronym for Prisoner of War - L"??", -}; - -STR16 pLongAttributeStrings[] = -{ - L"СИЛА", - L"ЛОВКОСТЬ", - L"ПРОВОРНОСТЬ", - L"ИНТЕЛЛЕКТ", - L"МЕТКОСТЬ", - L"МЕДИЦИНА", - L"МЕХАНИКА", - L"ЛИДЕРСТВО", - L"ВЗРЫВЧАТКА", - L"УРОВЕНЬ", -}; - -STR16 pInvPanelTitleStrings[] = -{ - L"Броня", // the armor rating of the merc - L"Вес", // the weight the merc is carrying //'Груз' - L"Камуф.", // the merc's camouflage rating //надо поменять местами броня и камуфляж для окна инвенторя наемника - L"Камуфляж:", - L"Броня:", -}; - -STR16 pShortAttributeStrings[] = -{ - L"Прв", // the abbreviated version of : agility - L"Лов", // dexterity - L"Сил", // strength - L"Лид", // leadership - L"Инт", // wisdom - L"Опт", // experience level - L"Мет", // marksmanship skill - L"Взр", // explosive skill - L"Мех", // mechanical skill - L"Мед", // medical skill -}; - - -STR16 pUpperLeftMapScreenStrings[] = -{ - L"Назначение", // the mercs current assignment - L"Контракт", // the contract info about the merc - L"Здоровье", // the health level of the current merc - L"Мораль", // the morale of the current merc - L"Сост.", // the condition of the current vehicle - L"Бензин", // the fuel level of the current vehicle -}; - -STR16 pTrainingStrings[] = -{ - L"Тренинг", // tell merc to train self - L"Ополчение", // tell merc to train town - L"Тренер", // tell merc to act as trainer - L"Ученик", // tell merc to be train by other -}; - -STR16 pGuardMenuStrings[] = -{ - L"Скоростр.:", // the allowable rate of fire for a merc who is guarding - L" Агрессивная атака", // the merc can be aggressive in their choice of fire rates - L" Беречь патроны", // conserve ammo - L" Воздержаться от стрельбы", // fire only when the merc needs to - L"Другие параметры:", // other options available to merc - L" Может отступить", // merc can retreat - L" Может искать укрытие", // merc is allowed to seek cover - L" Может помочь команде", // merc can assist teammates - L"Готово", // done with this menu - L"Отмена", // cancel this menu -}; - -// This string has the same comments as above, however the * denotes the option has been selected by the player - -STR16 pOtherGuardMenuStrings[] = -{ - L"Скоростр.:", - L" *Агрессивная атака*", - L" *Беречь патроны*", - L" *Воздержаться от стрельбы*", - L"Другие параметры:", - L" *Может отступить*", - L" *Может искать укрытие*", - L" *Может помочь команде*", - L"Готово", - L"Отмена", -}; - -STR16 pAssignMenuStrings[] = -{ - L"На службе", // merc is on active duty - L"Медик", // the merc is acting as a doctor - L"Пациент", // the merc is receiving medical attention - L"Машина", // the merc is in a vehicle - L"Ремонт", // the merc is repairing items - L"Обучение", // the merc is training //обучение - L"Отмена", // cancel this menu -}; - -//lal -STR16 pMilitiaControlMenuStrings[] = -{ - L"В атаку", // set militia to aggresive - L"Держать оборону", // set militia to stationary - L"Отступать", // retreat militia - L"За мной", // retreat militia - L"Ложись", // retreat militia - L"В укрытие", - L"Все в атаку", - L"Всем держать оборону", - L"Всем отступать", - L"Все за мной", - L"Всем рассеяться", - L"Всем залечь", - L"Всем в укрытие", - //L"Всем искать предметы", - L"Отмена", // cancel this menu -}; - -//STR16 pTalkToAllMenuStrings[] = -//{ -// L"Attack", // set militia to aggresive -// L"Hold Position", // set militia to stationary -// L"Retreat", // retreat militia -// L"Come to me", // retreat militia -// L"Get down", // retreat militia -// L"Cancel", // cancel this menu -//}; - -STR16 pRemoveMercStrings[] = -{ - L"Убрать бойца", // remove dead merc from current team - L"Отмена", -}; - -STR16 pAttributeMenuStrings[] = -{ - L"Сила", - L"Ловкость", - L"Проворность", - L"Здоровье", - L"Меткость", - L"Медицина", - L"Механика", - L"Лидерство", - L"Взрывчатка", - L"Отмена", -}; - -STR16 pTrainingMenuStrings[] = -{ - L"Практика", // train yourself - L"Ополчение", // train the town - L"Тренер", // train your teammates - L"Ученик", // be trained by an instructor - L"Отмена", // cancel this menu -}; - - -STR16 pSquadMenuStrings[] = -{ - L"Отряд 1", - L"Отряд 2", - L"Отряд 3", - L"Отряд 4", - L"Отряд 5", - L"Отряд 6", - L"Отряд 7", - L"Отряд 8", - L"Отряд 9", - L"Отряд 10", - L"Отряд 11", - L"Отряд 12", - L"Отряд 13", - L"Отряд 14", - L"Отряд 15", - L"Отряд 16", - L"Отряд 17", - L"Отряд 18", - L"Отряд 19", - L"Отряд 20", - L"Отмена", -}; - -STR16 pPersonnelTitle[] = -{ - L"Команда", // the title for the personnel screen/program application -}; - -STR16 pPersonnelScreenStrings[] = -{ - L"Здоровье:", // health of merc - L"Проворность:", - L"Ловкость:", - L"Сила:", - L"Лидерство:", - L"Интеллект:", - L"Опыт:", // experience level - L"Меткость:", - L"Механика:", - L"Взрывчатка:", - L"Медицина:", - L"Мед. депозит:", // amount of medical deposit put down on the merc - L"До конца контракта:", // cost of current contract - L"Убил врагов:", // number of kills by merc - L"Помог убить:", // number of assists on kills by merc - L"Гонорар за день:", // daily cost of merc - L"Общая цена услуг:", // total cost of merc - L"Контракт:", // cost of current contract - L"У вас на службе:", // total service rendered by merc - L"Задолж. жалования:", // amount left on MERC merc to be paid - L"Процент попаданий:", // percentage of shots that hit target - L"Боев:", // number of battles fought - L"Ранений:", // number of times merc has been wounded - L"Навыки:", - L"Нет навыков", -}; - - -//These string correspond to enums used in by the SkillTrait enums in SoldierProfileType.h -STR16 gzMercSkillText[] = -{ - L"Нет навыка", - L"Взлом замков", - L"Рукопашный бой", - L"Электроника", - L"Ночные операции", - L"Метание", - L"Инструктор", - L"Тяжелое оружие", - L"Авт. оружие", - L"Скрытность", - L"Стрельба с двух рук", - L"Воровство", - L"Боевые искусства", - L"Холодное оружие", - L"Снайпер", - L"Камуфляж", - L"Камуфляж (Город)", - L"Камуфляж (Пустыня)", - L"Камуфляж (Снег)", - L"(Эксперт)", -}; - - -// This is pop up help text for the options that are available to the merc - -STR16 pTacticalPopupButtonStrings[] = -{ - L"Встать/Идти (|S)", - L"Присесть/Гусиный шаг (|C)", - L"Стоять/Бежать (|R)", - L"Лечь/Ползти (|P)", - L"Поворот (|L)", - L"Действие", - L"Поговорить", - L"Осмотреть (|C|t|r|l)", - - // Pop up door menu - L"Открыть", - L"Искать ловушки", - L"Вскрыть отмычками", - L"Открыть cилой", - L"Обезвредить", - L"Запереть", - L"Отпереть", - L"Использовать заряд взрывчатки", - L"Взломать ломом", - L"Отмена (|E|s|c)", - L"Закрыть", -}; - -// Door Traps. When we examine a door, it could have a particular trap on it. These are the traps. - -STR16 pDoorTrapStrings[] = -{ - L"нет ловушки", - L"бомба-ловушка", - L"электроловушка", - L"сирена", - L"сигнализация" -}; - -// Contract Extension. These are used for the contract extension with AIM mercenaries. - -STR16 pContractExtendStrings[] = -{ - L"1 день", - L"7 дней", - L"14 дней", -}; - -// On the map screen, there are four columns. This text is popup help text that identifies the individual columns. - -STR16 pMapScreenMouseRegionHelpText[] = -{ - L"Выбрать наемника", - L"Отдать приказ", - L"Проложить путь движения", - L"Контракт наемника (|C)", - L"Местонахождение бойца", - L"Спать", -}; - -// volumes of noises - -STR16 pNoiseVolStr[] = -{ - L"ТИХИЙ", - L"ЧЕТКИЙ", - L"ГРОМКИЙ", - L"ОЧЕНЬ ГРОМКИЙ" -}; - -// types of noises - -STR16 pNoiseTypeStr[] = // OBSOLETE -{ - L"НЕЗНАКОМЫЙ", - L"ЗВУК ШАГОВ", - L"СКРИП", - L"ВСПЛЕСК", - L"УДАР", - L"ВЫСТРЕЛ", - L"ВЗРЫВ", - L"КРИК", - L"УДАР", - L"УДАР", - L"ЗВОН", - L"ГРОХОТ" -}; - -// Directions that are used to report noises - -STR16 pDirectionStr[] = -{ - L"c СЕВЕРО-ВОСТОКА", - L"c ВОСТОКА", - L"c ЮГО-ВОСТОКА", - L"c ЮГА", - L"c ЮГО-ЗАПАДА", - L"c ЗАПАДА", - L"c СЕВЕРО-ЗАПАДА", - L"c СЕВЕРА" -}; - -// These are the different terrain types. - -STR16 pLandTypeStrings[] = -{ - L"Город", - L"Дорога", - L"Равнина", - L"Пустыня", - L"Прерия", - L"Лес", - L"Болото", - L"Вода", - L"Холмы", - L"Непроходимо", - L"Река", //river from north to south - L"Река", //river from east to west - L"Чужая страна", - //NONE of the following are used for directional travel, just for the sector description. - L"Тропики", - L"Ферма", - L"Поля, дорога", - L"Леса, дорога", - L"Ферма, дорога", - L"Тропики, дорога", - L"Леса, дорога", - L"Побережье", - L"Горы, дорога", - L"Берег, дорога", - L"Пустыня, дорога", - L"Болота, дорога", - L"Прерия, ПВО", - L"Пустыня, ПВО", - L"Тропики, ПВО", - L"Медуна, ПВО", - - //These are descriptions for special sectors - L"Госпиталь Камбрии", - L"Аэропорт Драссена", - L"Аэропорт Медуны", - L"База ПВО", - L"Убежище повстанцев", //The rebel base underground in sector A10 - L"Подвалы Тиксы", //The basement of the Tixa Prison (J9) - L"Логово тварей", //Any mine sector with creatures in it - L"Подвалы Орты", //The basement of Orta (K4) - L"Туннель", //The tunnel access from the maze garden in Meduna - //leading to the secret shelter underneath the palace - L"Убежище", //The shelter underneath the queen's palace - L"", //Unused -}; - -STR16 gpStrategicString[] = -{ - L"", //Unused - L"%s замечен в секторе %c%d, и другой отряд уже на подходе.", //STR_DETECTED_SINGULAR - L"%s замечен в секторе %c%d, и остальные отряды уже на подходе.", //STR_DETECTED_PLURAL - L"Желаете дождаться прибытия остальных?", //STR_COORDINATE - - //Dialog strings for enemies. - - L"Враг предлагает вам сдаться.", //STR_ENEMY_SURRENDER_OFFER - L"Оставшиеся без сознания бойцы попали в плен.", //STR_ENEMY_CAPTURED - - //The text that goes on the autoresolve buttons - - L"Отступить", //The retreat button //STR_AR_RETREAT_BUTTON - L"OK", //The done button //STR_AR_DONE_BUTTON - - //The headers are for the autoresolve type (MUST BE UPPERCASE) - - L"ОБОРОНА", //STR_AR_DEFEND_HEADER - L"АТАКА", //STR_AR_ATTACK_HEADER - L"ВСТРЕЧА", //STR_AR_ENCOUNTER_HEADER - L"Сектор", //The Sector A9 part of the header //STR_AR_SECTOR_HEADER - - //The battle ending conditions - - L"ПОБЕДА!", //STR_AR_OVER_VICTORY - L"ПОРАЖЕНИЕ!", //STR_AR_OVER_DEFEAT - L"СДАЛСЯ!", //STR_AR_OVER_SURRENDERED - L"ПЛЕНЕН!", //STR_AR_OVER_CAPTURED - L"ОТСТУПИЛ!", //STR_AR_OVER_RETREATED - - //These are the labels for the different types of enemies we fight in autoresolve. - - L"Ополченец", //STR_AR_MILITIA_NAME, - L"Элита", //STR_AR_ELITE_NAME, - L"Солдат", //STR_AR_TROOP_NAME, - L"Смотритель", //STR_AR_ADMINISTRATOR_NAME, - L"Рептион", //STR_AR_CREATURE_NAME, - - //Label for the length of time the battle took - - L"Прошло времени", //STR_AR_TIME_ELAPSED, - - //Labels for status of merc if retreating. (UPPERCASE) - - L"ОТСТУПИЛ", //STR_AR_MERC_RETREATED, - L"ОТСТУПАЕТ", //STR_AR_MERC_RETREATING, - L"ОТСТУПИТЬ", //STR_AR_MERC_RETREAT, - - //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) - - L"Авто битва", //STR_PB_AUTORESOLVE_BTN, - L"Перейти в сектор", //STR_PB_GOTOSECTOR_BTN, - L"Уйти из сектора", //STR_PB_RETREATMERCS_BTN, - - //The different headers(titles) for the prebattle interface. - L"ВСТРЕЧА С ВРАГОМ", //STR_PB_ENEMYENCOUNTER_HEADER, - L"НАСТУПЛЕНИЕ ВРАГА", //STR_PB_ENEMYINVASION_HEADER, // 30 - L"ВРАЖЕСКАЯ ЗАСАДА", //STR_PB_ENEMYAMBUSH_HEADER - L"ВРАЖЕСКИЙ СЕКТОР", //STR_PB_ENTERINGENEMYSECTOR_HEADER - L"АТАКА ТВАРЕЙ", //STR_PB_CREATUREATTACK_HEADER - L"ЗАСАДА КОШЕК-УБИЙЦ", //STR_PB_BLOODCATAMBUSH_HEADER - L"ВХОД В ЛОГОВИЩЕ КОШЕК-УБИЙЦ", //STR_PB_ENTERINGBLOODCATLAIR_HEADER - - //Various single words for direct translation. The Civilians represent the civilian - //militia occupying the sector being attacked. Limited to 9-10 chars - - L"Локация", //надписи в красном окне - L"Враг", - L"Наемники", - L"Ополчение", - L"Рептионы", - L"Кошки-убийцы", - L"Сектор", - L"Нет", //If there are no uninvolved mercs in this fight. - L"Н/Д", //Acronym of Not Applicable - L"д", //One letter abbreviation of day - L"ч", //One letter abbreviation of hour - - //TACTICAL PLACEMENT USER INTERFACE STRINGS - //The four buttons - - L"Отмена", - L"Случайно", - L"Группой", - L"B aтaку!", - - //The help text for the four buttons. Use \n to denote new line (just like enter). - - L"Убирает все позиции бойцов \nи позволяет заново расставить их. (|C)", - L"При каждом нажатии распределяет \nбойцов случайным образом. (|S)", - L"Позволяет выбрать место, \nгде сгруппировать ваших бойцов. (|G)", - L"Нажмите эту кнопку, когда завершите \nвыбор позиций для бойцов. (|В|в|о|д)", - L"Вы должны разместить всех своих бойцов \nдо того, как начать бой.", - - //Various strings (translate word for word) - - L"Сектор", - L"Выбор точек входа", - - //Strings used for various popup message boxes. Can be as long as desired. - - L"Препятствие. Место недоступно. Попробуйте пройти другим путем.", - L"Поместите бойцов в незатененную часть карты.", - - //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"прибыл(а) в сектор", - - //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. - L"Автоматически просчитывает бой\nбез загрузки карты. (|A)", - L"Нельзя включить автобой\nво время нападения.", - L"Войти в сектор, чтобы атаковать врага. (|E)", - L"Отступить отрядом в предыдущий сектор. (|R)", //singular version - L"Всем отрядам отступить в предыдущий сектор. (|R)", //multiple groups with same previous sector -//!!!What about repeated "R" as hotkey? - //various popup messages for battle conditions. - - //%c%d is the sector -- ex: A9 - L"Враги атаковали ваших ополченцев в секторе %c%d.", - //%c%d сектор -- напр: A9 - L"Твари атаковали ваших ополченцев в секторе %c%d.", - //1st %d refers to the number of civilians eaten by monsters, %c%d is the sector -- ex: A9 - //Note: the minimum number of civilians eaten will be two. - L"Твари убили %d гражданских во время атаки сектора %s.", - //%s is the sector location -- ex: A9: Omerta - L"Враги атаковали ваших наемников в секторе %s. Ни один из ваших бойцов не в состоянии сражаться!", - //%s is the sector location -- ex: A9: Omerta - L"Твари атаковали ваших наемников в секторе %s. Ни один из ваших бойцов не в состоянии сражаться!", - -}; - -STR16 gpGameClockString[] = -{ - //This is the day represented in the game clock. Must be very short, 4 characters max. - L"День", -}; - -//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] = -{ - L"Находки сектора:", - L"Находки за день:", -}; - -//The headers used to describe various weapon statistics. - -CHAR16 gWeaponStatsDesc[][ 14 ] = -{ - L"Вес (%s):", - L"Состояние:", - L"Всего:", // Number of bullets left in a magazine - L"Дист:", // Range - L"Урон:", // Damage - L"ОД:", // abbreviation for Action Points - L"", - L"=", - L"=", - //Lal: additional strings for tooltips - L"Точность:", //9 - L"Дист:", //10 - L"Урон:", //11 - L"Вес:", //12 - L"Шок:",//13 //пр -}; - -//The headers used for the merc's money. - -CHAR16 gMoneyStatsDesc[][ 13 ] = -{ - L"Кол-во", //пр - L"Осталось:", //проверить this is the overall balance - L"Кол-во", //пр - L"Отделить:", //проверить the amount he wants to separate from the overall balance to get two piles of money - - L"Текущий", - L"Баланс", - L"Снимаемая", - L"Сумма", -}; - -//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. - -CHAR16 zHealthStr[][13] = -{ - L"УМИРАЕТ", // >= 0 - L"КРИТИЧЕН", // >= 15 - L"ПЛОХ", // >= 30 - L"РАНЕН", // >= 45 - L"ЗДОРОВ", // >= 60 - L"СИЛЕН", // >= 75 - L"ОТЛИЧНО", // >= 90 -}; - -STR16 gzMoneyAmounts[6] = -{ - L"1000$", - L"100$", - L"10$", - L"Снять", - L"Разделить", //пр - L"Взять" -}; - -// short words meaning "Advantages" for "Pros" and "Disadvantages" for "Cons." -CHAR16 gzProsLabel[10] = -{ - L"Плюсы:", //в описании ТТХ оружия -}; - -CHAR16 gzConsLabel[10] = -{ - L"Минусы:", //в описании ТТХ оружия -}; - -//Conversation options a player has when encountering an NPC -CHAR16 zTalkMenuStrings[6][ SMALL_STRING_LENGTH ] = -{ - L"Повторить", //meaning "Repeat yourself" - L"Дружественно", //approach in a friendly - L"Напрямую", //approach directly - let's get down to business - L"Угрожать", //approach threateningly - talk now, or I'll blow your face off - L"Дать", - L"Нанять" -}; - -//Some NPCs buy, sell or repair items. These different options are available for those NPCs as well. -CHAR16 zDealerStrings[4][ SMALL_STRING_LENGTH ]= -{ - L"Купить/Продать", - L"Купить", - L"Продать", - L"Ремонтировать", -}; - -CHAR16 zDialogActions[1][ SMALL_STRING_LENGTH ] = -{ - L"До встречи", //кнопка в диалоговом окне с мирным -}; - - -//These are vehicles in the game. - -STR16 pVehicleStrings[] = -{ - L"Эльдорадо", - L"Хаммер", // a hummer jeep/truck -- military vehicle - L"Фургон", - L"Джип", - L"Танк", - L"Вертолет", -}; - -STR16 pShortVehicleStrings[] = -{ - L"Эльдор", - L"Хаммер", // the HMVV - L"Фургон", - L"Джип", - L"Танк", - L"Верт.", // the helicopter -}; - -STR16 zVehicleName[] = -{ - L"Эльдорадо", - L"Хаммер", //a military jeep. This is a brand name. - L"Фургон", // Ice cream truck - L"Джип", - L"Танк", - L"Вертолет", //an abbreviation for Helicopter -}; - - -//These are messages Used in the Tactical Screen - -CHAR16 TacticalStr[][ MED_STRING_LENGTH ] = -{ - L"Воздушный Рейд", //пр - L"Оказать первую помощь?", - - // CAMFIELD NUKE THIS and add quote #66. - - L"%s замечает, что некоторые вещи отсутствуют в посылке.", //появляется когда мерк замечает кражу? - - // The %s is a string from pDoorTrapStrings - - L"Замок (%s).", //пр - L"Тут нет замка.", //пр - L"Успех!", //пр - L"Провал.", //пр - L"Успех!", //пр - L"Провал", //пр - L"На замке нет ловушки.", //пишет при действии 'искать ловушки' - L"Успех!", //пр - // The %s is a merc name - L"У %s нет подходящего ключа", //пр - L"Ловушка обезврежена", //пр - L"На замке не найдено ловушки.", //пишет при действии 'обезвредить' - L"Заперто", //пр - L"ДВЕРЬ", //пишет над дверью - L"С ЛОВУШКОЙ", //пишет над дверью - L"ЗАПЕРТАЯ", //пишет над дверью - L"НЕЗАПЕРТАЯ", //пишет над дверью - L"СЛОМАНАЯ", //пр - L"Тут есть кнопка. Нажать?", //к примеру кнопка в шкафу шиза - L"Разрядить ловушку?", //пр - L"Пред...", //пр - L"След...", //пр - L"Еще...", //пр - - // In the next 2 strings, %s is an item name - - L"%s помещен(а) на землю.", //пр - L"%s отдан(а) %s.", //пр - - // In the next 2 strings, %s is a name - - L"%s: Оплачено сполна.", //пр - L"%s: Еще должен %d.", //пр - L"Установить частоту радиодетонатора:", //in this case, frequency refers to a radio signal - L"Количество ходов до взрыва:", //how much time, in turns, until the bomb blows - L"Выберите частоту радиодетонатора на пульте:", //in this case, frequency refers to a radio signal - L"Обезвредить ловушку?", - L"Убрать синий флаг?", //пр - L"Поставить здесь синий флаг?", - L"Завершающий ход", //пр - - // In the next string, %s is a name. Stance refers to way they are standing. - - L"Вы действительно хотите атаковать %s?", - L"Увы, в машине боец не может изменить положение.", //пишет когда пытаешься наемником в машине на тактике присесть - L"Робот не может менять положение.", //пишет когда пытаешься присесть роботом - - // In the next 3 strings, %s is a name - - L"%s не может поменять положение здесь.", //пр - L"%s не может получить первую помощь.", //пр - L"%s не нуждается в медицинской помощи.", //пр - L"Туда идти нельзя.", //пр - L"У вас уже полная команда, мест нет.", //there's no room for a recruit on the player's team - - // In the next string, %s is a name - - L"%s нанят(а).", //к примеру, пишут когда Айру нанимаешь. - - // Here %s is a name and %d is a number - - L"%s должен получить $%d.", //пр - - // In the next string, %s is a name - - L"Сопроводить %s?", //пр - - // In the next string, the first %s is a name and the second %s is an amount of money (including $ sign) - - L"Нанять %s за %s в день?", //пр - - // This line is used repeatedly to ask player if they wish to participate in a boxing match. - - L"Хотите участвовать в поединке?", - - // In the next string, the first %s is an item name and the - // second %s is an amount of money (including $ sign) - - L"Купить %s за %s?", //пр - - // In the next string, %s is a name - - L"%s сопровождается отрядом %d.", //пр - - // These messages are displayed during play to alert the player to a particular situation - - L"ОТКАЗ", //ОТКАЗАЛО, ЗАКЛИНИЛО //weapon is jammed. - L"Роботу нужны патроны %s калибра.", //Robot is out of ammo - L"Бросить туда? Нет. Не выйдет.", //Merc can't throw to the destination he selected - - // These are different buttons that the player can turn on and off. - - L"Режим скрытности (|Z)", - L"Карта (|M)", - L"Завершить ход (|D)", - L"Говорить", - L"Молчать", - L"Подняться (|P|g|U|p)", - L"Смена уровня (|T|a|b)", - L"Забраться/Спрыгнуть", - L"Присесть/Лечь (|P|g|D|n)", - L"Осмотреть (|C|t|r|l)", - L"Предыдущий боец", - L"Следующий боец (|П|p|o|б|e|л)", - L"Настройки (|O)", - L"Режим очереди (|B)", - L"Смотреть/Повернуться (|L)", - L"Здоровье: %d/%d\nЭнергия: %d/%d\nМораль: %s", - L"Ну и?", //this means "what?" - L"Продолж.", //пр an abbrieviation for "Continued" - L"%s будет говорить.", - L"%s будет молчать.", - L"Состояние: %d/%d\nТопливо: %d/%d", - L"Выйти из машины", //пр - L"Сменить отряд (|S|h|i|f|t |П|p|о|б|e|л)", - L"Ехать", //пр - L"Н/Д", //this is an acronym for "Not Applicable." - L"Рукопашный бой", //может просто "Рукопашная"\Кулачный бой"? - L"Применить оружие", //вмнсто всех использовать можно "применить" - вроде тоже и короче. - L"Воспользоваться ножом", // - L"Использовать взрывчатку", // - L"Воспользоваться аптечкой", //может просто написать что-то вроде "лечить"\"Аптечка" - L"(Ловит)", - L"(Перезарядка)", //пр - L"(Дать)", //пишется под именем мирного, когда наводишь курсор с предметом - L"Сработала %s.", // The %s here is a string from pDoorTrapStrings ASSUME all traps are female gender - L"%s прибыл(а).", //к примеру, появляется при высадке в омерте - L"%s: истратил(а) все очки действия.", - L"%s сейчас не может действовать.", //пишет когда во время перехвата пытаешься выбрать наемника, который не перехватил ход - L"%s перевязан(а).", - L"%s: закончились бинты.", - L"Враг в секторе!", - L"Врагов в поле зрения нет.", //пишет когда врага не видишь и нажимаешь алт+ввод - L"Недостаточно очков действия.", - L"Оденьте на голову одного из наемников пульт управления роботом.", - L"Последняя очередь опустошила магазин!", - L"СОЛДАТ", //пр - L"РЕПТИОН", //пр - L"ОПОЛЧЕНЕЦ", //пишет как обращение при попытке лечить ополченца - L"ЖИТЕЛЬ", //пр - L"Выход из сектора", - L"ДА", - L"ОТМЕНА", - L"Выбранный боец", - L"Все бойцы отряда", - L"Идти в сектор", - L"Идти на карту", - L"Этот сектор отсюда покинуть нельзя.", //пр - L"%s слишком далеко.", //когда пытаешься выйти из сектора при перечеркнутом значке выхода - L"Скрыть кроны деревьев", - L"Показать кроны деревьев", - L"ВОРОНА", //Crow, as in the large black bird - L"ШЕЯ", - L"ГОЛОВА", - L"ТОРС", - L"НОГИ", - L"Рассказать Королеве то, что она хочет знать?", - L"Регистрация отпечатков пальцев пройдена.", - L"Неопознанные отпечатки пальцев. Оружие заблокировано.", - L"Цель захвачена", //пр - L"Путь заблокирован", //пр - L"Положить/Снять деньги", //подсказка джя значка $ на тактике Help text over the $ button on the Single Merc Panel - L"Никто не нуждается в медицинской помощи.", - L"отказ", // Short form of JAMMED, for small inv slots - L"Туда вскарабкаться невозможно.", // used ( now ) for when we click on a cliff - L"Путь блокирован. Хотите поменяться местами с этим человеком?", //пр - L"Человек отказывается двигаться.", //пр - // In the following message, '%s' would be replaced with a quantity of money (e.g. $200) - L"Вы согласны заплатить %s?", //пр - L"Принять бесплатное лечение?", //пр - L"Согласиться выйти замуж за Дэррела?", - L"Связка ключей", - L"С эскортируемыми этого сделать нельзя.", - L"Пощадить сержанта?", - L"За пределами прицельной дальности.", - L"Шахтер", //пр - L"Машина может ездить только между секторами.", - L"Ни у кого из наемников нет аптечки", //пр - L"Путь для %s заблокирован", - L"Ваши бойцы, захваченные армией Дейдраны, томятся здесь в плену!", - L"Замок поврежден.", - L"Замок разрушен.", - L"Кто-то с другой стороны пытается открыть эту дверь.", //пр - L"Состояние: %d/%d\nТопливо: %d/%d", - L"%s не видит %s.", // Cannot see person trying to talk to - L"Принадлежность отсоединена", //пр - L"Вы не можете содержать еще одну машину, довольствуйтесь уже имеющимися двумя.", -}; - -//Varying helptext explains (for the "Go to Sector/Map" checkbox) what will happen given different circumstances in the "exiting sector" interface. -STR16 pExitingSectorHelpText[] = -{ - //Helptext for the "Go to Sector" checkbox button, that explains what will happen when the box is checked. - L"Если выбрано, то карта соседнего сектора будет сразу же загружена.", - L"Если выбрано, то вы автоматически попадете на экран карты,\nтак как путешествие займет некоторое время.", - - //If you attempt to leave a sector when you have multiple squads in a hostile sector. - L"Этот сектор оккупирован врагом, и вы не можете выйти отсюда.\nВы должны разобраться с этим, прежде чем перейти в любой другой сектор.", - - //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"Как только оставшиеся наемники покинут этот сектор,\nсразу будет загружен соседний сектор.", - L"Выведя оставшихся наемников из этого сектора,\nвы автоматически попадете на экран карты,\nтак как на путешествие потребуется некоторое время.", - - //If an EPC is the selected merc, it won't allow the merc to leave alone as the merc is being escorted. The "single" button is disabled. - L"%s нуждается в сопровождении ваших наемников и не может в одиночку покинуть сектор.", - - //If only one conscious merc is left and is selected, and there are EPCs in the squad, the merc will be prohibited from leaving alone. - //There are several strings depending on the gender of the merc and how many EPCs are in the squad. - //DO NOT USE THE NEWLINE HERE AS IT IS USED FOR BOTH HELPTEXT AND SCREEN MESSAGES! - L"%s и %s не могут покинуть сектор поодиночке. Наемник сопровождает гражданского.", //male singular - L"%s и %s не могут покинуть сектор поодиночке. Наемник сопровождает гражданского.", //female singular - L"%s не может покинуть сектор в одиночку, так как он сопровождает группу из нескольких человек.", //male plural - L"%s не может покинуть сектор в одиночку, так как она сопровождает группу из нескольких человек.", //female plural - - //If one or more of your mercs in the selected squad aren't in range of the traversal area, then the "move all" option is disabled, - //and this helptext explains why. - L"Все ваши наемники должны быть в машине,\nчтобы отряд смог отправиться в место назначения.", - - L"", //UNUSED - - //Standard helptext for single movement. Explains what will happen (splitting the squad) - L"Если выбрать, то %s отправится в одиночку\nи автоматически будет переведен в отдельный отряд.", - - //Standard helptext for all movement. Explains what will happen (moving the squad) - L"Если выбрать, данный отряд отправится\nв место назначения, покинув этот сектор.", - - //This strings is used BEFORE the "exiting sector" interface is created. If you have an EPC selected and you attempt to tactically - //traverse the EPC while the escorting mercs aren't near enough (or dead, dying, or unconscious), this message will appear and the - //"exiting sector" interface will not appear. This is just like the situation where - //This string is special, as it is not used as helptext. Do not use the special newline character (\n) for this string. - L"%s сопровождается вашими наемниками и не может покинуть этот сектор в одиночку. Остальные наемники должны быть рядом, прежде чем вы сможете покинуть сектор.", -}; - - - -STR16 pRepairStrings[] = -{ - L"Предметы", // tell merc to repair items in inventory - L"База ПВО", // tell merc to repair SAM site - SAM is an acronym for Surface to Air Missile - L"Отмена", // cancel this menu - L"Робот", // repair the robot -}; - - -// NOTE: combine prestatbuildstring with statgain to get a line like the example below. -// "John has gained 3 points of marksmanship skill." - -STR16 sPreStatBuildString[] = -{ - L"теряет", // the merc has lost a statistic - L"получает", // the merc has gained a statistic - L"единицу", // singular - L"единиц", // plural - L"уровень", // singular - L"уровня", // plural -}; - -STR16 sStatGainStrings[] = -{ - L"здоровья.", - L"проворности.", - L"ловкости.", - L"интеллекта.", - L"медицины.", - L"взрывного дела.", - L"механики.", - L"меткости.", - L"опыта.", - L"силы.", - L"лидерства.", -}; - - -STR16 pHelicopterEtaStrings[] = -{ - L"Общая дистанция:", // total distance for helicopter to travel - L"Безопасно: ", // distance to travel to destination - L"Опасно:", // distance to return from destination to airport - L"Итого:", // total cost of trip by helicopter - L"ОВП:", // ETA is an acronym for "estimated time of arrival" - L"У вертолета закончилось топливо. Придется совершить посадку на вражеской территории!", // warning that the sector the helicopter is going to use for refueling is under enemy control -> - L"Пассажиры:", - L"Выбрать вертолет или точку высадки?", - L"Вертолет", - L"Высадка", -}; - -STR16 sMapLevelString[] = -{ - L"Подуровень:", // what level below the ground is the player viewing in mapscreen -}; - -STR16 gsLoyalString[] = -{ - L"Лояльность", // the loyalty rating of a town ie : Loyal 53% -}; - - -// error message for when player is trying to give a merc a travel order while he's underground. - -STR16 gsUndergroundString[] = -{ - L"не может выйти на марш в подземельях.", -}; - -STR16 gsTimeStrings[] = -{ - L"ч", // hours abbreviation - L"м", // minutes abbreviation - L"с", // seconds abbreviation - L"д", // days abbreviation -}; - -// text for the various facilities in the sector - -STR16 sFacilitiesStrings[] = -{ - L"Нет", //важные объекты сектора - L"Госпиталь", - L"Фабрика", - L"Тюрьма", - L"Военная база", - L"Аэропорт", - L"Стрельбище", // a field for soldiers to practise their shooting skills -}; - -// text for inventory pop up button - -STR16 pMapPopUpInventoryText[] = -{ - L"Инвентарь", - L"Выйти", -}; - -// town strings - -STR16 pwTownInfoStrings[] = -{ - L"Размер", // 0 // size of the town in sectors - L"", // blank line, required - L"Контроль", // how much of town is controlled - L"Нет", // none of this town - L"Шахта города", // mine associated with this town - L"Лояльность", // 5 // the loyalty level of this town - L"Готовы", // the forces in the town trained by the player - L"", - L"Важные объекты", // main facilities in this town - L"Уровень", // the training level of civilians in this town - L"Тренировка ополчения", // 10 // state of civilian training in town - L"Ополчение", // the state of the trained civilians in the town -}; - -// Mine strings - -STR16 pwMineStrings[] = -{ - L"Шахта", // 0 - L"Серебро", - L"Золото", - L"Дневная выработка", - L"Производственные возможности", - L"Заброшена", // 5 - L"Закрыта", - L"Истощается", - L"Идет добыча", - L"Статус", - L"Уровень добычи", - L"Тип руды", // 10 - L"Принадлежность", - L"Лояльность", -// L"Работ.шахтеры", -}; - -// blank sector strings - -STR16 pwMiscSectorStrings[] = -{ - L"Вражеские силы", - L"Сектор", - L"Количество предметов", - L"Неизвестно", - L"Под контролем", - L"Да", - L"Нет", -}; - -// error strings for inventory - -STR16 pMapInventoryErrorString[] = -{ - L"%s стоит слишком далеко.", //Merc is in sector with item but not close enough - L"Нельзя выбрать этого бойца.", //MARK CARTER - L"%s вне этого сектора, и не может подобрать предмет.", - L"Во время боя вам придется подбирать вещи вручную.", //*перефразировать, показывается когда пытаешься со стратегич карты в инвентаре сектора взять предмет - L"Во время боя вам придется выкладывать вещи вручную.", - L"%s вне этого сектора, и не может оставить предмет.", - L"Во время битвы вы не можете заряжать оружие патронами из короба.", -}; - -STR16 pMapInventoryStrings[] = -{ - L"Локация", // sector these items are in - L"Всего предметов", // total number of items in sector -}; - - -// help text for the user - -STR16 pMapScreenFastHelpTextList[] = -{ - L"Чтобы перевести наемника в другой отряд, назначить его врачом или отдать приказ ремонтировать вещи, щелкните по колонке 'ЗАНЯТИЕ'.", - L"Чтобы приказать наемнику перейти в другой сектор, щелкните в колонке 'КУДА'.", - L"Как только наемник получит приказ на передвижение, включится сжатие времени.", - L"Нажатием левой кнопки мыши выбирается сектор. Еще одно нажатие нужно, чтобы отдать наемникам приказы на передвижение. Нажатие правой кнопки мыши на секторе откроет экран дополнительной информации.", - L"Чтобы вызвать экран помощи - в любой момент времени нажмите 'h'.", - L"Тестовый текст", - L"Тестовый текст", - L"Тестовый текст", - L"Тестовый текст", - L"Вы практически ничего не сможете сделать на этом экране, пока не прибудете в Арулько. Когда познакомитесь со своей командой, включите сжатие времени (кнопки в правом нижнем углу). Это ускорит течение времени, пока ваша команда не прибудет в Арулько.", -}; - -// movement menu text - -STR16 pMovementMenuStrings[] = -{ - L"Отправить наемников в сектор", // title for movement box - L"Путь", //пр done with movement menu, start plotting movement - L"Отмена", //пр cancel this menu - L"Другое", //пр title for group of mercs not on squads nor in vehicles -}; - - -STR16 pUpdateMercStrings[] = -{ - L"Ой!:", // an error has occured - L"Срок контракта истек:", // this pop up came up due to a merc contract ending - L"Задание выполнили:", // this pop up....due to more than one merc finishing assignments - L"Бойцы вернулись к своим обязанностям:", // this pop up ....due to more than one merc waking up and returing to work - L"Бойцы ложатся спать:", // this pop up ....due to more than one merc being tired and going to sleep - L"Скоро закончатся контракты у:", // this pop up came up due to a merc contract ending -}; - -// map screen map border buttons help text - -STR16 pMapScreenBorderButtonHelpText[] = -{ - L"Населенные пункты (|W)", - L"Шахты (|M)", - L"Отряды и враги (|T)", - L"Карта воздушного пространства (|A)", - L"Показать вещи (|I)", - L"Ополчение и враги (|Z)", -}; - - -STR16 pMapScreenBottomFastHelp[] = -{ - L"Ноутбук (|L)", - L"Тактический экран (|E|s|c)", - L"Настройки (|O)", - L"Сжатие времени (|+)", // time compress more - L"Сжатие времени (|-)", // time compress less - L"Предыдущее сообщение (|С|т|р|е|л|к|а |в|в|е|р|х)\nПредыдущая страница (|P|g|U|p)", // previous message in scrollable list - L"Следующее сообщение (|С|т|р|е|л|к|а |в|н|и|з)\nСледующая страница (|P|g|D|n)", // next message in the scrollable list - L"Включить / выключить\nсжатие времени (|П|р|о|б|е|л)", // start/stop time compression -}; - -STR16 pMapScreenBottomText[] = -{ - L"Текущий баланс", // current balance in player bank account -}; - -STR16 pMercDeadString[] = -{ - L"%s мертв(а)", -}; - - -STR16 pDayStrings[] = -{ - L"День", -}; - -// the list of email sender names - -STR16 pSenderNameList[] = -{ - L"Энрико", - L"Psych Pro Inc.", - L"Помощь", - L"Psych Pro Inc.", - L"Спек", - L"R.I.S.", //5 - L"Барри", - L"Блад", - L"Рысь", - L"Гризли", - L"Вики", //10 - L"Тревор", - L"Хряп", - L"Иван", - L"Анаболик", - L"Игорь", //15 - L"Тень", - L"Рыжий", - L"Жнец (Потрошитель)", - L"Фидель", - L"Лиска", //20 - L"Сидней", - L"Гас", - L"Сдоба", - L"Айс", - L"Паук", //25 - L"Скала (Клифф)", - L"Бык", - L"Стрелок", - L"Тоска", - L"Рейдер", //30 - L"Сова", - L"Статик", - L"Лен", - L"Дэнни", - L"Маг", - L"Стефан", - L"Лысый", - L"Злобный", - L"Доктор Кью", - L"Гвоздь", - L"Тор", - L"Стрелка", - L"Волк", - L"ЭмДи", - L"Лава", - //---------- - L"M.I.S. Страховка", - L"Бобби Рэй", - L"Босс", - L"Джон Кульба", - L"А.I.М.", -}; - - -// next/prev strings - -STR16 pTraverseStrings[] = -{ - L"<<", - L">>", -}; - -// new mail notify string - -STR16 pNewMailStrings[] = -{ - L"Получена новая почта...", -}; - - -// confirm player's intent to delete messages - -STR16 pDeleteMailStrings[] = -{ - L"Удалить письмо?", - L"Удалить, НЕ ПРОЧИТАВ?", -}; - - -// the sort header strings - -STR16 pEmailHeaders[] = -{ - L"От:", - L"Тема:", - L"День:", -}; - -// email titlebar text - -STR16 pEmailTitleText[] = -{ - L"Почтовый ящик", -}; - - -// the financial screen strings -STR16 pFinanceTitle[] = -{ - L"Финансовый отчет", //the name we made up for the financial program in the game -}; - -STR16 pFinanceSummary[] = -{ - L"Доход:", // credit (subtract from) to player's account - L"Расход:", // debit (add to) to player's account - L"Вчерашний чистый доход:", - L"Вчерашние другие поступления:", - L"Вчерашний расход:", - L"Баланс на конец дня:", - L"Чистый доход сегодня:", - L"Другие поступления за сегодня:", - L"Расход за сегодня:", - L"Текущий баланс:", - L"Ожидаемый доход:", - L"Ожидаемый баланс:", // projected balance for player for tommorow -}; - - -// headers to each list in financial screen - -STR16 pFinanceHeaders[] = -{ - L"День", //пр the day column - L"Доход", // the credits column - L"Расход", // the debits column - L"Операции", // transaction type - see TransactionText below - L"Баланс", // balance at this point in time - L"Стр.", // page number - L"Дней", // the day(s) of transactions this page displays -}; - - -STR16 pTransactionText[] = -{ - L"Начисленный процент", // interest the player has accumulated so far - L"Анонимный взнос", - L"Перевод средств", - L"Нанят", // Merc was hired - L"Покупки у Бобби Рэя", // Bobby Ray is the name of an arms dealer - L"Оплата счета M.E.R.C.", - L"%s: страховка.", // medical deposit for merc - L"I.M.P. анализ профиля", // IMP is the acronym for International Mercenary Profiling - L"%s: куплена страховка.", - L"%s: Страховка уменьшена", - L"%s: Продление страховки", // johnny contract extended - L"для %s: Страховка аннулирована", - L"%s: Требуется страховка", // insurance claim for merc - L"1 день", // merc's contract extended for a day - L"7 дней", // merc's contract extended for a week - L"14 дней", // ... for 2 weeks - L"Доход шахты", - L"", //String nuked - L"Куплены цветы", - L"%s: Возврат мед. депозита", - L"%s: Остаток мед. депозита", - L"%s: Мед. депозит удержан", - L"%s: оплата услуг.", // %s is the name of the npc being paid - L"%s берет наличные.", // transfer funds to a merc - L"%s: переводит деньги.", // transfer funds from a merc - L"%s: оружие ополчению.", // initial cost to equip a town's militia - L"%s продал вам вещи.", //is used for the Shop keeper interface. The dealers name will be appended to the end of the string. - L"%s кладет наличные на счет.", - L"Снаряжение продано населению", //пишет при продаже вещей из инвентаря сектора (алт+клик) -}; - -STR16 pTransactionAlternateText[] = -{ - L"Страховка для", // insurance for a merc - L"%s: контракт продлен на 1 день.", // entend mercs contract by a day - L"%s: контракт продлен на 7 дней.", - L"%s: контракт продлен на 14 дней.", -}; - -// helicopter pilot payment - -STR16 pSkyriderText[] = -{ - L"Небесному Всаднику заплачено $%d", // skyrider was paid an amount of money - L"Вы все еще должны Небесному Всаднику $%d.", // skyrider is still owed an amount of money - L"Небесный Всадник завершил заправку.", // skyrider has finished refueling - L"",//unused - L"",//unused - L"Небесный Всадник готов к полету.", // Skyrider was grounded but has been freed - L"У Небесного Всадника нет пассажиров. Если вы хотите переправить бойцов в этот сектор, посадите их в вертолет (приказ 'Машина/Вертолет')." -}; - - -// strings for different levels of merc morale - -STR16 pMoralStrings[] = -{ - L"Отлично", - L"Хорошо", - L"Норма", - L"Низкая", - L"Паника", - L"Ужас", -}; - -// Mercs equipment has now arrived and is now available in Omerta or Drassen. - -STR16 pLeftEquipmentString[] = -{ - L"%s оставляет свою экипировку в Омерте (A9).", //%s может взять заказанную экипировку в Омерте (A9). - L"%s оставляет свою экипировку в Драссене (B13).", //%s может взять заказанную экипировку в Драссене (B13). -}; - -// Status that appears on the Map Screen - -STR16 pMapScreenStatusStrings[] = -{ - L"Здоровье", - L"Энергия", - L"Мораль", - L"Состояние", // the condition of the current vehicle (its "health") - L"Бензин", // the fuel level of the current vehicle (its "energy") -}; - - -STR16 pMapScreenPrevNextCharButtonHelpText[] = -{ - L"Предыдущий наемник\n(|С|т|р|е|л|к|а |В|л|е|в|о)", // previous merc in the list - L"Следующий наемник\n(|С|т|р|е|л|к|а |В|п|р|а|в|о)", // next merc in the list -}; - - -STR16 pEtaString[] = -{ - L"РВП:", // eta is an acronym for Estimated Time of Arrival -}; - -STR16 pTrashItemText[] = -{ - L"Вы больше никогда не увидите этот предмет. Уверены?", // do you want to continue and lose the item forever - L"Этот предмет кажется ОЧЕНЬ важным. Вы ДЕЙСТВИТЕЛЬНО хотите выкинуть его?", // does the user REALLY want to trash this item -}; - - -STR16 pMapErrorString[] = -{ - L"Отряд не может выйти на марш, когда один из наемников спит.", - -//1-5 - L"Сначала выведите отряд на поверхность.", - L"Выйти на марш? Да тут же враги повсюду!", - L"Чтобы выйти на марш, наемники должны быть назначены в отряд или посажены в машину.", - L"У вас еще нет ни одного бойца.", // you have no members, can't do anything - L"Наемник не может выполнить.", // merc can't comply with your order -//6-10 - L"нуждается в сопровождении чтобы идти. Назначьте его с кем-нибудь в отряд.", // merc can't move unescorted .. for a male - L"нуждается в сопровождении чтобы идти. Назначьте ее с кем-нибудь в отряд.", // for a female - L"Наемник еще не прибыл в Арулько!", - L"Кажется, сначала надо уладить проблемы с контрактом.", - L"Бежать от самолета? Только после вас!", //пр Cannot give a movement order. Air raid is going on. -//11-15 - L"Выступить на марш? Да у нас тут бой идет!", - L"Вы попали в засаду кошек-убийц в секторе %s!", - L"Вы только что попали в логово кошек-убийц, сектор I16!", - L"", - L"База ПВО в %s была захвачена.", -//16-20 - L"Шахта в %s была захвачена врагом. Ваш дневной доход сократился до %s в день.", - L"Враг занял без сопротивления сектор %s.", - L"Как минимум один из ваших бойцов не может выполнить этот приказ.", - L"%s не может присоединиться к %s - нет места.", - L"%s не может присоединиться к %s - слишком большое расстояние.", -//21-25 - L"Шахта в %s была захвачена войсками Дейдраны!", - L"Войска Дейдраны только что вторглись на базу ПВО в %s.", - L"Войска Дейдраны только что вторглись в %s.", - L"Войска Дейдраны были замечены в %s.", - L"Войска Дейдраны только что захватили %s.", -//26-30 - L"Как минимум один из ваших бойцов не хочет спать.", - L"Как минимум один из ваших бойцов не может проснуться.", - L"Ополченцы не появятся, пока не завершат тренировку.", - L"%s сейчас не в состоянии принять приказ о перемещении.", - L"Ополченцы вне границ города не могут перейти в другой сектор.", -//31-35 - L"Вы не можете держать ополченцев в %s.", - L"Пустая машина не может двигаться!", - L"%s из-за тяжелых ранений не может идти!", - L"Сначала вам нужно покинуть музей!", - L"%s мертв(а)!", -//36-40 - L"%s не может переключиться на %s, так как находится в движении.", - L"%s не может сесть в машину с этой стороны.", - L"%s не может вступить в %s", - L"Вы не можете включить сжатие времени, пока не наймете новых бойцов!", - L"Эта машина может двигаться только по дорогам!", -//41-45 - L"Вы не можете переназначить наемников на марше.", - L"У машины закончился бензин!", - L"%s еле волочит ноги и идти не может.", - L"Ни один из пассажиров не в состоянии вести машину.", - L"Один или несколько наемников из этого отряда не могут сейчас двигаться.", -//46-50 - L"Один или несколько наемников не могут сейчас двигаться.", - L"Машина сильно повреждена!", - L"Внимание! Тренировать ополченцев в одном секторе могут не более двух наемников.", - L"Роботом обязательно нужно управлять. Назначьте наемника с пультом и робота в один отряд.", -}; - - -// help text used during strategic route plotting -STR16 pMapPlotStrings[] = -{ - L"Еще раз щелкните по точке назначения, чтобы подтвердить путь или щелкните по другому сектору, чтобы установить больше путевых точек.", - L"Путь движения подтвержден.", - L"Точка назначения не изменена.", - L"Путь движения отменен.", - L"Путь сокращен.", -}; - - -// help text used when moving the merc arrival sector -STR16 pBullseyeStrings[] = -{ - L"Выберите сектор, в который прибудут наемники.", - L"Вновь прибывшие наемники высадятся в %s.", - L"Высадить здесь наемников нельзя. Воздушное пространство не безопасно!", - L"Отменено. Сектор прибытия не изменился.", - L"Небо над %s более не безопасно! Место высадки было перемещено в %s.", -}; - - -// help text for mouse regions - -STR16 pMiscMapScreenMouseRegionHelpText[] = -{ - L"Открыть инвентарь (|В|в|о|д)", - L"Выкинуть предмет", - L"Закрыть инвентарь (|В|в|о|д)", -}; - - - -// male version of where equipment is left -STR16 pMercHeLeaveString[] = -{ - L"Должен ли %s оставить свою амуницию здесь (в %s) или позже в Драссене (B13) перед отлетом?", - L"Должен ли %s оставить свою амуницию здесь (в %s) или позже в Омерте (A9) перед отлетом?", - L"скоро уходит и оставит свою амуницию в Омерте (А9).", - L"скоро уходит и оставит свою амуницию в Драссене (B13).", - L"%s скоро уходит и оставит свою амуницию в %s.", -}; - - -// female version -STR16 pMercSheLeaveString[] = -{ - L"Должна ли %s оставить свою амуницию здесь (в %s) или позже в Драссене (B13) перед отлетом?", - L"Должна ли %s оставить свою амуницию здесь (в %s) или позже в Омерте (A9) перед отлетом?", - L"скоро уходит и оставит свою амуницию в Омерте (А9).", - L"скоро уходит и оставит свою амуницию в Драссене (B13).", - L"%s скоро уходит и оставит свою амуницию в %s.", -}; - - -STR16 pMercContractOverStrings[] = -{ - L"отправляется домой, так как его контракт завершен.", // merc's contract is over and has departed - L"отправляется домой, так как ее контракт завершен.", // merc's contract is over and has departed - L"уходит, так как его контракт был прерван.", // merc's contract has been terminated - L"уходит, так как ее контракт был прерван.", // merc's contract has been terminated - L"Вы должны M.E.R.C. слишком много денег, так что %s уходит.", // Your M.E.R.C. account is invalid so merc left -}; - -// Text used on IMP Web Pages - -STR16 pImpPopUpStrings[] = -{ - L"Неверный код доступа.", - L"Это приведет к потере уже полученных результатов тестирования. Вы уверены?", - L"Введите правильное имя и укажите пол.", - L"Предварительный анализ вашего счета показывает, что вы не можете позволить себе пройти тестирование.", - L"Сейчас вы не можете выбрать этот пункт.", - L"Чтобы закончить анализ, нужно иметь место еще хотя бы для одного члена команды.", - L"Профиль уже создан.", - L"Не могу загрузить I.M.P.-персонаж с диска.", //пр - L"Вы достигли максимального количества I.M.P.-персонажей.", //пр - L"У вас в команде уже есть три I.M.P.-персонажа того же пола.", //пр - L"Вы не можете позволить себе такой I.M.P.-персонаж.", //пр - L"Новый I.M.P.-персонаж присоединился к команде.", //пр -}; - - -// button labels used on the IMP site - -STR16 pImpButtonText[] = -{ - L"Информация о нас", // about the IMP site - L"НАЧАТЬ", // begin profiling - L"Способности", // personality section - L"Характеристики", // personal stats/attributes section - L"Портрет", // the personal portrait selection - L"Голос: %d", // the voice selection - L"Готово", // done profiling - L"Начать сначала", // start over profiling - L"Да, я выбираю отмеченный ответ.", - L"Да", - L"Нет", - L"Готово", // finished answering questions - L"Назад", // previous question..abbreviated form - L"Дальше", // next question - L"ДА.", // yes, I am certain - L"НЕТ, Я ХОЧУ НАЧАТЬ СНОВА.", // no, I want to start over the profiling process - L"ДА", - L"НЕТ", - L"Назад", // back one page - L"Отменить", // cancel selection - L"Да, все верно.", - L"Нет, еще раз взгляну.", - L"Регистрация", // the IMP site registry..when name and gender is selected - L"Анализ данных", // analyzing your profile results - L"Готово", - L"Голос", -}; - -STR16 pExtraIMPStrings[] = -{ - L"Чтобы создать профиль, укажите свои личные данные.", - L"Завершив формирование личности, укажите свои способности и умения.", - L"Способности героя заданы. Теперь вы можете выбрать портрет.", - L"Чтобы завершить процесс, выберите голос, который вам подходит." -}; - -STR16 pFilesTitle[] = -{ - L"Просмотр данных", -}; - -STR16 pFilesSenderList[] = -{ - L"Отчет разведки", // the recon report sent to the player. Recon is an abbreviation for reconissance - L"В розыске #1", // first intercept file .. Intercept is the title of the organization sending the file...similar in function to INTERPOL/CIA/KGB..refer to fist record in files.txt for the translated title - L"В розыске #2", // second intercept file - L"В розыске #3", // third intercept file - L"В розыске #4", // fourth intercept file - L"В розыске #5", // fifth intercept file - L"В розыске #6", // sixth intercept file -}; - -// Text having to do with the History Log - -STR16 pHistoryTitle[] = -{ - L"Журнал событий", -}; - -STR16 pHistoryHeaders[] = -{ - L"День", // the day the history event occurred - L"Стр.", // the current page in the history report we are in - L"День", // the days the history report occurs over - L"Локация", // location (in sector) the event occurred - L"Событие", // the event label -}; - -// various history events -// THESE STRINGS ARE "HISTORY LOG" STRINGS AND THEIR LENGTH IS VERY LIMITED. -// PLEASE BE MINDFUL OF THE LENGTH OF THESE STRINGS. ONE WAY TO "TEST" THIS -// IS TO TURN "CHEAT MODE" ON AND USE CONTROL-R IN THE TACTICAL SCREEN, THEN -// GO INTO THE LAPTOP/HISTORY LOG AND CHECK OUT THE STRINGS. CONTROL-R INSERTS -// MANY (NOT ALL) OF THE STRINGS IN THE FOLLOWING LIST INTO THE GAME. -STR16 pHistoryStrings[] = -{ - L"", // leave this line blank - //1-5 - L"Нанят(а) %s из A.I.M.", // merc was hired from the aim site - L"Нанят(а) %s из M.E.R.C.", // merc was hired from the aim site - L"%s мертв(а).", // merc was killed - L"Оплачены услуги M.E.R.C.", // paid outstanding bills at MERC - L"Принято задание от Энрико Чивалдори", - //6-10 - L"Воспользовались услугами I.M.P.", - L"Оформлена страховка для %s.", // insurance contract purchased - L"%s: cтраховой контракт аннулирован.", // insurance contract canceled - L"Выплата страховки %s.", // insurance claim payout for merc - L"%s: контракт продлен на 1 день.", // Extented "mercs name"'s for a day - //11-15 - L"%s: контракт продлен на 7 дней.", // Extented "mercs name"'s for a week - L"%s: контракт продлен на 14 дней.", // Extented "mercs name"'s 2 weeks - L"Вы уволили %s.", // "merc's name" was dismissed. - L"%s уходит от вас.", // "merc's name" quit. - L"получено задание.", // a particular quest started - //16-20 - L"задание выполнено.", - L"Поговорили со старшим горняком города %s", // talked to head miner of town - L"%s освобожден(а).", - L"Включен режим чит-кодов", - L"Провизия будет доставлена в Омерту завтра.", - //21-25 - L"%s ушла, чтобы выйти замуж за Дерила Хика.", - L"Истек контракт у %s.", - L"Нанят(а) %s.", - L"Энрико сетует на отсутствие успехов в кампании.", - L"Победа в сражении!", - //26-30 - L"В шахте %s иссякает запас руды.", - L"Шахта %s истощилась.", - L"Шахта %s закрыта.", - L"Шахта %s снова работает.", - L"Получена информация о тюрьме Тикса.", - //31-35 - L"Узнали об Орте - секретном военном заводе.", - L"Ученый из Орты подарил вам ракетные винтовки.", - L"Королева Дейдрана нашла применение трупам.", - L"Фрэнк говорил что-то о боях в Сан-Моне.", - L"Пациенту кажется, что он что-то видел в шахтах.", - //36-40 - L"Встретили Дэвина - торговца взрывчаткой.", - L"Пересеклись с бывшим наемником A.I.M., Майком!", - L"Встретили Тони, торговца оружием.", - L"Получена ракетная винтовка от сержанта Кротта.", - L"Документы на магазин Энджела переданы Кайлу.", - //41-45 - L"Шиз предлагает построить робота.", //может, собрать робота? - L"Болтун может сделать варево, обманывающее жуков.", - L"Кит отошел от дел.", - L"Говард поставлял цианиды Дейдране.", - L"Встретили торговца Кита из Камбрии.", - //46-50 - L"Встретили Говарда, фармацевта из Балайма.", - L"Встретили Перко. Он держит небольшую мастерскую.", - L"Встретили Сэма из Балайма. Он торгует железками.", - L"Франц разбирается в электронике и других вещах.", - L"Арнольд держит мастерскую в Граме.", - //51-55 - L"Фредо из Грама чинит электронику.", - L"Один богатей из Балайма дал вам денег.", - L"Встретили старьевщика Джейка.", - L"Один бродяга дал нам электронную карточку.", - L"Вальтер подкуплен, он откроет дверь в подвал.", - //56-60 - L"Дэйв заправит машину бесплатно, если будет бензин.", - L"Дали взятку Пабло.", - L"Босс держит деньги в шахте Сан-Моны.", - L"%s: победа в бое без правил.", - L"%s: проигрыш в бое без правил.", - //61-65 - L"%s: дисквалификация в бое без правил.", //дисквалификация из боя? - L"В заброшенной шахте найдена куча денег.", - L"Встречен убийца, посланный Боссом.", - L"Потерян контроль над сектором", //ENEMY_INVASION_CODE - L"Отбита атака врага", - //66-70 - L"Сражение проиграно", //ENEMY_ENCOUNTER_CODE - L"Смертельная засада", //ENEMY_AMBUSH_CODE - L"Вырвались из засады", - L"Атака провалилась!", //ENTERING_ENEMY_SECTOR_CODE - L"Успешная атака!", - //71-75 - L"Атака тварей", //CREATURE_ATTACK_CODE - L"Кошки-убийцы уничтожили ваш отряд.", //BLOODCAT_AMBUSH_CODE - L"Все кошки-убийцы убиты", - L"%s был убит(а).", - L"Отдали Кармену голову террориста.", - L"Убийца ушел.", - L"%s убит(а) вашим отрядом.", -}; - -STR16 pHistoryLocations[] = -{ - L"Н/Д", // N/A is an acronym for Not Applicable -}; - -// icon text strings that appear on the laptop - -STR16 pLaptopIcons[] = -{ - L"Почта", - L"Сайты", - L"Финансы", - L"Команда", - L"Журнал", - L"Данные", - L"Выключить", - L"sir-FER 4.0", // our play on the company name (Sirtech) and web surFER -}; - -// bookmarks for different websites -// IMPORTANT make sure you move down the Cancel string as bookmarks are being added - -STR16 pBookMarkStrings[] = -{ - L"А.I.M.", - L"Бобби Рэй", - L"I.M.P.", - L"М.Е.R.С.", - L"Похороны", - L"Цветы", - L"Страховка", - L"Отмена", -}; - -STR16 pBookmarkTitle[] = -{ - L"Закладки", - L"Позже это меню можно вызвать правым щелчком мыши.", -}; - -// When loading or download a web page - -STR16 pDownloadString[] = -{ - L"Загрузка", - L"Обновление", -}; - -//This is the text used on the bank machines, here called ATMs for Automatic Teller Machine - -STR16 gsAtmSideButtonText[] = -{ - L"OK", //пр - L"Взять", // take money from merc - L"Дать", // give money to merc - L"Отмена", //пр cancel transaction - L"Очист.", //пр clear amount being displayed on the screen -}; - -STR16 gsAtmStartButtonText[] = -{ - L"Перевести $", // transfer money to merc -- short form - L"Параметры", // view stats of the merc - L"Инвентарь", // view the inventory of the merc - L"Контракт", -}; - -STR16 sATMText[ ]= -{ - L"Перевести средства?", // transfer funds to merc? - L"Уверены?", //пр are we certain? - L"Ввести сумму", // enter the amount you want to transfer to merc - L"Выбрать тип", // select the type of transfer to merc - L"Не хватает денег", // not enough money to transfer to merc - L"Сумма должна быть кратна $10", // transfer amount must be a multiple of $10 -}; - -// Web error messages. Please use German equivilant for these messages. -// DNS is the acronym for Domain Name Server -// URL is the acronym for Uniform Resource Locator - -STR16 pErrorStrings[] = -{ - L"Ошибка", - L"Сервер не зарегистрирован в DNS.", - L"Проверьте адрес и попробуйте еще раз.", - L"OK", //пр //Превышено время ожидания ответа сервера. - L"Обрыв соединения с сервером.", -}; - - -STR16 pPersonnelString[] = -{ - L"Бойцов:", // mercs we have -}; - - -STR16 pWebTitle[ ]= -{ - L"sir-FER 4.0", // our name for the version of the browser, play on company name -}; - - -// The titles for the web program title bar, for each page loaded - -STR16 pWebPagesTitles[] = -{ - L"А.I.M.", - L"A.I.M. Состав", - L"A.I.M. Портреты", // a mug shot is another name for a portrait - L"A.I.M. Сортировка", - L"A.I.M.", - L"A.I.M. Галерея", //$$ - L"A.I.M. Правила", - L"A.I.M. История", - L"A.I.M. Ссылки", - L"M.E.R.C.", - L"M.E.R.C. Счета", - L"M.E.R.C. Регистрация", - L"M.E.R.C. Оглавление", - L"Бобби Рэй", - L"Бобби Рэй - оружие", - L"Бобби Рэй - боеприпасы", - L"Бобби Рэй - броня", - L"Бобби Рэй - разное", //misc is an abbreviation for miscellaneous - L"Бобби Рэй - вещи б/у.", - L"Бобби Рэй - почтовый заказ", - L"I.M.P.", - L"I.M.P.", - L"\"Цветы по всему миру\"", - L"\"Цветы по всему миру\" - галерея", - L"\"Цветы по всему миру\" - бланк заказа", - L"\"Цветы по всему миру\" - открытки", - L"Страховые агенты: Малеус, Инкус и Стэйпс", - L"Информация", - L"Контракт", //пр - L"Комментарии", - L"Похоронная служба Макгилликатти", - L"", - L"Адрес не найден.", - L"Бобби Рэй - последние поступления",//@@@3 Translate new text - L"", - L"", -}; - -STR16 pShowBookmarkString[] = -{ - L"Подсказка", - L"Щелкните еще раз по кнопке \"Сайты\" для отображения меню сайтов.", -}; - -STR16 pLaptopTitles[] = -{ - L"Почтовый ящик", - L"Просмотр данных", - L"Персонал", //пр - L"Финансовый отчет", - L"Журнал", //пр -}; - -STR16 pPersonnelDepartedStateStrings[] = -{ - //reasons why a merc has left. - L"Погиб в бою", - L"Уволен", - L"Другое", - L"Замужем", - L"Контракт истек", - L"Выход", -}; -// personnel strings appearing in the Personnel Manager on the laptop - -STR16 pPersonelTeamStrings[] = -{ - L"В команде", - L"Выбывшие", - L"Гонорар за день:", - L"Высший гонорар:", - L"Низший гонорар:", - L"Погибло в боях:", - L"Уволено:", - L"Другое:", -}; - - -STR16 pPersonnelCurrentTeamStatsStrings[] = -{ - L"Худший", - L"Среднее", - L"Лучший", -}; - - -STR16 pPersonnelTeamStatsStrings[] = -{ - L"ЗДР", - L"ПРВ", - L"ЛОВ", - L"СИЛ", - L"ЛИД", - L"ИНТ", - L"ОПТ", - L"МЕТ", - L"МЕХ", - L"ВЗР", - L"МЕД", -}; - - -// horizontal and vertical indices on the map screen - -STR16 pMapVertIndex[] = -{ - L"X", - L"A", - L"B", - L"C", - L"D", - L"E", - L"F", - L"G", - L"H", - L"I", - L"J", - L"K", - L"L", - L"M", - L"N", - L"O", - L"P", -}; - -STR16 pMapHortIndex[] = -{ - L"X", - L"1", - L"2", - L"3", - L"4", - L"5", - L"6", - L"7", - L"8", - L"9", - L"10", - L"11", - L"12", - L"13", - L"14", - L"15", - L"16", -}; - -STR16 pMapDepthIndex[] = -{ - L"", - L"-1", - L"-2", - L"-3", -}; - -// text that appears on the contract button - -STR16 pContractButtonString[] = -{ - L"Контракт", -}; - -// text that appears on the update panel buttons - -STR16 pUpdatePanelButtons[] = -{ - L"Далее", - L"Стоп", -}; - -// Text which appears when everyone on your team is incapacitated and incapable of battle - -CHAR16 LargeTacticalStr[][ LARGE_STRING_LENGTH ] = -{ - L"Вы потерпели поражение в этом секторе!", - L"Рептионы, не испытывая угрызений совести, пожрут всех до единого!", //пр - L"Ваши бойцы захвачены в плен (некоторые без сознания)!", - L"Ваши бойцы захвачены в плен.", -}; - - -//Insurance Contract.c -//The text on the buttons at the bottom of the screen. - -STR16 InsContractText[] = -{ - L"Назад", - L"Дальше", - L"Да", //пр - L"Очистить", //пр -}; - - - -//Insurance Info -// Text on the buttons on the bottom of the screen - -STR16 InsInfoText[] = -{ - L"Назад", - L"Дальше" -}; - - - -//For use at the M.E.R.C. web site. Text relating to the player's account with MERC - -STR16 MercAccountText[] = -{ - // Text on the buttons on the bottom of the screen - L"Внести сумму", - L"В начало", - L"Номер счета:", - L"Наемник", - L"Дней", - L"Ставка", //5 - L"Стоимость", - L"Всего:", - L"Вы подтверждаете платеж в размере %s?", //the %s is a string that contains the dollar amount ( ex. "$150" ) -}; - -// Merc Account Page buttons -STR16 MercAccountPageText[] = -{ - // Text on the buttons on the bottom of the screen - L"Назад", - L"Дальше", -}; - -//For use at the M.E.R.C. web site. Text relating a MERC mercenary - - -STR16 MercInfo[] = -{ - L"Здоровье", - L"Проворность", - L"Ловкость", - L"Сила", - L"Лидерство", - L"Интеллект", - L"Уровень опыта", - L"Меткость", - L"Механика", - L"Взрывчатка", - L"Медицина", - - L"Назад", - L"Нанять", - L"Дальше", - L"Дополнительная информация", - L"В начало", - L"Нанят", - L"Oплaтa", - L"в день", - L"Погиб", - - L"Похоже, вы пытаетесь нанять более 18 наемников, а это недопустимо.", - L"Недоступно", -}; - - - -// For use at the M.E.R.C. web site. Text relating to opening an account with MERC - -STR16 MercNoAccountText[] = -{ - //Text on the buttons at the bottom of the screen - L"Открыть счет", - L"Отмена", - L"Вы еще не зарегистрировались. Желаете открыть счет?" -}; - - - -// For use at the M.E.R.C. web site. MERC Homepage - -STR16 MercHomePageText[] = -{ - //Description of various parts on the MERC page - L"Спек Т. Кляйн, основатель и хозяин", - L"Открыть счет", - L"Просмотр счета", - L"Просмотр файлов", - // The version number on the video conferencing system that pops up when Speck is talking - L"Спек Ком v3.2" -}; - -// For use at MiGillicutty's Web Page. - -STR16 sFuneralString[] = -{ - L"Похоронное агентство Макгилликатти: скорбим вместе с семьями усопших с 1983.", - L"Директор по похоронам и бывший наемник А.I.М. - Мюррэй Макгилликатти \"Папаша\", специалист по части похорон.", - L"Всю жизнь Папашу сопровождали смерть и утраты, поэтому он, как никто, познал их тяжесть.", - L"Похоронное агентство Макгилликатти предлагает широкий спектр ритуальных услуг - от жилетки, в которую можно поплакать, до восстановления сильно поврежденных останков.", - L"Похоронное агентство Макгилликатти поможет вам и вашим родственникам покоиться с миром.", - - // Text for the various links available at the bottom of the page - L"ДОСТАВКА ЦВЕТОВ", - L"КОЛЛЕКЦИЯ УРН И ГРОБОВ", - L"УСЛУГИ ПО КРЕМАЦИИ", - L"ПОМОЩЬ В ПРОВЕДЕНИИ ПОХОРОН", - L"ПОХОРОННЫЕ РИТУАЛЫ", - - // The text that comes up when you click on any of the links ( except for send flowers ). - L"К сожалению, наш сайт не закончен, в связи с утратой в семье. Мы постараемся продолжить работу после прочтения завещания и выплат долгов умершего. Сайт вскоре откроется.", - L"Мы искренне сочувствуем вам в это трудное время. Заходите еще." -}; - -// Text for the florist Home page - -STR16 sFloristText[] = -{ - //Text on the button on the bottom of the page - - L"Галерея", - - //Address of United Florist - - L"\"Мы сбросим ваш букет где угодно!\"", - L"1-555-SCENT-ME", - L"333 NoseGay Dr,Seedy City, CA USA 90210", - L"http://www.scent-me.com", - - // detail of the florist page - - L"Мы работаем быстро и эффективно!", - L"Гарантируем доставку на следующий день практически в любой уголок мира. Есть некоторые ограничения.", - L"Гарантируем самые низкие цены в мире!", - L"Покажите нам рекламу более дешевого сервиса и получите 10 бесплатных роз.", - L"\"Крылатая Флора\", занимаемся фауной и цветами с 1981 г.", - L"Наши летчики, бывшие пилоты бомбардировщиков, сбросят ваш букет в радиусе 10 миль от заданного района. Когда угодно и сколько угодно!", - L"Позвольте нам удовлетворить ваши цветочные фантазии.", - L"Пусть Брюс, известный во всем мире садовник, сам соберет вам отличный букет в нашем саду.", - L"И запомните, если у нас нет таких цветов, мы быстро вырастим то, что вам надо!" -}; - - - -//Florist OrderForm - -STR16 sOrderFormText[] = -{ - //Text on the buttons - - L"Назад", - L"Послать", - L"Отмена", - L"Галерея", - - L"Название букета:", - L"Цена:", //5 - L"Номер заказа:", - L"Доставить", - L"Завтра", - L"Как будете в тех краях", - L"Место доставки", //10 - L"Дополнительно", - L"Сломать цветы ($10)", - L"Черные розы ($20)", - L"Увядший букет ($10)", - L"Фруктовый пирог (если есть) ($10)", //15 - L"Текст поздравления:", - L"Ввиду небольшого размера открытки, постарайтесь уложиться в 75 символов.", - L"...или выберите одну из", - - L"СТАНДАРТНЫХ ОТКРЫТОК", - L"Информация о счете",//20 - - //The text that goes beside the area where the user can enter their name - - L"Название:", -}; - - - - -//Florist Gallery.c - -STR16 sFloristGalleryText[] = -{ - //text on the buttons - - L"Назад", //abbreviation for previous - L"Дальше", //abbreviation for next - - L"Выберите букет, которые хотите послать.", - L"Примечание: Если Вам нужно послать увядший или сломанный букет - заплатите еще $10.", - - //text on the button - - L"В начало", -}; - -//Florist Cards - -STR16 sFloristCards[] = -{ - L"Выберите текст, который будет напечатан на открытке.", - L"Назад" -}; - - - -// Text for Bobby Ray's Mail Order Site - -STR16 BobbyROrderFormText[] = -{ - L"Бланк заказа", //Title of the page - L"Штк", // The number of items ordered - L"Вес (%s)", // The weight of the item - L"Название", // The name of the item - L"цена 1 вещи", // the item's weight - L"Итого", //5 // The total price of all of items of the same type - L"Стоимость", // The sub total of all the item totals added - L"ДиУ (см. Место Доставки)", // S&H is an acronym for Shipping and Handling - L"Всего", // The grand total of all item totals + the shipping and handling - L"Место доставки", - L"Скорость доставки", //10 // See below - L"Цена (за %s.)", // The cost to ship the items - L"Экспресс-доставка", // Gets deliverd the next day - L"2 рабочих дня", // Gets delivered in 2 days - L"Обычная доставка", // Gets delivered in 3 days - L"ОЧИСТИТЬ",//15 // Clears the order page - L"ЗАКАЗАТЬ", // Accept the order - L"Назад", // text on the button that returns to the previous page - L"В начало", // Text on the button that returns to the home page - L"* - вещи, бывшие в употреблении", // Disclaimer stating that the item is used - L"Вы не можете это оплатить.", //20 // A popup message that to warn of not enough money - L"<НЕ ВЫБРАНО>", // Gets displayed when there is no valid city selected - L"Вы действительно хотите отправить груз в %s?", // A popup that asks if the city selected is the correct one - L"Вес груза**", // Displays the weight of the package - L"** Мин. вес", // Disclaimer states that there is a minimum weight for the package - L"Заказы", -}; - - -STR16 BobbyRFilter[] = -{ - // Guns - L"Тяжелое", - L"Пистолеты", - L"Авт.пистол.", - L"ПП", - L"Винтовки", - L"Сн.винтовки", - L"Шт.винтовки", - L"Пулеметы", - L"Ружья", - - // Ammo - //L"Heavy W.", - L"Пистолеты", - L"Авт.пистол.", - L"ПП", - L"Винтовки", - L"Сн.винтовки", - L"Шт.винтовки", - L"Пулеметы", - L"Ружья", - - // Used - L"Оружие", - L"Броня", - L"Разгр.с-мы", - L"Разное", - - // Armour - L"Каски", - L"Жилеты", - L"Брюки", - L"Пластины", - - // Misc - L"Режущие", - L"Метательн.", - L"Дробящие", - L"Гранаты", - L"Бомбы", - L"Аптечки", - L"Наборы", - L"Головные", - L"Разгр.с-мы", - L"Разное", -}; - - -// This text is used when on the various Bobby Ray Web site pages that sell items - -STR16 BobbyRText[] = -{ - L"Заказать", // Title - // instructions on how to order - L"Нажмите на товар. Левая кнопка - добавить, правая кнопка - уменьшить. После того как выберете товар, оформите заказ.", - - //Text on the buttons to go the various links - - L"Назад", // - L"Оружие", //3 - L"Патроны", //4 - L"Броня", //5 - L"Разное", //6 //misc is an abbreviation for miscellaneous - L"Б/У", //7 - L"Далее", - L"БЛАНК ЗАКАЗА", - L"В начало", //10 - - //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 - - L"У вашей команды есть",//11 - L"оруж., использующее этот тип боеприпасов", //12 - - //The following lines provide information on the items - - L"Вес:", // Weight of all the items of the same type - L"Кал.:", // the caliber of the gun - L"Маг:", // number of rounds of ammo the Magazine can hold - L"Дист:", // The range of the gun - L"Урон:", // Damage of the weapon - L"Скор:", // Weapon's Rate Of Fire, acronym ROF - L"Цена:", // Cost of the item - L"Склад:", // The number of items still in the store's inventory - L"Штук в заказе:", // The number of items on order - L"Урон:", // If the item is damaged - L"Вес:", // the Weight of the item - L"Итого:", // The total cost of all items on order - L"* %% до износа", // 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"Черт! Эта форма поддерживает не более 10 предметов в одном заказе. Если вы хотите заказать больше (а мы надеемся, вы хотите), то заполните еще один заказ и примите наши извинения за неудобства.", - - // A popup that tells the user that they are trying to order more items then the store has in stock - - L"Извините, но данного товара нет на складе. Попробуйте заглянуть позже.", - - //A popup that tells the user that the store is temporarily sold out - - L"Извините, но данного товара пока нет на складе.", - -}; - - -// Text for Bobby Ray's Home Page - -STR16 BobbyRaysFrontText[] = -{ - //Details on the web site - - L"Здесь вы найдете лучшие и новейшие образцы оружия", - L"Мы снабдим вас всем, что нужно для победы над противником", - L"ВЕЩИ Б/У", - - //Text for the various links to the sub pages - - L"РАЗНОЕ", - L"ОРУЖИЕ", - L"БОЕПРИПАСЫ", //5 - L"БРОНЯ", - - //Details on the web site - - L"Если у нас чего-то нет, то этого нет нигде!", - L"В разработке", -}; - - - -// Text for the AIM page. -// This is the text used when the user selects the way to sort the aim mercanaries on the AIM mug shot page - -STR16 AimSortText[] = -{ - L"А.I.M. Состав", // Title - // Title for the way to sort - L"Сортировка:", - - // sort by... - - L"Цена", - L"Опыт", - L"Меткость", - L"Медицина", - L"Взрывчатка", - L"Механика", - - //Text of the links to other AIM pages - - L"Показать фотографии наемников", - L"Просмотреть информацию о наемниках", - L"Просмотреть архивную галерею A.I.M.", - - // text to display how the entries will be sorted - - L"По возрастанию", - L"По убыванию" -}; - - -//Aim Policies.c -//The page in which the AIM policies and regulations are displayed - -STR16 AimPolicyText[] = -{ - // The text on the buttons at the bottom of the page - - L"Назад", - L"В начало", - L"Оглавление", - L"Дальше", - L"Не согласен", - L"Согласен" -}; - - - -//Aim Member.c -//The page in which the players hires AIM mercenaries - -// Instructions to the user to either start video conferencing with the merc, or to go the mug shot index - -STR16 AimMemberText[] = -{ - L"Левая кнопка мыши", - L"чтобы связаться с бойцом.", - L"Правая кнопка мыши", - L"экран с фотографиями.", -}; - -//Aim Member.c -//The page in which the players hires AIM mercenaries - -STR16 CharacterInfo[] = -{ - // The various attributes of the merc - - L"Здоровье", - L"Проворность", - L"Ловкость", - L"Сила", - L"Лидерство", - L"Интеллект", - L"Уровень опыта", - L"Меткость", - L"Механика", - L"Взрывчатка", - L"Медицина", //10 - - // the contract expenses' area - - L"Гонорар", - L"Срок", - L"1 день", - L"7 дней", - L"14 дней", - - // text for the buttons that either go to the previous merc, - // start talking to the merc, or go to the next merc - - L"<<", - L"Связаться", - L">>", - - L"Дополнительная информация", // Title for the additional info for the merc's bio - L"Действующий состав", //20 // Title of the page - L"Снаряжение:", // Displays the optional gear cost - L"Стоимость Мед. депозита", // If the merc required a medical deposit, this is displayed -}; - - -//Aim Member.c -//The page in which the player's hires AIM mercenaries - -//The following text is used with the video conference popup - -STR16 VideoConfercingText[] = -{ - L"Сумма контракта:", //Title beside the cost of hiring the merc - - //Text on the buttons to select the length of time the merc can be hired - - L"1 день", - L"7 дней", - L"14 дней", - - //Text on the buttons to determine if you want the merc to come with the equipment - - L"Без снаряжения", - L"Со снаряжением", - - // Text on the Buttons - - L"ОПЛАТИТЬ", // to actually hire the merc - L"ОТМЕНА", // go back to the previous menu - L"НАНЯТЬ", // go to menu in which you can hire the merc - L"ОТБОЙ", // stops talking with the merc - L"ЗАКРЫТЬ", - L"СООБЩЕНИЕ", // if the merc is not there, you can leave a message - - //Text on the top of the video conference popup - - L"Видеоконференция с", - L"Подключение. . .", - - L"+ страховка" // Displays if you are hiring the merc with the medical deposit -}; - - - -//Aim Member.c -//The page in which the player hires AIM mercenaries - -// The text that pops up when you select the TRANSFER FUNDS button - -STR16 AimPopUpText[] = -{ - L"ПРОИЗВЕДЕН ЭЛЕКТРОННЫЙ ПЛАТЕЖ", // You hired the merc - L"НЕЛЬЗЯ ПЕРЕВЕСТИ СРЕДСТВА", // Player doesn't have enough money, message 1 - L"НЕ ХВАТАЕТ СРЕДСТВ", // Player doesn't have enough money, message 2 - - // if the merc is not available, one of the following is displayed over the merc's face - - L"На задании", - L"Пожалуйста, оставьте сообщение", - L"Скончался", - - //If you try to hire more mercs than game can support - - L"У вас уже полная команда из 18 наемников.", - - L"Автоответчик", - L"Сообщение оставлено на автоответчике", -}; - - -//AIM Link.c - -STR16 AimLinkText[] = -{ - L"A.I.M. Ссылки", //The title of the AIM links page -}; - - - -//Aim History - -// This page displays the history of AIM - -STR16 AimHistoryText[] = -{ - L"A.I.M. История", //Title - - // Text on the buttons at the bottom of the page - - L"Назад", - L"В начало", - L"A.I.M. Галерея", //$$ - L"Дальше" -}; - - -//Aim Mug Shot Index - -//The page in which all the AIM members' portraits are displayed in the order selected by the AIM sort page. - -STR16 AimFiText[] = -{ - // displays the way in which the mercs were sorted - - L"Цена", - L"Опыт", - L"Меткость", - L"Медицина", - L"Взрывчатка", - L"Механика", - - // The title of the page, the above text gets added at the end of this text - - L"Сортировка состава A.I.M. По возрастанию, критерий - %s", - L"Сортировка состава A.I.M. По убыванию, критерий - %s", - - // Instructions to the players on what to do - - L"Левый щелчок", - L"Выбрать наемника", //10 - L"Правый щелчок", - L"Критерий сортировки", - - // Gets displayed on top of the merc's portrait if they are... - - L"Выбыл", - L"Скончался", //14 - L"На задании", -}; - - - -//AimArchives. -// The page that displays information about the older AIM alumni merc... mercs who are no longer with AIM - -STR16 AimAlumniText[] = -{ - // Text of the buttons - - L"СТР. 1", - L"СТР. 2", - L"СТР. 3", - - L"A.I.M. Галерея", // Title of the page //$$ - - L"ОК" // Stops displaying information on selected merc -}; - - - - - - -//AIM Home Page - -STR16 AimScreenText[] = -{ - // AIM disclaimers - - L"A.I.M. и логотип A.I.M. - зарегистрированные во многих странах торговые марки.", - L"Так что и не думай подражать нам.", - L"(с) 1998-1999 A.I.M., Ltd. Все права защищены.", - - //Text for an advertisement that gets displayed on the AIM page - - L"\"Цветы по всему миру\"", - L"\"Мы сбросим ваш букет где угодно!\"", //10 - L"Сделай как надо", - L"...в первый раз", - L"Если у нас нет такого ствола, то он вам и не нужен.", -}; - - -//Aim Home Page - -STR16 AimBottomMenuText[] = -{ - //Text for the links at the bottom of all AIM pages - L"В начало", - L"Наемники", - L"Архив", //$$ - L"Правила", - L"Информация", - L"Ссылки" -}; - - - -//ShopKeeper Interface -// The shopkeeper interface is displayed when the merc wants to interact with -// the various store clerks scattered through out the game. - -STR16 SKI_Text[ ] = -{ - L"ИМЕЮЩИЕСЯ ТОВАРЫ", //Header for the merchandise available - L"СТР.", //The current store inventory page being displayed - L"ОБЩАЯ ЦЕНА", //The total cost of the the items in the Dealer inventory area - L"ОБЩАЯ ЦЕННОСТЬ", //The total value of items player wishes to sell - L"ОЦЕНКА", //Button text for dealer to evaluate items the player wants to sell - L"ПЕРЕВОД", //Button text which completes the deal. Makes the transaction. - L"УЙТИ", //Text for the button which will leave the shopkeeper interface. - L"ЦЕНА РЕМОНТА", //The amount the dealer will charge to repair the merc's goods - L"1 ЧАС", // SINGULAR! The text underneath the inventory slot when an item is given to the dealer to be repaired - L"%d ЧАСОВ", // PLURAL! The text underneath the inventory slot when an item is given to the dealer to be repaired - L"ИСПРАВНО", // Text appearing over an item that has just been repaired by a NPC repairman dealer - L"Вам уже некуда класть вещи.", //Message box that tells the user there is no more room to put there stuff - L"%d МИНУТ", // The text underneath the inventory slot when an item is given to the dealer to be repaired - L"Выбросить предмет на землю.", -}; - -//ShopKeeper Interface -//for the bank machine panels. Referenced here is the acronym ATM, which means Automatic Teller Machine - -STR16 SkiAtmText[] = -{ - //Text on buttons on the banking machine, displayed at the bottom of the page - L"0", - L"1", - L"2", - L"3", - L"4", - L"5", - L"6", - L"7", - L"8", - L"9", - L"OK", //пр Transfer the money - L"Взять", //пр Take money from the player - L"Дать", //пр Give money to the player - L"Отмена", //пр Cancel the transfer - L"Очистить", //пр Clear the money display -}; - - -//Shopkeeper Interface -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 - L"Введите сумму", //пр Enter the amount to transfer - L"Перевести деньги бойцу", //пр Giving money to the merc - L"Забрать деньги у бойца", //пр Taking money from the merc - L"Недостаточно средств", //пр Not enough money to transfer - L"Баланс", //пр Display the amount of money the player currently has -}; - - -STR16 SkiMessageBoxText[] = -{ - L"Желаете снять со счета %s, чтобы покрыть разницу?", - L"Недостаточно средств. Не хватает %s", - L"Желаете снять со счета %s, чтобы оплатить полную стоимость?", - L"Попросить торговца сделать перевод", - L"Попросить торговца починить выбранные предметы", - L"Закончить беседу", //вспл. подсказка по нажатии кнопки кэнсэл при торговле\ремонте - L"Текущий баланс", -}; - - -//OptionScreen.c - -STR16 zOptionsText[] = -{ - //button Text - L"Сохранить игру", - L"Загрузить игру", - L"Выход", - L"Готово", - - //Text above the slider bars - L"Звуки", - L"Речь", - L"Музыка", - - //Confirmation pop when the user selects.. - L"Выйти из игры и вернуться в главное меню?", - - L"Необходимо выбрать или \"Речь\", или \"Субтитры\"", -}; - - -//SaveLoadScreen -STR16 zSaveLoadText[] = -{ - L"Сохранить", - L"Загрузить", - L"Отмена", - L"Сохранение выбрано", - L"Загрузка выбрана", - - L"Игра успешно сохранена", - L"ОШИБКА сохранения игры!", - L"Игра успешно загружена", - L"ОШИБКА загрузки игры!", - - L"Это сохранение было сделано иной версией игры. Скорее всего, вы не сможете загрузить его. Все равно продолжить?", - L"Версия файла сохранения отличается от текущей версии игры.", - - //Translators, the next two strings are for the same thing. The first one is for beta version releases and the second one - //is used for the final version. Please don't modify the "#ifdef JA2BETAVERSION" or the "#else" or the "#endif" as they are - //used by the compiler and will cause program errors if modified/removed. It's okay to translate the strings though. -#ifdef JA2BETAVERSION - L"Скорее всего, вы не сможете нормально продолжить игру. Все равно продолжить?", -#else - L"Версия файла сохранения отличается от текущей версии игры.", -#endif - - //Translators, the next two strings are for the same thing. The first one is for beta version releases and the second one - //is used for the final version. Please don't modify the "#ifdef JA2BETAVERSION" or the "#else" or the "#endif" as they are - //used by the compiler and will cause program errors if modified/removed. It's okay to translate the strings though. -#ifdef JA2BETAVERSION - L"Вероятно, файлы сохранения повреждены. Желаете удалить их?", -#else - L"Пытаюсь загрузить старую версию файла сохранения. Автоматически обновить и загрузить файл?", -#endif - - L"Вы решили записать игру на существующее сохранение #%d?", - L"Хотите загрузить игру из сохранения #", - - - //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"У вас заканчивается свободное место на жестком диске. Сейчас свободно %d Мб, а требуется %d Мб свободного места для JA.", - - L"Сохраняю...", //When saving a game, a message box with this string appears on the screen - - L"Нормальный", - L"Расширенный", - L"Реалистичный", - L"Фантастический", - - L"Стиль игры", //пр - L"Золотая серия", //Placeholder English - L"Бобби Рей", - L"Нормальный", - L"Большой", - L"Огромный", - L"Все, включая эксклюзив", - - L"Новый инвентарь, используемый в этом релизе, не работает при разрешении экрана 640х480. Измените разрешение и запустит игру заново.", - L"Новый инвентарь не работает, если выбрана по умолчанию игровая папка 'Data'.", -}; - - - -//MapScreen -STR16 zMarksMapScreenText[] = -{ - L"Уровень карты", - L"У вас нет ополченцев. Чтобы они появились, вам нужно склонить на свою сторону горожан.", - L"Доход в сутки", - L"Наемник застрахован", - L"%s не нуждается в отдыхе.", - L"%s на марше и не может лечь спать.", - L"%s валится с ног от усталости, погоди немного.", - L"%s ведет машину.", - L"Отряд не может двигаться, когда один из наемников спит.", - - // stuff for contracts - L"Хотя у вас и есть деньги на подписание контракта, но их не хватит, чтобы оплатить страховку наемника.", - L"%s: продление страховки составит %s за %d дополнительных дней. Желаете заплатить?", - L"Предметы в секторе", - L"Жизнь наемника застрахована.", - - // other items - L"Медики", // people acting a field medics and bandaging wounded mercs - L"Раненые", // people who are being bandaged by a medic - L"Готово", // Continue on with the game after autobandage is complete - L"Стоп", // Stop autobandaging of patients by medics now - L"Извините, этот пункт недоступен в демонстрационной версии.", // informs player this option/button has been disabled in the demo - L"%s: нет инструментов.", - L"%s: нет аптечки.", - L"Здесь недостаточно добровольцев для тренировки.", - L"В %s максимальное количество ополченцев.", - L"У наемника ограниченный контракт.", - L"Контракт наемника не застрахован", - L"Карта Арулько", // 24 -}; - - -STR16 pLandMarkInSectorString[] = -{ - L"Отряд %d заметил кого-то в секторе %s.", -}; - -// confirm the player wants to pay X dollars to build a militia force in town -STR16 pMilitiaConfirmStrings[] = -{ - L"Тренировка отряда ополченцев будет стоить $", // telling player how much it will cost - L"Подтвердить платеж?", // asking player if they wish to pay the amount requested - L"Вы не можете себе этого позволить.", // telling the player they can't afford to train this town - L"Продолжить тренировку в %s (%s %d)?", // continue training this town? - L"Цена $", // the cost in dollars to train militia - L"( Д/Н )", // abbreviated yes/no - L"", // unused - L"Тренировка ополчения в секторе %d будет стоить $%d. %s", // cost to train sveral sectors at once - L"У вас нет $%d, чтобы приступить к тренировке ополчения.", - L"%s: Требуется не менее %d процентов лояльности, чтобы продолжить тренировку ополчения.", - L"Больше вы не можете тренировать ополчение в %s.", -}; - -//Strings used in the popup box when withdrawing, or depositing money from the $ sign at the bottom of the single merc panel -STR16 gzMoneyWithdrawMessageText[] = -{ - L"За один раз вы можете снять со счета не более $20.000.", - L"Вы решили положить %s на свой счет?", -}; - -STR16 gzCopyrightText[] = -{ - L"Aвтopcкиe пpaвa (C) 1999 Sir-Tech Canada Ltd. Bce пpaвa зaщищeны.", -}; - -//option Text -STR16 zOptionsToggleText[] = -{ - L"Речь", - L"Молчаливые герои", //$$ - L"Субтитры", - L"Пауза в диалогах", - L"Анимированный дым", - L"Кровь и жестокость", - L"Не трогать мышь!", - L"Старый метод выбора", - L"Показывать путь движения", - L"Показывать промахи", - L"Игра в реальном времени", - L"Подтверждение сна/подъема", - L"Метрическая система", - L"Движущаяся подсветка бойца", - L"Курсор на бойцов", - L"Курсор на дверь", - L"Мерцание вещей", - L"Показать кроны деревьев", - L"Показывать каркасы", - L"Трехмерный курсор", - L"Показывать шанс попадания", - L"Курсор очереди для гранат", - L"Выпадение всего из врагов", //Весь трофей врага - L"Стрельба гранатой навесом", - L"Классическое прицеливание", - L"Выбор пробелом след. отряда", - L"Тени предметов в инвентаре", - L"Дальность оружия в тайлах", - L"Одиночный трассер", - L"Шум дождя", - L"Вороны", - L"Случайный I.M.P персонаж", - L"Автосохранение каждый ход", - L"Молчаливый пилот вертолета", - L"Низкое использование CPU", -}; - -//This is the help text associated with the above toggles. -STR16 zOptionsScreenHelpText[] = -{ - //speech - L"Включить или выключить\nголос во время диалогов.", - - //Mute Confirmation - L"Включить или выключить речевое\nподтверждение выполнения приказов.", - - //Subtitles - L"Включить или выключить отображение\nсубтитров во время диалогов.", //$$ - - //Key to advance speech - L"Если субтитры включены, выберите этот пункт,\nчтобы успеть прочитать диалоги персонажей.", - - //Toggle smoke animation - L"Отключите анимацию дыма,\nесли он замедляет игру.", - - //Blood n Gore - L"Отключите этот пункт, если боитесь крови.", - - //Never move my mouse - L"Если выключено, то курсор автоматически перемещается\nна кнопку всплывающего окна диалога.", - - //Old selection method - L"Если включено, то будет использоваться старый метод выбора наемников\n(для тех, кто привык к управлению предыдущих частей Jagged Alliance).", - - //Show movement path - L"Если включено, то в режиме реального времени будет отображаться путь передвижения\n(если выключено, нажмите SHIFT, чтобы увидеть путь).", - - //show misses - L"Если включено, то камера будет отслеживать\nтраекторию пуль, прошедших мимо цели.", - - //Real Time Confirmation - L"Если включено, то для приказа на передвижение будет требоваться\nдополнительный, подтверждающий щелчок мыши на месте назначения.", - - //Display the enemy indicator - L"Если включено, то вы получите предупреждение,\nкогда наемники лягут спать или проснутся.", - - //Use the metric system - L"Если включено, то используется метрическая система мер,\nиначе будет британская.", - - //Merc Lighted movement - L"При ходьбе карта подсвечивается вокруг бойца.\nВыключите опцию для повышения производительности системы.", - - //Smart cursor - L"Если включено, то перемещение курсора возле наемника\nавтоматически выбирает его.", - - //snap cursor to the door - L"Если включено, то перемещение курсора возле двери\nавтоматически помещает его на дверь.", - - //glow items - L"Если включено, то все предметы подсвечиваются. (|I)", - - //toggle tree tops - L"Если включено, то отображаются кроны деревьев. (|T)", - - //toggle wireframe - L"Если включено, то у препятствий\nдополнительно показывается каркас. (|W)", //$$ - - L"Если включено, то курсор передвижения\nотображается в 3D. (|Home )", - - // Options for 1.13 - L"Если включено, шанс попадания\nпоказывается над курсором.", - L"Если включено, очередь из гранатомета\nиспользует курсор стрельбы очередями.", - L"Если включено, из убитых врагов\nвыпадает все их снаряжение.", - L"Если включено, гранатометы выстреливают заряд под большим углом к горизонту (|Q).", - L"Если включено, из винтовок нельзя целится\nдольше 4 очков действия.", - L"Если включено, |П|р|о|б|е|л выделяет следующий отряд автоматически.", - L"Если включено, показываются тени предметов в инвентаре.", - L"Если включено, дальность оружия показывается в тайлах.", - L"Если включено, трассирующий эффект\nсоздается одиночным выстрелом.", - L"Если включено, вы услышите шум дождя во время непогоды.", - L"Если включено, вороны присутствуют в игре.", - L"Если включено, персонаж I.M.P будет получать\nслучайную внешность и характеристики.", - L"Если включено, игра будет автоматически сохраняться\nпосле каждого хода игрока.", - L"Если включено, Небесный Всадник\nне будет вас раздражать болтливостью.", - L"Если включено, игра будет использовать\nменьше процессорного времени.", -}; - - -STR16 gzGIOScreenText[] = -{ - L"УСТАНОВКА НАЧАЛА ИГРЫ", - L"Стиль игры", - L"Реалистичный", - L"Фантастический", - L"Золотая серия", //Placeholder English - L"Выбор оружия", - L"Расширенный", - L"Нормальный", - L"Уровень сложности", - L"Легкий", - L"Нормальный", - L"Трудный", - L"БЕЗУМИЕ", - L"Начать игру", - L"Главное меню", - L"Дополнительная сложность", - L"Сохранение в любое время", - L"СТАЛЬНАЯ ВОЛЯ", - L"Отключено в демо-версии", - L"Ассортимент Бобби Рэя", - L"Нормальный", - L"Большой", - L"Огромный", - L"Все, включая эксклюзив", - L"Режим инвентаря", - L"Классический", - L"Новый вариант", -}; - -STR16 pDeliveryLocationStrings[] = -{ - L"Остин", //Austin, Texas, USA - L"Багдад", //Baghdad, Iraq (Suddam Hussein's home) - L"Драссен", //The main place in JA2 that you can receive items. The other towns are dummy names... - L"Гонконг", //Hong Kong, Hong Kong - L"Бейрут", //Beirut, Lebanon (Middle East) - L"Лондон", //London, England - L"Лос-Анджелес", //Los Angeles, California, USA (SW corner of USA) - L"Медуна", //Meduna -- the other airport in JA2 that you can receive items. - L"Метавира", //The island of Metavira was the fictional location used by JA1 - L"Майами", //Miami, Florida, USA (SE corner of USA) - L"Москва", //Moscow, USSR - L"Нью-Йорк", //New York, New York, USA - L"Оттава", //Ottawa, Ontario, Canada -- where JA2 was made! - L"Париж", //Paris, France - L"Триполи", //Tripoli, Libya (eastern Mediterranean) - L"Токио", //Tokyo, Japan - L"Ванкувер", //Vancouver, British Columbia, Canada (west coast near US border) -}; - -STR16 pSkillAtZeroWarning[] = -{ //This string is used in the IMP character generation. It is possible to select 0 ability - //in a skill meaning you can't use it. This text is confirmation to the player. - L"Вы уверены? Значение 0 означает отсутствие этого навыка вообще." -}; - -STR16 pIMPBeginScreenStrings[] = -{ - L"( до 8 символов )", -}; - -STR16 pIMPFinishButtonText[ 1 ]= -{ - L"Анализ", //пр -}; - -STR16 pIMPFinishStrings[ ]= -{ - L"Спасибо, %s", //%s is the name of the merc -}; - -// the strings for imp voices screen -STR16 pIMPVoicesStrings[] = -{ - L"Голос", -}; - -STR16 pDepartedMercPortraitStrings[ ]= -{ - L"Погиб в бою", - L"Уволен", - L"Другое", -}; - -// title for program -STR16 pPersTitleText[] = -{ - L"Досье", //пр -}; - -// paused game strings -STR16 pPausedGameText[] = -{ - L"Пауза в игре", - L"Продолжить (|P|a|u|s|e)", - L"Пауза (|P|a|u|s|e)", -}; - - -STR16 pMessageStrings[] = -{ - L"Выйти из игры?", - L"Да", - L"ДА", - L"НЕТ", - L"ОТМЕНА", - L"НАНЯТЬ", - L"СОЛГАТЬ", - L"Нет описания.", //Save slots that don't have a description. - L"Игра сохранена.", - L"Игра сохранена.", - L"QuickSave", //The name of the quicksave file (filename, text reference) - L"SaveGame", //The name of the normal savegame file, such as SaveGame01, SaveGame02, etc. - L"sav", //The 3 character dos extension (represents sav) - L"..\\SavedGames", //The name of the directory where games are saved. - L"День", //пр - L"Наемн", //пр - L"Свободное место", //An empty save game slot - L"Демо", //Demo of JA2 - L"Ловля Багов", //State of development of a project (JA2) that is a debug build - L"Release", //Release build for JA2 - L"пвм", //пр //Abbreviation for Rounds per minute -- the potential # of bullets fired in a minute. - L"мин", //Abbreviation for minute. - L"м", //One character abbreviation for meter (metric distance measurement unit). - L"пуль", //пр //Abbreviation for rounds (# of bullets) - L"кг", //Abbreviation for kilogram (metric weight measurement unit) - L"фунт", //Abbreviation for pounds (Imperial weight measurement unit) - L"В начало", //пр //Home as in homepage on the internet. - L"USD", //Abbreviation to US dollars - L"н/д", //Lowercase acronym for not applicable. - L"Посмотрим что происходит тем временем в другом месте", //Meanwhile - L"%s: прибыл в сектор %s%s", //Name/Squad has arrived in sector A9. Order must not change without notifying - //SirTech - L"Версия", - L"Пустая ячейка быстрого сохр", - L"Эта ячейка зарезервирована для Быстрого Сохранения, которое можно провести с тактической карты или с глобальной карты, нажав клавиши ALT+S.", - L"Открытая", //возможно это про дверь, проверить - L"Закрытая", //возможно это про дверь, проверить - L"У вас заканчивается свободное дисковое пространство. На диске есть всего %sMб свободного места, а для Jagged Alliance 2 требуется %sMб.", - L"Из A.I.M. нанят боец %s.", - L"%s ловит %s.", //'Merc name' has caught 'item' -- let SirTech know if name comes after item. - L"%s принимает препарат.", //'Merc name' has taken the drug - L"%s: отсутствуют навыки в медицине.",//'Merc name' has no medical skill. - - //CDRom errors (such as ejecting CD while attempting to read the CD) - L"Нарушена целостность программы.", - L"ОШИБКА: CD-ROM открыт.", - - //When firing heavier weapons in close quarters, you may not have enough room to do so. - L"Нет места, чтобы вести отсюда огонь.", - - //Can't change stance due to objects in the way... - L"Сейчас нельзя изменить положение тела.", - - //Simple text indications that appear in the game, when the merc can do one of these things. - L"Выкинуть", - L"Бросить", - L"Передать", - - L"%s передан %s.", //"Item" passed to "merc". Please try to keep the item %s before the merc %s, otherwise, - //must notify SirTech. - L"Не хватает места, чтобы передать %s %s.", //pass "item" to "merc". Same instructions as above. - - //A list of attachments appear after the items. Ex: Kevlar vest ( Ceramic Plate 'Attached )' - L" присоединен )", - - //Cheat modes - L"Достигнут чит-уровень один.", - L"Достигнут чит-уровень два.", - - //Toggling various stealth modes - L"Отряд перешел в режим скрытности.", - L"Отряд перешел в обычный режим.", - L"%s теперь в режиме скрытности.", - L"%s теперь в обычном режиме.", - - //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"Каркас зданий ВКЛ.",//$$ - L"Каркас зданий ВЫКЛ.",//$$ - - //These are used in the cheat modes for changing levels in the game. Going from a basement level to - //an upper level, etc. - L"Нельзя подняться с этого уровня...", - L"Нет нижних этажей...", - L"Входим в подвал. Уровень %d...", - L"Покидаем подвал...", - - L".", // used in the shop keeper inteface to mark the ownership of the item eg Red's gun - L"Режим следования ВЫКЛ.", - L"Режим следования ВКЛ.", - L"3D курсор ВЫКЛ.", - L"3D курсор ВКЛ.", - L"Выбран %dй отряд.", - L"Не хватает денег, чтобы заплатить %s ежедневный гонорар %s", //first %s is the mercs name, the seconds is a string containing the salary - L"Нет", - L"%s не может уйти в одиночку.", - L"Файл сохранения был записан под названием SaveGame99.sav. Если необходимо, переименуйте его в SaveGame01 - SaveGame10 и тогда, он станет доступен в экране сохранений.", - L"%s: выпил(а) немного %s.", - L"Посылка прибыла в Драссен.", - L"%s прибудет в точку назначения (сектор %s) в %dй день, примерно в %s.", //first %s is mercs name, next is the sector location and name where they will be arriving in, lastely is the day an the time of arrival - L"В журнал добавлена запись!", - L"Очереди из гранат используют курсор стрельбы очередями (стрельба по площадям возможна)", - L"Очереди из гранат используют курсор метания (стрельба по площадям не возможна)", - L"Выпадение всего снаряжения ВКЛ", - L"Выпадение всего снаряжения ВЫКЛ", - L"Гранатометы стреляют под обычным углом", - L"Гранатометы стреляют навесом", -#ifdef JA2BETAVERSION - L"Игра сохранена в ячейку авто-сохранения.", -#endif -}; - - -CHAR16 ItemPickupHelpPopup[][40] = -{ - L"Взять", - L"Вверх", - L"Выбрать все", - L"Вниз", - L"Отмена" -}; - -STR16 pDoctorWarningString[] = -{ - L"%s слишком далеко, чтобы подлечиться.", - L"Ваши медики не могут оказать первую помощь всем раненым.", -}; - -STR16 pMilitiaButtonsHelpText[] = -{ - L"Уменьшить (правя кнопка)\nУвеличить (левая кнопка)\nчисло новобранцев", // button help text informing player they can pick up or drop militia with this button - L"Уменьшить (правая кнопка)\nУвеличить (левая кнопка)\nчисло рядовых", - L"Уменьшить (правая кнопка)\nУвеличить (левая кнопка)\nчисло элитных солдат", - L"Равномерно распределить\nополченцев по всем секторам.", -}; - -STR16 pMapScreenJustStartedHelpText[] = -{ - L"Отправляйтесь в A.I.M. и наймите бойцов (*Подсказка* - это в ноутбуке).", // to inform the player to hired some mercs to get things going - L"Когда будете готовы отправиться в Арулько, включите сжатие времени в правом нижнем углу экрана.", // to inform the player to hit time compression to get the game underway -}; - -STR16 pAntiHackerString[] = -{ - L"Ошибка. Пропущен или испорчен файл(ы). Игра прекращает работу.", -}; - - -STR16 gzLaptopHelpText[] = -{ - //Buttons: - L"Просмотреть почту", - L"Посетить Интернет сайты", - L"Просмотреть полученные данные", - L"Просмотреть журнал последних событий", - L"Показать информацию о команде", - L"Просмотреть финансовые отчеты", - L"Закрыть ноутбук", - - //Bottom task bar icons (if they exist): - L"Получена новая почта", - L"Получены новые данные", - - //Bookmarks: - L"Международная Ассоциация Наемников A.I.M.", - L"Бобби Рэй - заказ оружия через Интернет", - L"Институт Изучения Личности Наемника I.M.P.", - L"Центр рекрутов M.E.R.C.", - L"Похоронная служба Макгилликатти", - L"'Цветы по всему миру'", - L"Страховые агенты по контрактам A.I.M.", -}; - - -STR16 gzHelpScreenText[] = -{ - L"Закрыть экран помощи", -}; - -STR16 gzNonPersistantPBIText[] = -{ - L"Идет бой. Вы можете отступить только через тактический экран.", - L"Войти в сектор, чтобы продолжить бой. (|E)", - L"Провести бой автоматически (|A).", - L"Во время атаки врага автоматическую битву включить нельзя.", - L"После того как вы попали в засаду, автоматическую битву включить нельзя.", - L"Рядом рептионы - автоматическую битву включить нельзя.", - L"Рядом враждебные гражданские - автоматическую битву включить нельзя.", - L"Рядом кошки-убийцы - автоматическую битву включить нельзя.", - L"ИДЕТ БОЙ", - L"Сейчас вы не можете отступить.", -}; - -STR16 gzMiscString[] = -{ - L"Ваши ополченцы продолжают бой без помощи наемников...", - L"Сейчас машине топливо не требуется.", - L"Топливный бак полон на %d%%.", - L"%s полностью под контролем Дейдраны.", - L"Вы потеряли заправочную станцию.", -}; - -STR16 gzIntroScreen[] = -{ - L"Не удается найти вступительный видеоролик", -}; - -// 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 -// report a noise. -// e.g. "Sidney hears a loud sound of MOVEMENT coming from the SOUTH." -STR16 pNewNoiseStr[] = -{ - L"%s слышит %s звук %s.", - L"%s слышит %s звук движения %s.", - L"%s слышит %s скрип, идущий %s.", - L"%s слышит %s звук всплеска %s.", - L"%s слышит %s звук удара %s.", //$$ - L"%s слышит %s звук взрыва %s.", - L"%s слышит %s крик %s.", - L"%s слышит %s звук удара %s.", - L"%s слышит %s звук удара %s.", - L"%s слышит %s звон %s.", - L"%s слышит %s грохот %s.", -}; - -STR16 wMapScreenSortButtonHelpText[] = -{ - L"Сортировка по имени (|F|1)", - L"Сортировка по роду деятельности (|F|2)", - L"Сортировка по состоянию сна (|F|3)", - L"Сортировка по месту пребывания (|F|4)", - L"Сортировка по месту назначения (|F|5)", - L"Сортировка по времени контракта (|F|6)", -}; - - - -STR16 BrokenLinkText[] = -{ - L"Ошибка 404", - L"Сайт не найден.", -}; - - -STR16 gzBobbyRShipmentText[] = -{ - L"Последние поступления", - L"Заказ #", - L"Количество", - L"Заказано", -}; - - -STR16 gzCreditNames[]= -{ - L"Chris Camfield", - L"Shaun Lyng", - L"Kris Mornes", - L"Ian Currie", - L"Linda Currie", - L"Eric \"WTF\" Cheng", - L"Lynn Holowka", - L"Norman \"NRG\" Olsen", - L"George Brooks", - L"Andrew Stacey", - L"Scot Loving", - L"Andrew \"Big Cheese\" Emmons", - L"Dave \"The Feral\" French", - L"Alex Meduna", - L"Joey \"Joeker\" Whelan", -}; - - -STR16 gzCreditNameTitle[]= -{ - L"Ведущий программист игры", // Chris Camfield !!! - L"Дизайнер/Сценарист", // Shaun Lyng - L"Программист стратегической части и редактора", //Kris Marnes - L"Продюсер/Дизайнер", // Ian Currie - L"Дизайнер/Дизайн карт", // Linda Currie - L"Художник", // Eric \"WTF\" Cheng - L"Тестирование, поддержка", // Lynn Holowka - L"Главный художник", // Norman \"NRG\" Olsen - L"Мастер по звуку", // George Brooks - L"Дизайнер экранов/художник", // Andrew Stacey - L"Ведущий художник/аниматор", // Scot Loving - L"Ведущий программист", // Andrew \"Big Cheese Doddle\" Emmons - L"Программист", // Dave French - L"Программист стратегии и баланса игры", // Alex Meduna - L"Художник-портретист", // Joey \"Joeker\" Whelan", -}; - -STR16 gzCreditNameFunny[]= -{ - L"", // Chris Camfield - L"(Все еще зубрит правила пунктуации)", // Shaun Lyng - L"(\"Я просто вносил исправления.\")", //Kris \"The Cow Rape Man\" Marnes - L"(уже слишком стар для всего этого)", // Ian Currie - L"(также работает над Wizardry 8)", // Linda Currie - L"(тестировал проект под дулом пистолета)", // Eric \"WTF\" Cheng - L"(ушла от нас в CFSA - скатертью дорожка...)", // Lynn Holowka - L"", // Norman \"NRG\" Olsen - L"", // George Brooks - L"(поклонник Мертвой Головы и джаза)", // Andrew Stacey - L"(его настоящее имя Роберт)", // Scot Loving - L"(единственный ответственный человек)", // Andrew \"Big Cheese Doddle\" Emmons - L"(может опять заняться мотогонками)", // Dave French - L"(украден из Wizardry 8!)", // Alex Meduna - L"(еще делал предметы и загрузочные экраны!)", // Joey \"Joeker\" Whelan", -}; - -STR16 sRepairsDoneString[] = -{ - L"%s: завершен ремонт личных вещей.", - L"%s: завершен ремонт всего оружия и брони.", - L"%s: завершен ремонт всей экипировки отряда.", - L"%s: завершен ремонт всех вещей, имеющихся у отряда.", - L"%s: завершен ремонт всех вещей, имеющихся у отряда.", - L"%s: завершен ремонт всех вещей, имеющихся у отряда.", -}; - -STR16 zGioDifConfirmText[]= -{ - L"Вы выбрали ЛЕГКИЙ режим. Этот режим предназначен для тех, кто не знаком с Jagged Alliance и стратегическими играми вообще. Ваш выбор определит ход всей игры, так что будьте осторожны. Вы действительно хотите начать игру в этом режиме?", - L"Вы выбрали НОРМАЛЬНЫЙ режим. Этот режим предназначен для тех, кто знаком с Jagged Alliance или другими подобными играми. Ваш выбор определит ход всей игры, так что будьте осторожны. Вы действительно хотите начать игру в этом режиме?", - L"Вы выбрали ТРУДНЫЙ режим. Предупреждаем: не сетуйте на нас, если вас быстро разгромят. Ваш выбор определит ход всей игры, так что будьте осторожны. Вы действительно хотите начать игру в этом режиме?", - L"Вы выбрали режим БЕЗУМИЕ. Если игра уже пройдена на предыдущих трех уровнях сложности, то нужно подумать о смысле жизни, о происхождении вселенной и вообще... Но если вам все равно на что тратить время и нервы, то можете играть в этом режиме. Страшно?", -}; - -STR16 gzLateLocalizedString[] = -{ - L"%S файл для загрузки экрана не найден...", - - //1-5 - L"Робот не сможет покинуть этот сектор, пока кто-нибудь не возьмет пульт управления.", - - //This message comes up if you have pending bombs waiting to explode in tactical. - L"Сейчас нельзя включить сжатие времени. Дождитесь взрыва!", - - //'Name' refuses to move. - L"%s отказывается подвинуться.", - - //%s a merc name - L"%s: недостаточно очков действия для изменения положения.", - - //A message that pops up when a vehicle runs out of gas. - L"%s: закончилось топливо. Машина осталась в %c%d.", - - //6-10 - - // the following two strings are combined with the pNewNoise[] strings above to report noises - // heard above or below the merc - L"сверху", - L"снизу", - - //The following strings are used in autoresolve for autobandaging related feedback. - L"Никто из ваших наемников не имеет медицинских навыков.", - L"Нечем бинтовать. Ни у кого из наемников нет аптечки.", - L"Чтобы перевязать всех наемников, не хватило бинтов.", - L"Никто из ваших наемников не нуждается в перевязке.", - L"Автоматически перевязывать бойцов.", - L"Все ваши наемники перевязаны.", - - //14 - L"Арулько", - - L"(на крыше)", - - L"Здоровье: %d/%d", - - //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 против %d", - - L"%s полон!", //(ex "The ice cream truck is full") - - L"%s нуждается не в первой помощи или перевязке, а в серьезном лечении и/или отдыхе.", - - //20 - //Happens when you get shot in the legs, and you fall down. - L"Из-за ранения в ногу %s падает на землю!", - //Name can't speak right now. - L"%s сейчас не может говорить", - - //22-24 plural versions @@@2 elite to veteran - L"%d новобранца из ополчения произведены в элитных солдат.", - L"%d новобранца из ополчения произведены в рядовые.", - L"%d рядовых ополченца произведены в элитных солдат.", - - //25 - L"Кнопка", - - //26 - //Name has gone psycho -- when the game forces the player into burstmode (certain unstable characters) - L"%s приступ безумия!", - - //27-28 - //Messages why a player can't time compress. - L"Сейчас небезопасно включать сжатие времени - у вас есть наемники в секторе %s.", // - L"Сейчас небезопасно включать сжатие времени - у вас есть наемники в пещерах с жуками.", // - - //29-31 singular versions @@@2 elite to veteran - L"1 новобранец из ополчения стал элитным солдатом.", - L"1 новобранец из ополчения стал рядовым ополченцем.", - L"1 рядовой ополченец стал элитным солдатом.", - - //32-34 - L"%s ничего не говорит.", - L"Выбраться на поверхность?", - L"(%dй отряд)", - - //35 - //Ex: "Red has repaired Scope's MP5K". Careful to maintain the proper order (Red before Scope, Scope before MP5K) - L"%s отремонтировал(а) у %s %s", - - //36 - L"ГЕПАРД", - - //37-38 "Name trips and falls" - L"%s спотыкается и падает.", - L"Этот предмет отсюда взять невозможно.", - - //39 - L"Оставшиеся наемники не могут сражаться. Сражение с тварями продолжат ополченцы.", - - //40-43 - //%s is the name of merc. - L"%s: закончились медикаменты!", - L"%s: недостаточно навыков для лечения.", - L"%s: закончился ремонтный набор!", - L"%s: недостаточно навыков для ремонта.", //проверить! пишет когда все предметы отремонтированы "%s lacks the necessary skill to repair anything!" - - //44-45 - L"Время ремонта", - L"%s не видит этого человека.", - - //46-48 - L"%s: отвалилась ствольная насадка!", - L"В одном секторе может быть не более %d тренеров ополчения.", - L"Вы уверены?", - - //49-50 - L"Сжатие времени.", - L"Бак машины полон.", - - //51-52 Fast help text in mapscreen. - L"Возобновить сжатие времени (|П|р|о|б|е|л)", - L"Прекратить сжатие времени (|E|s|c)", - - //53-54 "Magic has unjammed the Glock 18" or "Magic has unjammed Raven's H&K G11" - L"%s починил(а) %s", - L"%s починил(а) %s (%s)", - - //55 - L"Нельзя включить сжатие времени при просмотре предметов в секторе.", - - L"CD Агония Власти не найден. Программа выходит в ОС.", - - L"Предметы успешно совмещены.", - - //58 - //Displayed with the version information when cheats are enabled. - L"Прогресс игры текущий/максимально достигнутый: %d%%/%d%%", - - //59 - L"Сопроводить Джона и Мэри?", - - L"Кнопка нажата.", //пишет при нажатии кнопки, к примеру кнопка в шкафу шиза - - L"%s чувствует что в бронежилете что-то треснуло!", - L"%s выпустил на %d больше пуль!", - L"%s выпустил на %d пулю больше!", -}; - -STR16 gzCWStrings[] = -{ - L"Нужна ли поддержка ополчения из соседних секторов?", -}; - -// WANNE: Tooltips -STR16 gzTooltipStrings[] = -{ - // Debug info - L"%s|Место: %d\n", - L"%s|Яркость: %d / %d\n", - L"%s|Дистанция до |Цели: %d\n", - L"%s|I|D: %d\n", - L"%s|Приказы: %d\n", - L"%s|Настрой: %d\n", - L"%s|Текущие |A|Ps: %d\n", - L"%s|Текущее |Здоровье: %d\n", - // Full info - L"%s|Каска: %s\n", - L"%s|Жилет: %s\n", - L"%s|Брюки: %s\n", - // Limited, Basic - L"|Броня: ", - L"Каска ", - L"Жилет ", - L"Брюки", - L"Одет", - L"нет брони", - L"%s|П|Н|В: %s\n", - L"нет ПНВ", - L"%s|Противогаз: %s\n", - L"нет противогаза", - L"%s|Голова,|Слот |1: %s\n", - L"%s|Голова,|Слот |2: %s\n", - L"\n(в рюкзаке) ", - L"%s|Оружие: %s ", - L"без оружия", - L"Пистолет", - L"Пистолет-пулемет", - L"Винтовка", - L"Ручной пулемет", - L"Ружье", - L"Нож", - L"Тяжелое оружие", - L"без каски", - L"без бронежилета", - L"без поножей", - L"|Броня: %s\n", -}; - -STR16 New113Message[] = -{ - L"Началась буря.", - L"Буря закончилась.", - L"Начался дождь.", - L"Дождь закончился.", - L"Опасайтесь снайперов...", - L"Огонь на подавление!", //suppression fire! - L"*", //BRST - всегда стабильна по количеству выпущеных пуль - L"***", //AUTO - регулируемая очередь (три звездочки - это потому что она можеть быть намного длиннее очереди с отсечкой) - L"ГР", //гранатомет - L"ГР *", // - L"ГР ***", // - L"Снайпер!", - L"Невозможно разделить деньги из-за предмета на курсоре.", - L"Точка высадки новых наемников перенесена в %s, так как предыдущая точка высадки %s захвачена противником.", - L"Выброшена вещь.", - L"Выброшены все вещи выбранной группы.", - L"Вещь продана голодающему населению Арулько.", - L"Проданы все вещи выбранной группы.", -}; - -// WANNE: This are the email texts, when one of the 4 new 1.13 MERC mercs have levelled up, that Speck sends -// INFO: Do not replace the ± characters. They indicate the (-> Newline) from the edt files -STR16 New113MERCMercMailTexts[] = -{ - // Gaston: Text from Line 39 in Email.edt - L"Пожалуйста, примите к сведению, что с настоящего момента гонорар Гастона увеличивается вследствие повышения его профессионального уровня. ± ± Спек Т. Кляйн ± ", - // Stogie: Text from Line 43 in Email.edt - L"Пожалуйста, примите к сведению, что повышение боевых навыков лейтенанта Хорга 'Сигары' влечет за собой повышение его гонорара. ± ± Спек Т. Кляйн ± ", - // Tex: Text from Line 45 in Email.edt - L"Прошу принять к сведению, что заслуги Текса позволяют ему требовать более достойной оплаты. Поэтому его гонорар был увеличен, чтобы соответствовать его умениям. ± ± Спек Т. Кляйн ± ", - // Biggens: Text from Line 49 in Email.edt - L"Ставим в известность, что отличная работа полковника Фредерика Биггенса заслуживает поощрения в виде повышения гонорара. Постановление считать действительным с текущего момента. ± ± Спек Т. Кляйн ± ", -}; - -// WANNE: These are the missing skills from the impass.edt file -// INFO: Do not replace the ± characters. They indicate the (-> Newline) from the edt files -STR16 MissingIMPSkillsDescriptions[] = -{ - // Sniper - L"Снайпер: У вас глаза ястреба. В свободное время вы развлекаетесь отстреливая крылышки у мух с расстояния 100 метров! ± ", - // Camouflage - L"Маскировка: На вашем фоне кусты выглядят синтетическими! ± ", -}; - -STR16 NewInvMessage[] = -{ - L"В данный момент поднять рюкзак нельзя.", - L"Вы не можете одновременно носить 2 рюкзака.", - L"Вы потеряли свой рюкзак...", - L"Замок рюкзака работает лишь во время битвы.", - L"Вы не можете передвигаться с открытым рюкзаком.", - L"Вы уверены что находитесь в здравом уме и отвечаете за свои действия? И вы в самом деле хотите продать весь хлам этого сектора голодающему населению Арулько?", - L"Вы уверены что находитесь в здравом уме и отвечаете за свои действия? И вы в самом деле хотите выбросить весь хлам, валяющийся в этом секторе?", -}; - -#endif //RUSSIAN +#ifdef PRECOMPILEDHEADERS +#include "Utils All.h" +#else +#endif +#include "Language Defines.h" +#include "text.h" +#include "Fileman.h" + +#ifdef RUSSIAN + +/* + +****************************************************************************************************** +** IMPORTANT TRANSLATION NOTES ** +****************************************************************************************************** + +GENERAL TOPWARE INSTRUCTIONS +- Always be aware that German 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 the German language 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...", + 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 + 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 + 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 + 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 + 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 Topware 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. + 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. + + 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 + uses 'M'. If you can't always find a match, then the best thing to do is append the 'M' at the end + of the string in this format: + + EX: L"Ecran De Carte (|M)" (this is the French translation) + + Other examples are used multiple times, like the Esc key or "|E|s|c" or Space -> (|S|p|a|c|e) + +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. + + EX: L"Clears all the mercs' positions,\nand allows you to re-enter them manually." + + Would appear as: + + Clears all the mercs' positions, + and allows you to re-enter them manually. + + NOTE: It is important that you don't pad the characters adjacent to the \n with spaces. If we did this + 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." + + Would appear as: (the second line is moved in a character) + + Clears all the mercs' positions, + and allows you to re-enter them manually. + + +@@@ NOTATION +************ + + 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. + +!!! NOTATION +************ + + As described above, the "!!!" notation should be used by Topware to ask questions and address problems as + SirTech uses the "@@@" notation. + +*/ + +STR16 pCreditsJA2113[] = +{ + L"@T,{;Разработчики JA2 v1.13", + L"@T,C144,R134,{;Программирование", + L"@T,C144,R134,{;Графика и звук", + L"@};(Многое было взято из других модов!)", + L"@T,C144,R134,{;Предметы", + L"@T,C144,R134,{;Также помогали", + L"@};(И многие другие, предложившие хорошие идеи и высказавшие важные замечания!)", +}; + +CHAR16 ItemNames[MAXITEMS][80] = +{ + L"" +}; + + +CHAR16 ShortItemNames[MAXITEMS][80] = +{ + L"" +}; + +// Different weapon calibres +// CAWS is Close Assault Weapon System and should probably be left as it is +// NATO is the North Atlantic Treaty Organization +// WP is Warsaw Pact +// cal is an abbreviation for calibre +CHAR16 AmmoCaliber[MAXITEMS][20];// = +//{ +// L"0", +// L",38 кал", +// L"9мм", +// L",45 кал", +// L",357 кал", +// L"12 кал", +// L"ОББ", +// L"5,45мм", +// L"5,56мм", +// L"7,62мм НАТО", +// L"7,62мм ВД", +// L"4,7мм", +// L"5,7мм", +// L"Монстр", +// L"Ракета", +// L"", // дротик +// L"", // пламя +//// L".50 cal", // barrett +//// L"9mm Hvy", // Val silent +//}; + +// 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 +// WP is Warsaw Pact +// cal is an abbreviation for calibre +CHAR16 BobbyRayAmmoCaliber[MAXITEMS][20] ;//= +//{ +// L"0", +// L",38 кал", +// L"9мм", +// L",45 кал", +// L",357 кал", +// L"12 кал", +// L"ОББ", +// L"5,45мм", +// L"5,56мм", +// L"7,62мм Н.", +// L"7,62мм ВД", +// L"4,7мм", +// L"5.7мм", +// L"Монстр", +// L"Ракета", +// L"", // дротик +//// L"", // flamethrower +//// L".50 cal", // barrett +//// L"9mm Hvy", // Val silent +//}; + + +CHAR16 WeaponType[][30] = +{ + L"", //Other + L"Пистолет", //Pistol + L"Авт.пистолет", //MP //'Автоматический пистолет' + L"ПП", //SMG //'Пистолет-пулемет' + L"Винтовка", //Rifle + L"Сн.винтовка", //Sniper rifle //'Снайперская винтовка' + L"Шт.винтовка", //Assault rifle //'Штурмовая винтовка' + L"Ручной пулемет", //LMG //'Ручной пулемет' + L"Ружье" //Shotgun //'Гладкоствольное ружье' +}; + +CHAR16 TeamTurnString[][STRING_LENGTH] = +{ + L"Ход Игрока", // player's turn + L"Ход Противника", + L"Ход Тварей", + L"Ход Ополчения", + L"Ход Гражданских" + L"Player_Plan",// planning turn + L"Client #1",//hayden + L"Client #2",//hayden + L"Client #3",//hayden + L"Client #4",//hayden +}; + +CHAR16 Message[][STRING_LENGTH] = +{ + L"", + + // In the following 8 strings, the %s is the merc's name, and the %d (if any) is a number. + + L"%s получает ранение в голову и теряет в интеллекте!", + L"%s получает ранение в плечо и теряет в ловкости!", + L"%s получает ранение в грудь и теряет в силе!", + L"%s получает ранение в ногу и теряет в проворности!", + L"%s получает ранение в голову и теряет %d очков интеллекта!", + L"%s получает ранение в плечо и теряет %d очков ловкости!", + L"%s получает ранение в грудь и теряет %d очков силы!", + L"%s получает ранение в ногу и теряет %d очков проворности!", + L"Перехват!", + + // The first %s is a merc's name, the second is a string from pNoiseVolStr, + // the third is a string from pNoiseTypeStr, and the last is a string from pDirectionStr + + L"", //OBSOLETE + L"К вам на помощь прибыло подкрепление!", + + // In the following four lines, all %s's are merc names + + L"%s перезаряжает оружие.", + L"%s недостаточно очков действия!", + L"%s оказывает первую помощь (любая клавиша - отмена).", + L"%s и %s оказывают первую помощь (любая клавиша - отмена).", + // the following 17 strings are used to create lists of gun advantages and disadvantages + // (separated by commas) + L"надежен", + L"ненадежен", + L"простой ремонт", + L"сложный ремонт", + L"большой урон", + L"малый урон", + L"скорострельный", + L"нескоростр.", + L"дальний бой", + L"ближний бой", + L"легкий", + L"тяжелый", + L"компактный", + L"очередями", + L"", //нет отсечки очереди + L"бол.магазин", + L"мал.магазин", + + // In the following two lines, all %s's are merc names + + L"%s: камуфляжная краска стерлась.", + L"%s: камуфляжная краска смылась.", + + // The first %s is a merc name and the second %s is an item name + + L"Второе оружие: закончились патроны!", + L"%s крадет %s.", + + // The %s is a merc name + + L"%s: оружие не стреляет очередями.", + + L"Уже установлено!", //не используется, применялось при приаттачивании аттача когда такой же уже приаттачен + L"Объединить?", //используется если предметом-аттачем на курсоре кликнуть на предмет, лежащий в слоте руки + + // Both %s's are item names + + L"Нельзя присоединить %s к %s.", + + L"Ничего", + L"Разрядить", + L"Навеска", + + //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"Нельзя использовать %s и %s одновременно.", + + L"Этот предмет можно присоединить к другим предметам, поместив его в одно из четырех мест для приспособлений.", + L"Этот предмет можно присоединить к другим предметам, поместив его в одно из четырех мест для приспособлений. (Однако эти предметы несовместимы)", + L"В секторе еще остались враги!", + L"%s требует полную оплату, нужно заплатить еще %s", + L"%s: попадание в голову!", + L"Покинуть битву?", + L"Это несъемное приспособление. Установить его?", + L"%s чувствует прилив энергии!", + L"%s поскальзывается на стеклянных шариках!", + L"%s не удалось отобрать %s у врага!", + L"%s чинит %s", + L"Перехватили ход: ", //при перехвате хода у врага + L"Сдаться?", + L"Человек отверг вашу помощь.", + L"Вам это надо?", //появляется при попытке перевязать жука или кошку + L"Чтобы воспользоваться вертолетом Небесного Всадника выберите 'Машина/Вертолет'.", + L"%s успевает зарядить только одно оружие.", //%s only had enough time to reload ONE gun + L"Ход Кошек-Убийц", //Bloodcats' turn + L"автоматический", //full auto + L"неавтоматический", //no full auto + L"точный", //accurate + L"неточный", //inaccurate + L"нет одиночных", //no semi auto + L"Враг обобран до нитки!", + L"У врага в руках ничего нет!", +}; + + +// the names of the towns in the game + +CHAR16 pTownNames[MAX_TOWNS][MAX_TOWN_NAME_LENGHT] = +{ + L"", + L"Омерта", + L"Драссен", + L"Альма", + L"Грам", + L"Тикса", + L"Камбрия", + L"Сан-Мона", + L"Эстони", + L"Орта", + L"Балайм", + L"Медуна", + L"Читзена", +}; + +// the types of time compression. For example: is the timer paused? at normal speed, 5 minutes per second, etc. +// min is an abbreviation for minutes + +STR16 sTimeStrings[] = +{ + L"Пауза", + L"Норма", //есть подозрение, что в игре этого не увидиш + L"5 мин", + L"30 мин", + L"60 мин", + L"6 часов", //есть подозрение, что в игре этого не увидиш +}; + + +// 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[] = +{ + L"Отряд 1", + L"Отряд 2", + L"Отряд 3", + L"Отряд 4", + L"Отряд 5", + L"Отряд 6", + L"Отряд 7", + L"Отряд 8", + L"Отряд 9", + L"Отряд 10", + L"Отряд 11", + L"Отряд 12", + L"Отряд 13", + L"Отряд 14", + L"Отряд 15", + L"Отряд 16", + L"Отряд 17", + L"Отряд 18", + L"Отряд 19", + L"Отряд 20", + L"На службе", // on active duty //SB: коряво + L"Медик", // оказывает медпомощь + L"Пациент", //принимает медпомощь + L"Транспорт", // in a vehicle + L"В пути", //транзитом - сокращение + L"Ремонт", // ремонтируются + L"Практика", // тренируются + L"Ополчение", //готовят восстание среди горожан + L"Тренер", // training a teammate + L"Ученик", // being trained by someone else + L"Мертв", // мертв + L"Недеесп.", // abbreviation for incapacitated + L"В плену", // Prisoner of war - captured + L"Госпиталь", // patient in a hospital + L"Пуст", // Vehicle is empty +}; + + +STR16 pMilitiaString[] = +{ + L"Ополчение", // the title of the militia box + L"Запас", //the number of unassigned militia troops + L"Нельзя перераспределять ополчение, когда враг находится в этом районе!", +}; + + +STR16 pMilitiaButtonString[] = +{ + L"Авто", // auto place the militia troops for the player + L"Готово", // done placing militia troops +}; + +STR16 pConditionStrings[] = +{ + L"Отличное", //состояние солдата..отличное здоровье + L"Хорошее", //хорошее здоровье + L"Сносное", //нормальное здоровье + L"Ранен", //раны + L"Устал", // усталый + L"Кровотечение", // истекает кровью + L"Без сознания", // в обмороке + L"Умирает", //умирает + L"Мертв", // мертв +}; + +STR16 pEpcMenuStrings[] = +{ + L"Сражаться", // set merc on active duty //это строки из меню ТОЛЬКО для эскортируемых + L"Пациент", // set as a patient to receive medical aid + L"Транспорт", // tell merc to enter vehicle + L"Без эскорта", // охрана покидает героя + L"Отмена", // выход из этого меню +}; + + +// look at pAssignmentString above for comments + +STR16 pPersonnelAssignmentStrings[] = +{ + L"Отряд 1", + L"Отряд 2", + L"Отряд 3", + L"Отряд 4", + L"Отряд 5", + L"Отряд 6", + L"Отряд 7", + L"Отряд 8", + L"Отряд 9", + L"Отряд 10", + L"Отряд 11", + L"Отряд 12", + L"Отряд 13", + L"Отряд 14", + L"Отряд 15", + L"Отряд 16", + L"Отряд 17", + L"Отряд 18", + L"Отряд 19", + L"Отряд 20", + L"На службе", + L"Медик", + L"Пациент", + L"Транспорт", + L"В пути", + L"Ремонт", + L"Практика", + L"Ополчение", + L"Тренер", + L"Ученик", + L"Мертв", + L"Недеесп.", + L"В плену", + L"Госпиталь", + L"Пуст", // Vehicle is empty +}; + + +// refer to above for comments + +STR16 pLongAssignmentStrings[] = +{ + L"Отряд 1", + L"Отряд 2", + L"Отряд 3", + L"Отряд 4", + L"Отряд 5", + L"Отряд 6", + L"Отряд 7", + L"Отряд 8", + L"Отряд 9", + L"Отряд 10", + L"Отряд 11", + L"Отряд 12", + L"Отряд 13", + L"Отряд 14", + L"Отряд 15", + L"Отряд 16", + L"Отряд 17", + L"Отряд 18", + L"Отряд 19", + L"Отряд 20", + L"На службе", + L"Медик", + L"Пациент", + L"Транспорт", + L"В пути", + L"Ремонт", + L"Практика", + L"Ополчение", + L"Тренер", + L"Ученик", + L"Мертв", + L"Недеесп.", + L"В плену", + L"Госпиталь", // patient in a hospital + L"Пуст", // Vehicle is empty +}; + + +// the contract options + +STR16 pContractStrings[] = +{ + L"Изменение контракта:", + L"", // a blank line, required + L"Продлить на 1 день", // offer merc a one day contract extension + L"Продлить на 7 дней", // 1 week + L"Продлить на 14 дней", // 2 week + L"Уволить", // end merc's contract + L"Отмена", // stop showing this menu +}; + +STR16 pPOWStrings[] = +{ + L"В плену", //an acronym for Prisoner of War + L"??", +}; + +STR16 pLongAttributeStrings[] = +{ + L"СИЛА", + L"ЛОВКОСТЬ", + L"ПРОВОРНОСТЬ", + L"ИНТЕЛЛЕКТ", + L"МЕТКОСТЬ", + L"МЕДИЦИНА", + L"МЕХАНИКА", + L"ЛИДЕРСТВО", + L"ВЗРЫВЧАТКА", + L"УРОВЕНЬ", +}; + +STR16 pInvPanelTitleStrings[] = +{ + L"Броня", // the armor rating of the merc + L"Вес", // the weight the merc is carrying //'Груз' + L"Камуф.", // the merc's camouflage rating //надо поменять местами броня и камуфляж для окна инвенторя наемника + L"Камуфляж:", + L"Броня:", +}; + +STR16 pShortAttributeStrings[] = +{ + L"Прв", // the abbreviated version of : agility + L"Лов", // dexterity + L"Сил", // strength + L"Лид", // leadership + L"Инт", // wisdom + L"Опт", // experience level + L"Мет", // marksmanship skill + L"Взр", // explosive skill + L"Мех", // mechanical skill + L"Мед", // medical skill +}; + + +STR16 pUpperLeftMapScreenStrings[] = +{ + L"Назначение", // the mercs current assignment + L"Контракт", // the contract info about the merc + L"Здоровье", // the health level of the current merc + L"Мораль", // the morale of the current merc + L"Сост.", // the condition of the current vehicle + L"Бензин", // the fuel level of the current vehicle +}; + +STR16 pTrainingStrings[] = +{ + L"Тренинг", // tell merc to train self + L"Ополчение", // tell merc to train town + L"Тренер", // tell merc to act as trainer + L"Ученик", // tell merc to be train by other +}; + +STR16 pGuardMenuStrings[] = +{ + L"Скоростр.:", // the allowable rate of fire for a merc who is guarding + L" Агрессивная атака", // the merc can be aggressive in their choice of fire rates + L" Беречь патроны", // conserve ammo + L" Воздержаться от стрельбы", // fire only when the merc needs to + L"Другие параметры:", // other options available to merc + L" Может отступить", // merc can retreat + L" Может искать укрытие", // merc is allowed to seek cover + L" Может помочь команде", // merc can assist teammates + L"Готово", // done with this menu + L"Отмена", // cancel this menu +}; + +// This string has the same comments as above, however the * denotes the option has been selected by the player + +STR16 pOtherGuardMenuStrings[] = +{ + L"Скоростр.:", + L" *Агрессивная атака*", + L" *Беречь патроны*", + L" *Воздержаться от стрельбы*", + L"Другие параметры:", + L" *Может отступить*", + L" *Может искать укрытие*", + L" *Может помочь команде*", + L"Готово", + L"Отмена", +}; + +STR16 pAssignMenuStrings[] = +{ + L"На службе", // merc is on active duty + L"Медик", // the merc is acting as a doctor + L"Пациент", // the merc is receiving medical attention + L"Машина", // the merc is in a vehicle + L"Ремонт", // the merc is repairing items + L"Обучение", // the merc is training //обучение + L"Отмена", // cancel this menu +}; + +//lal +STR16 pMilitiaControlMenuStrings[] = +{ + L"В атаку", // set militia to aggresive + L"Держать оборону", // set militia to stationary + L"Отступать", // retreat militia + L"За мной", // retreat militia + L"Ложись", // retreat militia + L"В укрытие", + L"Все в атаку", + L"Всем держать оборону", + L"Всем отступать", + L"Все за мной", + L"Всем рассеяться", + L"Всем залечь", + L"Всем в укрытие", + //L"Всем искать предметы", + L"Отмена", // cancel this menu +}; + +//STR16 pTalkToAllMenuStrings[] = +//{ +// L"Attack", // set militia to aggresive +// L"Hold Position", // set militia to stationary +// L"Retreat", // retreat militia +// L"Come to me", // retreat militia +// L"Get down", // retreat militia +// L"Cancel", // cancel this menu +//}; + +STR16 pRemoveMercStrings[] = +{ + L"Убрать бойца", // remove dead merc from current team + L"Отмена", +}; + +STR16 pAttributeMenuStrings[] = +{ + L"Сила", + L"Ловкость", + L"Проворность", + L"Здоровье", + L"Меткость", + L"Медицина", + L"Механика", + L"Лидерство", + L"Взрывчатка", + L"Отмена", +}; + +STR16 pTrainingMenuStrings[] = +{ + L"Практика", // train yourself + L"Ополчение", // train the town + L"Тренер", // train your teammates + L"Ученик", // be trained by an instructor + L"Отмена", // cancel this menu +}; + + +STR16 pSquadMenuStrings[] = +{ + L"Отряд 1", + L"Отряд 2", + L"Отряд 3", + L"Отряд 4", + L"Отряд 5", + L"Отряд 6", + L"Отряд 7", + L"Отряд 8", + L"Отряд 9", + L"Отряд 10", + L"Отряд 11", + L"Отряд 12", + L"Отряд 13", + L"Отряд 14", + L"Отряд 15", + L"Отряд 16", + L"Отряд 17", + L"Отряд 18", + L"Отряд 19", + L"Отряд 20", + L"Отмена", +}; + +STR16 pPersonnelTitle[] = +{ + L"Команда", // the title for the personnel screen/program application +}; + +STR16 pPersonnelScreenStrings[] = +{ + L"Здоровье:", // health of merc + L"Проворность:", + L"Ловкость:", + L"Сила:", + L"Лидерство:", + L"Интеллект:", + L"Опыт:", // experience level + L"Меткость:", + L"Механика:", + L"Взрывчатка:", + L"Медицина:", + L"Мед. депозит:", // amount of medical deposit put down on the merc + L"До конца контракта:", // cost of current contract + L"Убил врагов:", // number of kills by merc + L"Помог убить:", // number of assists on kills by merc + L"Гонорар за день:", // daily cost of merc + L"Общая цена услуг:", // total cost of merc + L"Контракт:", // cost of current contract + L"У вас на службе:", // total service rendered by merc + L"Задолж. жалования:", // amount left on MERC merc to be paid + L"Процент попаданий:", // percentage of shots that hit target + L"Боев:", // number of battles fought + L"Ранений:", // number of times merc has been wounded + L"Навыки:", + L"Нет навыков", +}; + + +//These string correspond to enums used in by the SkillTrait enums in SoldierProfileType.h +STR16 gzMercSkillText[] = +{ + L"Нет навыка", + L"Взлом замков", + L"Рукопашный бой", + L"Электроника", + L"Ночные операции", + L"Метание", + L"Инструктор", + L"Тяжелое оружие", + L"Авт. оружие", + L"Скрытность", + L"Стрельба с двух рук", + L"Воровство", + L"Боевые искусства", + L"Холодное оружие", + L"Снайпер", + L"Камуфляж", + L"Камуфляж (Город)", + L"Камуфляж (Пустыня)", + L"Камуфляж (Снег)", + L"(Эксперт)", +}; + + +// This is pop up help text for the options that are available to the merc + +STR16 pTacticalPopupButtonStrings[] = +{ + L"Встать/Идти (|S)", + L"Присесть/Гусиный шаг (|C)", + L"Стоять/Бежать (|R)", + L"Лечь/Ползти (|P)", + L"Поворот (|L)", + L"Действие", + L"Поговорить", + L"Осмотреть (|C|t|r|l)", + + // Pop up door menu + L"Открыть", + L"Искать ловушки", + L"Вскрыть отмычками", + L"Открыть cилой", + L"Обезвредить", + L"Запереть", + L"Отпереть", + L"Использовать заряд взрывчатки", + L"Взломать ломом", + L"Отмена (|E|s|c)", + L"Закрыть", +}; + +// Door Traps. When we examine a door, it could have a particular trap on it. These are the traps. + +STR16 pDoorTrapStrings[] = +{ + L"нет ловушки", + L"бомба-ловушка", + L"электроловушка", + L"сирена", + L"сигнализация" +}; + +// Contract Extension. These are used for the contract extension with AIM mercenaries. + +STR16 pContractExtendStrings[] = +{ + L"1 день", + L"7 дней", + L"14 дней", +}; + +// On the map screen, there are four columns. This text is popup help text that identifies the individual columns. + +STR16 pMapScreenMouseRegionHelpText[] = +{ + L"Выбрать наемника", + L"Отдать приказ", + L"Проложить путь движения", + L"Контракт наемника (|C)", + L"Местонахождение бойца", + L"Спать", +}; + +// volumes of noises + +STR16 pNoiseVolStr[] = +{ + L"ТИХИЙ", + L"ЧЕТКИЙ", + L"ГРОМКИЙ", + L"ОЧЕНЬ ГРОМКИЙ" +}; + +// types of noises + +STR16 pNoiseTypeStr[] = // OBSOLETE +{ + L"НЕЗНАКОМЫЙ", + L"ЗВУК ШАГОВ", + L"СКРИП", + L"ВСПЛЕСК", + L"УДАР", + L"ВЫСТРЕЛ", + L"ВЗРЫВ", + L"КРИК", + L"УДАР", + L"УДАР", + L"ЗВОН", + L"ГРОХОТ" +}; + +// Directions that are used to report noises + +STR16 pDirectionStr[] = +{ + L"c СЕВЕРО-ВОСТОКА", + L"c ВОСТОКА", + L"c ЮГО-ВОСТОКА", + L"c ЮГА", + L"c ЮГО-ЗАПАДА", + L"c ЗАПАДА", + L"c СЕВЕРО-ЗАПАДА", + L"c СЕВЕРА" +}; + +// These are the different terrain types. + +STR16 pLandTypeStrings[] = +{ + L"Город", + L"Дорога", + L"Равнина", + L"Пустыня", + L"Прерия", + L"Лес", + L"Болото", + L"Вода", + L"Холмы", + L"Непроходимо", + L"Река", //river from north to south + L"Река", //river from east to west + L"Чужая страна", + //NONE of the following are used for directional travel, just for the sector description. + L"Тропики", + L"Ферма", + L"Поля, дорога", + L"Леса, дорога", + L"Ферма, дорога", + L"Тропики, дорога", + L"Леса, дорога", + L"Побережье", + L"Горы, дорога", + L"Берег, дорога", + L"Пустыня, дорога", + L"Болота, дорога", + L"Прерия, ПВО", + L"Пустыня, ПВО", + L"Тропики, ПВО", + L"Медуна, ПВО", + + //These are descriptions for special sectors + L"Госпиталь Камбрии", + L"Аэропорт Драссена", + L"Аэропорт Медуны", + L"База ПВО", + L"Убежище повстанцев", //The rebel base underground in sector A10 + L"Подвалы Тиксы", //The basement of the Tixa Prison (J9) + L"Логово тварей", //Any mine sector with creatures in it + L"Подвалы Орты", //The basement of Orta (K4) + L"Туннель", //The tunnel access from the maze garden in Meduna + //leading to the secret shelter underneath the palace + L"Убежище", //The shelter underneath the queen's palace + L"", //Unused +}; + +STR16 gpStrategicString[] = +{ + L"", //Unused + L"%s замечен в секторе %c%d, и другой отряд уже на подходе.", //STR_DETECTED_SINGULAR + L"%s замечен в секторе %c%d, и остальные отряды уже на подходе.", //STR_DETECTED_PLURAL + L"Желаете дождаться прибытия остальных?", //STR_COORDINATE + + //Dialog strings for enemies. + + L"Враг предлагает вам сдаться.", //STR_ENEMY_SURRENDER_OFFER + L"Оставшиеся без сознания бойцы попали в плен.", //STR_ENEMY_CAPTURED + + //The text that goes on the autoresolve buttons + + L"Отступить", //The retreat button //STR_AR_RETREAT_BUTTON + L"OK", //The done button //STR_AR_DONE_BUTTON + + //The headers are for the autoresolve type (MUST BE UPPERCASE) + + L"ОБОРОНА", //STR_AR_DEFEND_HEADER + L"АТАКА", //STR_AR_ATTACK_HEADER + L"ВСТРЕЧА", //STR_AR_ENCOUNTER_HEADER + L"Сектор", //The Sector A9 part of the header //STR_AR_SECTOR_HEADER + + //The battle ending conditions + + L"ПОБЕДА!", //STR_AR_OVER_VICTORY + L"ПОРАЖЕНИЕ!", //STR_AR_OVER_DEFEAT + L"СДАЛСЯ!", //STR_AR_OVER_SURRENDERED + L"ПЛЕНЕН!", //STR_AR_OVER_CAPTURED + L"ОТСТУПИЛ!", //STR_AR_OVER_RETREATED + + //These are the labels for the different types of enemies we fight in autoresolve. + + L"Ополченец", //STR_AR_MILITIA_NAME, + L"Элита", //STR_AR_ELITE_NAME, + L"Солдат", //STR_AR_TROOP_NAME, + L"Смотритель", //STR_AR_ADMINISTRATOR_NAME, + L"Рептион", //STR_AR_CREATURE_NAME, + + //Label for the length of time the battle took + + L"Прошло времени", //STR_AR_TIME_ELAPSED, + + //Labels for status of merc if retreating. (UPPERCASE) + + L"ОТСТУПИЛ", //STR_AR_MERC_RETREATED, + L"ОТСТУПАЕТ", //STR_AR_MERC_RETREATING, + L"ОТСТУПИТЬ", //STR_AR_MERC_RETREAT, + + //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) + + L"Авто битва", //STR_PB_AUTORESOLVE_BTN, + L"Перейти в сектор", //STR_PB_GOTOSECTOR_BTN, + L"Уйти из сектора", //STR_PB_RETREATMERCS_BTN, + + //The different headers(titles) for the prebattle interface. + L"ВСТРЕЧА С ВРАГОМ", //STR_PB_ENEMYENCOUNTER_HEADER, + L"НАСТУПЛЕНИЕ ВРАГА", //STR_PB_ENEMYINVASION_HEADER, // 30 + L"ВРАЖЕСКАЯ ЗАСАДА", //STR_PB_ENEMYAMBUSH_HEADER + L"ВРАЖЕСКИЙ СЕКТОР", //STR_PB_ENTERINGENEMYSECTOR_HEADER + L"АТАКА ТВАРЕЙ", //STR_PB_CREATUREATTACK_HEADER + L"ЗАСАДА КОШЕК-УБИЙЦ", //STR_PB_BLOODCATAMBUSH_HEADER + L"ВХОД В ЛОГОВИЩЕ КОШЕК-УБИЙЦ", //STR_PB_ENTERINGBLOODCATLAIR_HEADER + + //Various single words for direct translation. The Civilians represent the civilian + //militia occupying the sector being attacked. Limited to 9-10 chars + + L"Локация", //надписи в красном окне + L"Враг", + L"Наемники", + L"Ополчение", + L"Рептионы", + L"Кошки-убийцы", + L"Сектор", + L"Нет", //If there are no uninvolved mercs in this fight. + L"Н/Д", //Acronym of Not Applicable + L"д", //One letter abbreviation of day + L"ч", //One letter abbreviation of hour + + //TACTICAL PLACEMENT USER INTERFACE STRINGS + //The four buttons + + L"Отмена", + L"Случайно", + L"Группой", + L"B aтaку!", + + //The help text for the four buttons. Use \n to denote new line (just like enter). + + L"Убирает все позиции бойцов \nи позволяет заново расставить их. (|C)", + L"При каждом нажатии распределяет \nбойцов случайным образом. (|S)", + L"Позволяет выбрать место, \nгде сгруппировать ваших бойцов. (|G)", + L"Нажмите эту кнопку, когда завершите \nвыбор позиций для бойцов. (|В|в|о|д)", + L"Вы должны разместить всех своих бойцов \nдо того, как начать бой.", + + //Various strings (translate word for word) + + L"Сектор", + L"Выбор точек входа", + + //Strings used for various popup message boxes. Can be as long as desired. + + L"Препятствие. Место недоступно. Попробуйте пройти другим путем.", + L"Поместите бойцов в незатененную часть карты.", + + //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"прибыл(а) в сектор", + + //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. + L"Автоматически просчитывает бой\nбез загрузки карты. (|A)", + L"Нельзя включить автобой\nво время нападения.", + L"Войти в сектор, чтобы атаковать врага. (|E)", + L"Отступить отрядом в предыдущий сектор. (|R)", //singular version + L"Всем отрядам отступить в предыдущий сектор. (|R)", //multiple groups with same previous sector +//!!!What about repeated "R" as hotkey? + //various popup messages for battle conditions. + + //%c%d is the sector -- ex: A9 + L"Враги атаковали ваших ополченцев в секторе %c%d.", + //%c%d сектор -- напр: A9 + L"Твари атаковали ваших ополченцев в секторе %c%d.", + //1st %d refers to the number of civilians eaten by monsters, %c%d is the sector -- ex: A9 + //Note: the minimum number of civilians eaten will be two. + L"Твари убили %d гражданских во время атаки сектора %s.", + //%s is the sector location -- ex: A9: Omerta + L"Враги атаковали ваших наемников в секторе %s. Ни один из ваших бойцов не в состоянии сражаться!", + //%s is the sector location -- ex: A9: Omerta + L"Твари атаковали ваших наемников в секторе %s. Ни один из ваших бойцов не в состоянии сражаться!", + +}; + +STR16 gpGameClockString[] = +{ + //This is the day represented in the game clock. Must be very short, 4 characters max. + L"День", +}; + +//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] = +{ + L"Находки сектора:", + L"Находки за день:", +}; + +//The headers used to describe various weapon statistics. + +CHAR16 gWeaponStatsDesc[][ 14 ] = +{ + L"Вес (%s):", + L"Состояние:", + L"Всего:", // Number of bullets left in a magazine + L"Дист:", // Range + L"Урон:", // Damage + L"ОД:", // abbreviation for Action Points + L"", + L"=", + L"=", + //Lal: additional strings for tooltips + L"Точность:", //9 + L"Дист:", //10 + L"Урон:", //11 + L"Вес:", //12 + L"Шок:",//13 //пр +}; + +//The headers used for the merc's money. + +CHAR16 gMoneyStatsDesc[][ 13 ] = +{ + L"Кол-во", //пр + L"Осталось:", //проверить this is the overall balance + L"Кол-во", //пр + L"Отделить:", //проверить the amount he wants to separate from the overall balance to get two piles of money + + L"Текущий", + L"Баланс", + L"Снимаемая", + L"Сумма", +}; + +//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. + +CHAR16 zHealthStr[][13] = +{ + L"УМИРАЕТ", // >= 0 + L"КРИТИЧЕН", // >= 15 + L"ПЛОХ", // >= 30 + L"РАНЕН", // >= 45 + L"ЗДОРОВ", // >= 60 + L"СИЛЕН", // >= 75 + L"ОТЛИЧНО", // >= 90 +}; + +STR16 gzMoneyAmounts[6] = +{ + L"1000$", + L"100$", + L"10$", + L"Снять", + L"Разделить", //пр + L"Взять" +}; + +// short words meaning "Advantages" for "Pros" and "Disadvantages" for "Cons." +CHAR16 gzProsLabel[10] = +{ + L"Плюсы:", //в описании ТТХ оружия +}; + +CHAR16 gzConsLabel[10] = +{ + L"Минусы:", //в описании ТТХ оружия +}; + +//Conversation options a player has when encountering an NPC +CHAR16 zTalkMenuStrings[6][ SMALL_STRING_LENGTH ] = +{ + L"Повторить", //meaning "Repeat yourself" + L"Дружественно", //approach in a friendly + L"Напрямую", //approach directly - let's get down to business + L"Угрожать", //approach threateningly - talk now, or I'll blow your face off + L"Дать", + L"Нанять" +}; + +//Some NPCs buy, sell or repair items. These different options are available for those NPCs as well. +CHAR16 zDealerStrings[4][ SMALL_STRING_LENGTH ]= +{ + L"Купить/Продать", + L"Купить", + L"Продать", + L"Ремонтировать", +}; + +CHAR16 zDialogActions[1][ SMALL_STRING_LENGTH ] = +{ + L"До встречи", //кнопка в диалоговом окне с мирным +}; + + +//These are vehicles in the game. + +STR16 pVehicleStrings[] = +{ + L"Эльдорадо", + L"Хаммер", // a hummer jeep/truck -- military vehicle + L"Фургон", + L"Джип", + L"Танк", + L"Вертолет", +}; + +STR16 pShortVehicleStrings[] = +{ + L"Эльдор", + L"Хаммер", // the HMVV + L"Фургон", + L"Джип", + L"Танк", + L"Верт.", // the helicopter +}; + +STR16 zVehicleName[] = +{ + L"Эльдорадо", + L"Хаммер", //a military jeep. This is a brand name. + L"Фургон", // Ice cream truck + L"Джип", + L"Танк", + L"Вертолет", //an abbreviation for Helicopter +}; + + +//These are messages Used in the Tactical Screen + +CHAR16 TacticalStr[][ MED_STRING_LENGTH ] = +{ + L"Воздушный Рейд", //пр + L"Оказать первую помощь?", + + // CAMFIELD NUKE THIS and add quote #66. + + L"%s замечает, что некоторые вещи отсутствуют в посылке.", //появляется когда мерк замечает кражу? + + // The %s is a string from pDoorTrapStrings + + L"Замок (%s).", //пр + L"Тут нет замка.", //пр + L"Успех!", //пр + L"Провал.", //пр + L"Успех!", //пр + L"Провал", //пр + L"На замке нет ловушки.", //пишет при действии 'искать ловушки' + L"Успех!", //пр + // The %s is a merc name + L"У %s нет подходящего ключа", //пр + L"Ловушка обезврежена", //пр + L"На замке не найдено ловушки.", //пишет при действии 'обезвредить' + L"Заперто", //пр + L"ДВЕРЬ", //пишет над дверью + L"С ЛОВУШКОЙ", //пишет над дверью + L"ЗАПЕРТАЯ", //пишет над дверью + L"НЕЗАПЕРТАЯ", //пишет над дверью + L"СЛОМАНАЯ", //пр + L"Тут есть кнопка. Нажать?", //к примеру кнопка в шкафу шиза + L"Разрядить ловушку?", //пр + L"Пред...", //пр + L"След...", //пр + L"Еще...", //пр + + // In the next 2 strings, %s is an item name + + L"%s помещен(а) на землю.", //пр + L"%s отдан(а) %s.", //пр + + // In the next 2 strings, %s is a name + + L"%s: Оплачено сполна.", //пр + L"%s: Еще должен %d.", //пр + L"Установить частоту радиодетонатора:", //in this case, frequency refers to a radio signal + L"Количество ходов до взрыва:", //how much time, in turns, until the bomb blows + L"Выберите частоту радиодетонатора на пульте:", //in this case, frequency refers to a radio signal + L"Обезвредить ловушку?", + L"Убрать синий флаг?", //пр + L"Поставить здесь синий флаг?", + L"Завершающий ход", //пр + + // In the next string, %s is a name. Stance refers to way they are standing. + + L"Вы действительно хотите атаковать %s?", + L"Увы, в машине боец не может изменить положение.", //пишет когда пытаешься наемником в машине на тактике присесть + L"Робот не может менять положение.", //пишет когда пытаешься присесть роботом + + // In the next 3 strings, %s is a name + + L"%s не может поменять положение здесь.", //пр + L"%s не может получить первую помощь.", //пр + L"%s не нуждается в медицинской помощи.", //пр + L"Туда идти нельзя.", //пр + L"У вас уже полная команда, мест нет.", //there's no room for a recruit on the player's team + + // In the next string, %s is a name + + L"%s нанят(а).", //к примеру, пишут когда Айру нанимаешь. + + // Here %s is a name and %d is a number + + L"%s должен получить $%d.", //пр + + // In the next string, %s is a name + + L"Сопроводить %s?", //пр + + // In the next string, the first %s is a name and the second %s is an amount of money (including $ sign) + + L"Нанять %s за %s в день?", //пр + + // This line is used repeatedly to ask player if they wish to participate in a boxing match. + + L"Хотите участвовать в поединке?", + + // In the next string, the first %s is an item name and the + // second %s is an amount of money (including $ sign) + + L"Купить %s за %s?", //пр + + // In the next string, %s is a name + + L"%s сопровождается отрядом %d.", //пр + + // These messages are displayed during play to alert the player to a particular situation + + L"ОТКАЗ", //ОТКАЗАЛО, ЗАКЛИНИЛО //weapon is jammed. + L"Роботу нужны патроны %s калибра.", //Robot is out of ammo + L"Бросить туда? Нет. Не выйдет.", //Merc can't throw to the destination he selected + + // These are different buttons that the player can turn on and off. + + L"Режим скрытности (|Z)", + L"Карта (|M)", + L"Завершить ход (|D)", + L"Говорить", + L"Молчать", + L"Подняться (|P|g|U|p)", + L"Смена уровня (|T|a|b)", + L"Забраться/Спрыгнуть", + L"Присесть/Лечь (|P|g|D|n)", + L"Осмотреть (|C|t|r|l)", + L"Предыдущий боец", + L"Следующий боец (|П|p|o|б|e|л)", + L"Настройки (|O)", + L"Режим очереди (|B)", + L"Смотреть/Повернуться (|L)", + L"Здоровье: %d/%d\nЭнергия: %d/%d\nМораль: %s", + L"Ну и?", //this means "what?" + L"Продолж.", //пр an abbrieviation for "Continued" + L"%s будет говорить.", + L"%s будет молчать.", + L"Состояние: %d/%d\nТопливо: %d/%d", + L"Выйти из машины", //пр + L"Сменить отряд (|S|h|i|f|t |П|p|о|б|e|л)", + L"Ехать", //пр + L"Н/Д", //this is an acronym for "Not Applicable." + L"Рукопашный бой", //может просто "Рукопашная"\Кулачный бой"? + L"Применить оружие", //вмнсто всех использовать можно "применить" - вроде тоже и короче. + L"Воспользоваться ножом", // + L"Использовать взрывчатку", // + L"Воспользоваться аптечкой", //может просто написать что-то вроде "лечить"\"Аптечка" + L"(Ловит)", + L"(Перезарядка)", //пр + L"(Дать)", //пишется под именем мирного, когда наводишь курсор с предметом + L"Сработала %s.", // The %s here is a string from pDoorTrapStrings ASSUME all traps are female gender + L"%s прибыл(а).", //к примеру, появляется при высадке в омерте + L"%s: истратил(а) все очки действия.", + L"%s сейчас не может действовать.", //пишет когда во время перехвата пытаешься выбрать наемника, который не перехватил ход + L"%s перевязан(а).", + L"%s: закончились бинты.", + L"Враг в секторе!", + L"Врагов в поле зрения нет.", //пишет когда врага не видишь и нажимаешь алт+ввод + L"Недостаточно очков действия.", + L"Оденьте на голову одного из наемников пульт управления роботом.", + L"Последняя очередь опустошила магазин!", + L"СОЛДАТ", //пр + L"РЕПТИОН", //пр + L"ОПОЛЧЕНЕЦ", //пишет как обращение при попытке лечить ополченца + L"ЖИТЕЛЬ", //пр + L"Выход из сектора", + L"ДА", + L"ОТМЕНА", + L"Выбранный боец", + L"Все бойцы отряда", + L"Идти в сектор", + L"Идти на карту", + L"Этот сектор отсюда покинуть нельзя.", //пр + L"%s слишком далеко.", //когда пытаешься выйти из сектора при перечеркнутом значке выхода + L"Скрыть кроны деревьев", + L"Показать кроны деревьев", + L"ВОРОНА", //Crow, as in the large black bird + L"ШЕЯ", + L"ГОЛОВА", + L"ТОРС", + L"НОГИ", + L"Рассказать Королеве то, что она хочет знать?", + L"Регистрация отпечатков пальцев пройдена.", + L"Неопознанные отпечатки пальцев. Оружие заблокировано.", + L"Цель захвачена", //пр + L"Путь заблокирован", //пр + L"Положить/Снять деньги", //подсказка джя значка $ на тактике Help text over the $ button on the Single Merc Panel + L"Никто не нуждается в медицинской помощи.", + L"отказ", // Short form of JAMMED, for small inv slots + L"Туда вскарабкаться невозможно.", // used ( now ) for when we click on a cliff + L"Путь блокирован. Хотите поменяться местами с этим человеком?", //пр + L"Человек отказывается двигаться.", //пр + // In the following message, '%s' would be replaced with a quantity of money (e.g. $200) + L"Вы согласны заплатить %s?", //пр + L"Принять бесплатное лечение?", //пр + L"Согласиться выйти замуж за Дэррела?", + L"Связка ключей", + L"С эскортируемыми этого сделать нельзя.", + L"Пощадить сержанта?", + L"За пределами прицельной дальности.", + L"Шахтер", //пр + L"Машина может ездить только между секторами.", + L"Ни у кого из наемников нет аптечки", //пр + L"Путь для %s заблокирован", + L"Ваши бойцы, захваченные армией Дейдраны, томятся здесь в плену!", + L"Замок поврежден.", + L"Замок разрушен.", + L"Кто-то с другой стороны пытается открыть эту дверь.", //пр + L"Состояние: %d/%d\nТопливо: %d/%d", + L"%s не видит %s.", // Cannot see person trying to talk to + L"Принадлежность отсоединена", //пр + L"Вы не можете содержать еще одну машину, довольствуйтесь уже имеющимися двумя.", +}; + +//Varying helptext explains (for the "Go to Sector/Map" checkbox) what will happen given different circumstances in the "exiting sector" interface. +STR16 pExitingSectorHelpText[] = +{ + //Helptext for the "Go to Sector" checkbox button, that explains what will happen when the box is checked. + L"Если выбрано, то карта соседнего сектора будет сразу же загружена.", + L"Если выбрано, то вы автоматически попадете на экран карты,\nтак как путешествие займет некоторое время.", + + //If you attempt to leave a sector when you have multiple squads in a hostile sector. + L"Этот сектор оккупирован врагом, и вы не можете выйти отсюда.\nВы должны разобраться с этим, прежде чем перейти в любой другой сектор.", + + //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"Как только оставшиеся наемники покинут этот сектор,\nсразу будет загружен соседний сектор.", + L"Выведя оставшихся наемников из этого сектора,\nвы автоматически попадете на экран карты,\nтак как на путешествие потребуется некоторое время.", + + //If an EPC is the selected merc, it won't allow the merc to leave alone as the merc is being escorted. The "single" button is disabled. + L"%s нуждается в сопровождении ваших наемников и не может в одиночку покинуть сектор.", + + //If only one conscious merc is left and is selected, and there are EPCs in the squad, the merc will be prohibited from leaving alone. + //There are several strings depending on the gender of the merc and how many EPCs are in the squad. + //DO NOT USE THE NEWLINE HERE AS IT IS USED FOR BOTH HELPTEXT AND SCREEN MESSAGES! + L"%s и %s не могут покинуть сектор поодиночке. Наемник сопровождает гражданского.", //male singular + L"%s и %s не могут покинуть сектор поодиночке. Наемник сопровождает гражданского.", //female singular + L"%s не может покинуть сектор в одиночку, так как он сопровождает группу из нескольких человек.", //male plural + L"%s не может покинуть сектор в одиночку, так как она сопровождает группу из нескольких человек.", //female plural + + //If one or more of your mercs in the selected squad aren't in range of the traversal area, then the "move all" option is disabled, + //and this helptext explains why. + L"Все ваши наемники должны быть в машине,\nчтобы отряд смог отправиться в место назначения.", + + L"", //UNUSED + + //Standard helptext for single movement. Explains what will happen (splitting the squad) + L"Если выбрать, то %s отправится в одиночку\nи автоматически будет переведен в отдельный отряд.", + + //Standard helptext for all movement. Explains what will happen (moving the squad) + L"Если выбрать, данный отряд отправится\nв место назначения, покинув этот сектор.", + + //This strings is used BEFORE the "exiting sector" interface is created. If you have an EPC selected and you attempt to tactically + //traverse the EPC while the escorting mercs aren't near enough (or dead, dying, or unconscious), this message will appear and the + //"exiting sector" interface will not appear. This is just like the situation where + //This string is special, as it is not used as helptext. Do not use the special newline character (\n) for this string. + L"%s сопровождается вашими наемниками и не может покинуть этот сектор в одиночку. Остальные наемники должны быть рядом, прежде чем вы сможете покинуть сектор.", +}; + + + +STR16 pRepairStrings[] = +{ + L"Предметы", // tell merc to repair items in inventory + L"База ПВО", // tell merc to repair SAM site - SAM is an acronym for Surface to Air Missile + L"Отмена", // cancel this menu + L"Робот", // repair the robot +}; + + +// NOTE: combine prestatbuildstring with statgain to get a line like the example below. +// "John has gained 3 points of marksmanship skill." + +STR16 sPreStatBuildString[] = +{ + L"теряет", // the merc has lost a statistic + L"получает", // the merc has gained a statistic + L"единицу", // singular + L"единиц", // plural + L"уровень", // singular + L"уровня", // plural +}; + +STR16 sStatGainStrings[] = +{ + L"здоровья.", + L"проворности.", + L"ловкости.", + L"интеллекта.", + L"медицины.", + L"взрывного дела.", + L"механики.", + L"меткости.", + L"опыта.", + L"силы.", + L"лидерства.", +}; + + +STR16 pHelicopterEtaStrings[] = +{ + L"Общая дистанция:", // total distance for helicopter to travel + L"Безопасно: ", // distance to travel to destination + L"Опасно:", // distance to return from destination to airport + L"Итого:", // total cost of trip by helicopter + L"ОВП:", // ETA is an acronym for "estimated time of arrival" + L"У вертолета закончилось топливо. Придется совершить посадку на вражеской территории!", // warning that the sector the helicopter is going to use for refueling is under enemy control -> + L"Пассажиры:", + L"Выбрать вертолет или точку высадки?", + L"Вертолет", + L"Высадка", +}; + +STR16 sMapLevelString[] = +{ + L"Подуровень:", // what level below the ground is the player viewing in mapscreen +}; + +STR16 gsLoyalString[] = +{ + L"Лояльность", // the loyalty rating of a town ie : Loyal 53% +}; + + +// error message for when player is trying to give a merc a travel order while he's underground. + +STR16 gsUndergroundString[] = +{ + L"не может выйти на марш в подземельях.", +}; + +STR16 gsTimeStrings[] = +{ + L"ч", // hours abbreviation + L"м", // minutes abbreviation + L"с", // seconds abbreviation + L"д", // days abbreviation +}; + +// text for the various facilities in the sector + +STR16 sFacilitiesStrings[] = +{ + L"Нет", //важные объекты сектора + L"Госпиталь", + L"Фабрика", + L"Тюрьма", + L"Военная база", + L"Аэропорт", + L"Стрельбище", // a field for soldiers to practise their shooting skills +}; + +// text for inventory pop up button + +STR16 pMapPopUpInventoryText[] = +{ + L"Инвентарь", + L"Выйти", +}; + +// town strings + +STR16 pwTownInfoStrings[] = +{ + L"Размер", // 0 // size of the town in sectors + L"", // blank line, required + L"Контроль", // how much of town is controlled + L"Нет", // none of this town + L"Шахта города", // mine associated with this town + L"Лояльность", // 5 // the loyalty level of this town + L"Готовы", // the forces in the town trained by the player + L"", + L"Важные объекты", // main facilities in this town + L"Уровень", // the training level of civilians in this town + L"Тренировка ополчения", // 10 // state of civilian training in town + L"Ополчение", // the state of the trained civilians in the town +}; + +// Mine strings + +STR16 pwMineStrings[] = +{ + L"Шахта", // 0 + L"Серебро", + L"Золото", + L"Дневная выработка", + L"Производственные возможности", + L"Заброшена", // 5 + L"Закрыта", + L"Истощается", + L"Идет добыча", + L"Статус", + L"Уровень добычи", + L"Тип руды", // 10 + L"Принадлежность", + L"Лояльность", +// L"Работ.шахтеры", +}; + +// blank sector strings + +STR16 pwMiscSectorStrings[] = +{ + L"Вражеские силы", + L"Сектор", + L"Количество предметов", + L"Неизвестно", + L"Под контролем", + L"Да", + L"Нет", +}; + +// error strings for inventory + +STR16 pMapInventoryErrorString[] = +{ + L"%s стоит слишком далеко.", //Merc is in sector with item but not close enough + L"Нельзя выбрать этого бойца.", //MARK CARTER + L"%s вне этого сектора, и не может подобрать предмет.", + L"Во время боя вам придется подбирать вещи вручную.", //*перефразировать, показывается когда пытаешься со стратегич карты в инвентаре сектора взять предмет + L"Во время боя вам придется выкладывать вещи вручную.", + L"%s вне этого сектора, и не может оставить предмет.", + L"Во время битвы вы не можете заряжать оружие патронами из короба.", +}; + +STR16 pMapInventoryStrings[] = +{ + L"Локация", // sector these items are in + L"Всего предметов", // total number of items in sector +}; + + +// help text for the user + +STR16 pMapScreenFastHelpTextList[] = +{ + L"Чтобы перевести наемника в другой отряд, назначить его врачом или отдать приказ ремонтировать вещи, щелкните по колонке 'ЗАНЯТИЕ'.", + L"Чтобы приказать наемнику перейти в другой сектор, щелкните в колонке 'КУДА'.", + L"Как только наемник получит приказ на передвижение, включится сжатие времени.", + L"Нажатием левой кнопки мыши выбирается сектор. Еще одно нажатие нужно, чтобы отдать наемникам приказы на передвижение. Нажатие правой кнопки мыши на секторе откроет экран дополнительной информации.", + L"Чтобы вызвать экран помощи - в любой момент времени нажмите 'h'.", + L"Тестовый текст", + L"Тестовый текст", + L"Тестовый текст", + L"Тестовый текст", + L"Вы практически ничего не сможете сделать на этом экране, пока не прибудете в Арулько. Когда познакомитесь со своей командой, включите сжатие времени (кнопки в правом нижнем углу). Это ускорит течение времени, пока ваша команда не прибудет в Арулько.", +}; + +// movement menu text + +STR16 pMovementMenuStrings[] = +{ + L"Отправить наемников в сектор", // title for movement box + L"Путь", //пр done with movement menu, start plotting movement + L"Отмена", //пр cancel this menu + L"Другое", //пр title for group of mercs not on squads nor in vehicles +}; + + +STR16 pUpdateMercStrings[] = +{ + L"Ой!:", // an error has occured + L"Срок контракта истек:", // this pop up came up due to a merc contract ending + L"Задание выполнили:", // this pop up....due to more than one merc finishing assignments + L"Бойцы вернулись к своим обязанностям:", // this pop up ....due to more than one merc waking up and returing to work + L"Бойцы ложатся спать:", // this pop up ....due to more than one merc being tired and going to sleep + L"Скоро закончатся контракты у:", // this pop up came up due to a merc contract ending +}; + +// map screen map border buttons help text + +STR16 pMapScreenBorderButtonHelpText[] = +{ + L"Населенные пункты (|W)", + L"Шахты (|M)", + L"Отряды и враги (|T)", + L"Карта воздушного пространства (|A)", + L"Показать вещи (|I)", + L"Ополчение и враги (|Z)", +}; + + +STR16 pMapScreenBottomFastHelp[] = +{ + L"Ноутбук (|L)", + L"Тактический экран (|E|s|c)", + L"Настройки (|O)", + L"Сжатие времени (|+)", // time compress more + L"Сжатие времени (|-)", // time compress less + L"Предыдущее сообщение (|С|т|р|е|л|к|а |в|в|е|р|х)\nПредыдущая страница (|P|g|U|p)", // previous message in scrollable list + L"Следующее сообщение (|С|т|р|е|л|к|а |в|н|и|з)\nСледующая страница (|P|g|D|n)", // next message in the scrollable list + L"Включить / выключить\nсжатие времени (|П|р|о|б|е|л)", // start/stop time compression +}; + +STR16 pMapScreenBottomText[] = +{ + L"Текущий баланс", // current balance in player bank account +}; + +STR16 pMercDeadString[] = +{ + L"%s мертв(а)", +}; + + +STR16 pDayStrings[] = +{ + L"День", +}; + +// the list of email sender names + +STR16 pSenderNameList[] = +{ + L"Энрико", + L"Psych Pro Inc.", + L"Помощь", + L"Psych Pro Inc.", + L"Спек", + L"R.I.S.", //5 + L"Барри", + L"Блад", + L"Рысь", + L"Гризли", + L"Вики", //10 + L"Тревор", + L"Хряп", + L"Иван", + L"Анаболик", + L"Игорь", //15 + L"Тень", + L"Рыжий", + L"Жнец (Потрошитель)", + L"Фидель", + L"Лиска", //20 + L"Сидней", + L"Гас", + L"Сдоба", + L"Айс", + L"Паук", //25 + L"Скала (Клифф)", + L"Бык", + L"Стрелок", + L"Тоска", + L"Рейдер", //30 + L"Сова", + L"Статик", + L"Лен", + L"Дэнни", + L"Маг", + L"Стефан", + L"Лысый", + L"Злобный", + L"Доктор Кью", + L"Гвоздь", + L"Тор", + L"Стрелка", + L"Волк", + L"ЭмДи", + L"Лава", + //---------- + L"M.I.S. Страховка", + L"Бобби Рэй", + L"Босс", + L"Джон Кульба", + L"А.I.М.", +}; + + +// next/prev strings + +STR16 pTraverseStrings[] = +{ + L"<<", + L">>", +}; + +// new mail notify string + +STR16 pNewMailStrings[] = +{ + L"Получена новая почта...", +}; + + +// confirm player's intent to delete messages + +STR16 pDeleteMailStrings[] = +{ + L"Удалить письмо?", + L"Удалить, НЕ ПРОЧИТАВ?", +}; + + +// the sort header strings + +STR16 pEmailHeaders[] = +{ + L"От:", + L"Тема:", + L"День:", +}; + +// email titlebar text + +STR16 pEmailTitleText[] = +{ + L"Почтовый ящик", +}; + + +// the financial screen strings +STR16 pFinanceTitle[] = +{ + L"Финансовый отчет", //the name we made up for the financial program in the game +}; + +STR16 pFinanceSummary[] = +{ + L"Доход:", // credit (subtract from) to player's account + L"Расход:", // debit (add to) to player's account + L"Вчерашний чистый доход:", + L"Вчерашние другие поступления:", + L"Вчерашний расход:", + L"Баланс на конец дня:", + L"Чистый доход сегодня:", + L"Другие поступления за сегодня:", + L"Расход за сегодня:", + L"Текущий баланс:", + L"Ожидаемый доход:", + L"Ожидаемый баланс:", // projected balance for player for tommorow +}; + + +// headers to each list in financial screen + +STR16 pFinanceHeaders[] = +{ + L"День", //пр the day column + L"Доход", // the credits column + L"Расход", // the debits column + L"Операции", // transaction type - see TransactionText below + L"Баланс", // balance at this point in time + L"Стр.", // page number + L"Дней", // the day(s) of transactions this page displays +}; + + +STR16 pTransactionText[] = +{ + L"Начисленный процент", // interest the player has accumulated so far + L"Анонимный взнос", + L"Перевод средств", + L"Нанят", // Merc was hired + L"Покупки у Бобби Рэя", // Bobby Ray is the name of an arms dealer + L"Оплата счета M.E.R.C.", + L"%s: страховка.", // medical deposit for merc + L"I.M.P. анализ профиля", // IMP is the acronym for International Mercenary Profiling + L"%s: куплена страховка.", + L"%s: Страховка уменьшена", + L"%s: Продление страховки", // johnny contract extended + L"для %s: Страховка аннулирована", + L"%s: Требуется страховка", // insurance claim for merc + L"1 день", // merc's contract extended for a day + L"7 дней", // merc's contract extended for a week + L"14 дней", // ... for 2 weeks + L"Доход шахты", + L"", //String nuked + L"Куплены цветы", + L"%s: Возврат мед. депозита", + L"%s: Остаток мед. депозита", + L"%s: Мед. депозит удержан", + L"%s: оплата услуг.", // %s is the name of the npc being paid + L"%s берет наличные.", // transfer funds to a merc + L"%s: переводит деньги.", // transfer funds from a merc + L"%s: оружие ополчению.", // initial cost to equip a town's militia + L"%s продал вам вещи.", //is used for the Shop keeper interface. The dealers name will be appended to the end of the string. + L"%s кладет наличные на счет.", + L"Снаряжение продано населению", //пишет при продаже вещей из инвентаря сектора (алт+клик) +}; + +STR16 pTransactionAlternateText[] = +{ + L"Страховка для", // insurance for a merc + L"%s: контракт продлен на 1 день.", // entend mercs contract by a day + L"%s: контракт продлен на 7 дней.", + L"%s: контракт продлен на 14 дней.", +}; + +// helicopter pilot payment + +STR16 pSkyriderText[] = +{ + L"Небесному Всаднику заплачено $%d", // skyrider was paid an amount of money + L"Вы все еще должны Небесному Всаднику $%d.", // skyrider is still owed an amount of money + L"Небесный Всадник завершил заправку.", // skyrider has finished refueling + L"",//unused + L"",//unused + L"Небесный Всадник готов к полету.", // Skyrider was grounded but has been freed + L"У Небесного Всадника нет пассажиров. Если вы хотите переправить бойцов в этот сектор, посадите их в вертолет (приказ 'Машина/Вертолет')." +}; + + +// strings for different levels of merc morale + +STR16 pMoralStrings[] = +{ + L"Отлично", + L"Хорошо", + L"Норма", + L"Низкая", + L"Паника", + L"Ужас", +}; + +// Mercs equipment has now arrived and is now available in Omerta or Drassen. + +STR16 pLeftEquipmentString[] = +{ + L"%s оставляет свою экипировку в Омерте (A9).", //%s может взять заказанную экипировку в Омерте (A9). + L"%s оставляет свою экипировку в Драссене (B13).", //%s может взять заказанную экипировку в Драссене (B13). +}; + +// Status that appears on the Map Screen + +STR16 pMapScreenStatusStrings[] = +{ + L"Здоровье", + L"Энергия", + L"Мораль", + L"Состояние", // the condition of the current vehicle (its "health") + L"Бензин", // the fuel level of the current vehicle (its "energy") +}; + + +STR16 pMapScreenPrevNextCharButtonHelpText[] = +{ + L"Предыдущий наемник\n(|С|т|р|е|л|к|а |В|л|е|в|о)", // previous merc in the list + L"Следующий наемник\n(|С|т|р|е|л|к|а |В|п|р|а|в|о)", // next merc in the list +}; + + +STR16 pEtaString[] = +{ + L"РВП:", // eta is an acronym for Estimated Time of Arrival +}; + +STR16 pTrashItemText[] = +{ + L"Вы больше никогда не увидите этот предмет. Уверены?", // do you want to continue and lose the item forever + L"Этот предмет кажется ОЧЕНЬ важным. Вы ДЕЙСТВИТЕЛЬНО хотите выкинуть его?", // does the user REALLY want to trash this item +}; + + +STR16 pMapErrorString[] = +{ + L"Отряд не может выйти на марш, когда один из наемников спит.", + +//1-5 + L"Сначала выведите отряд на поверхность.", + L"Выйти на марш? Да тут же враги повсюду!", + L"Чтобы выйти на марш, наемники должны быть назначены в отряд или посажены в машину.", + L"У вас еще нет ни одного бойца.", // you have no members, can't do anything + L"Наемник не может выполнить.", // merc can't comply with your order +//6-10 + L"нуждается в сопровождении чтобы идти. Назначьте его с кем-нибудь в отряд.", // merc can't move unescorted .. for a male + L"нуждается в сопровождении чтобы идти. Назначьте ее с кем-нибудь в отряд.", // for a female + L"Наемник еще не прибыл в Арулько!", + L"Кажется, сначала надо уладить проблемы с контрактом.", + L"Бежать от самолета? Только после вас!", //пр Cannot give a movement order. Air raid is going on. +//11-15 + L"Выступить на марш? Да у нас тут бой идет!", + L"Вы попали в засаду кошек-убийц в секторе %s!", + L"Вы только что попали в логово кошек-убийц, сектор I16!", + L"", + L"База ПВО в %s была захвачена.", +//16-20 + L"Шахта в %s была захвачена врагом. Ваш дневной доход сократился до %s в день.", + L"Враг занял без сопротивления сектор %s.", + L"Как минимум один из ваших бойцов не может выполнить этот приказ.", + L"%s не может присоединиться к %s - нет места.", + L"%s не может присоединиться к %s - слишком большое расстояние.", +//21-25 + L"Шахта в %s была захвачена войсками Дейдраны!", + L"Войска Дейдраны только что вторглись на базу ПВО в %s.", + L"Войска Дейдраны только что вторглись в %s.", + L"Войска Дейдраны были замечены в %s.", + L"Войска Дейдраны только что захватили %s.", +//26-30 + L"Как минимум один из ваших бойцов не хочет спать.", + L"Как минимум один из ваших бойцов не может проснуться.", + L"Ополченцы не появятся, пока не завершат тренировку.", + L"%s сейчас не в состоянии принять приказ о перемещении.", + L"Ополченцы вне границ города не могут перейти в другой сектор.", +//31-35 + L"Вы не можете держать ополченцев в %s.", + L"Пустая машина не может двигаться!", + L"%s из-за тяжелых ранений не может идти!", + L"Сначала вам нужно покинуть музей!", + L"%s мертв(а)!", +//36-40 + L"%s не может переключиться на %s, так как находится в движении.", + L"%s не может сесть в машину с этой стороны.", + L"%s не может вступить в %s", + L"Вы не можете включить сжатие времени, пока не наймете новых бойцов!", + L"Эта машина может двигаться только по дорогам!", +//41-45 + L"Вы не можете переназначить наемников на марше.", + L"У машины закончился бензин!", + L"%s еле волочит ноги и идти не может.", + L"Ни один из пассажиров не в состоянии вести машину.", + L"Один или несколько наемников из этого отряда не могут сейчас двигаться.", +//46-50 + L"Один или несколько наемников не могут сейчас двигаться.", + L"Машина сильно повреждена!", + L"Внимание! Тренировать ополченцев в одном секторе могут не более двух наемников.", + L"Роботом обязательно нужно управлять. Назначьте наемника с пультом и робота в один отряд.", +}; + + +// help text used during strategic route plotting +STR16 pMapPlotStrings[] = +{ + L"Еще раз щелкните по точке назначения, чтобы подтвердить путь или щелкните по другому сектору, чтобы установить больше путевых точек.", + L"Путь движения подтвержден.", + L"Точка назначения не изменена.", + L"Путь движения отменен.", + L"Путь сокращен.", +}; + + +// help text used when moving the merc arrival sector +STR16 pBullseyeStrings[] = +{ + L"Выберите сектор, в который прибудут наемники.", + L"Вновь прибывшие наемники высадятся в %s.", + L"Высадить здесь наемников нельзя. Воздушное пространство не безопасно!", + L"Отменено. Сектор прибытия не изменился.", + L"Небо над %s более не безопасно! Место высадки было перемещено в %s.", +}; + + +// help text for mouse regions + +STR16 pMiscMapScreenMouseRegionHelpText[] = +{ + L"Открыть инвентарь (|В|в|о|д)", + L"Выкинуть предмет", + L"Закрыть инвентарь (|В|в|о|д)", +}; + + + +// male version of where equipment is left +STR16 pMercHeLeaveString[] = +{ + L"Должен ли %s оставить свою амуницию здесь (в %s) или позже в Драссене (B13) перед отлетом?", + L"Должен ли %s оставить свою амуницию здесь (в %s) или позже в Омерте (A9) перед отлетом?", + L"скоро уходит и оставит свою амуницию в Омерте (А9).", + L"скоро уходит и оставит свою амуницию в Драссене (B13).", + L"%s скоро уходит и оставит свою амуницию в %s.", +}; + + +// female version +STR16 pMercSheLeaveString[] = +{ + L"Должна ли %s оставить свою амуницию здесь (в %s) или позже в Драссене (B13) перед отлетом?", + L"Должна ли %s оставить свою амуницию здесь (в %s) или позже в Омерте (A9) перед отлетом?", + L"скоро уходит и оставит свою амуницию в Омерте (А9).", + L"скоро уходит и оставит свою амуницию в Драссене (B13).", + L"%s скоро уходит и оставит свою амуницию в %s.", +}; + + +STR16 pMercContractOverStrings[] = +{ + L"отправляется домой, так как его контракт завершен.", // merc's contract is over and has departed + L"отправляется домой, так как ее контракт завершен.", // merc's contract is over and has departed + L"уходит, так как его контракт был прерван.", // merc's contract has been terminated + L"уходит, так как ее контракт был прерван.", // merc's contract has been terminated + L"Вы должны M.E.R.C. слишком много денег, так что %s уходит.", // Your M.E.R.C. account is invalid so merc left +}; + +// Text used on IMP Web Pages + +STR16 pImpPopUpStrings[] = +{ + L"Неверный код доступа.", + L"Это приведет к потере уже полученных результатов тестирования. Вы уверены?", + L"Введите правильное имя и укажите пол.", + L"Предварительный анализ вашего счета показывает, что вы не можете позволить себе пройти тестирование.", + L"Сейчас вы не можете выбрать этот пункт.", + L"Чтобы закончить анализ, нужно иметь место еще хотя бы для одного члена команды.", + L"Профиль уже создан.", + L"Не могу загрузить I.M.P.-персонаж с диска.", //пр + L"Вы достигли максимального количества I.M.P.-персонажей.", //пр + L"У вас в команде уже есть три I.M.P.-персонажа того же пола.", //пр + L"Вы не можете позволить себе такой I.M.P.-персонаж.", //пр + L"Новый I.M.P.-персонаж присоединился к команде.", //пр +}; + + +// button labels used on the IMP site + +STR16 pImpButtonText[] = +{ + L"Информация о нас", // about the IMP site + L"НАЧАТЬ", // begin profiling + L"Способности", // personality section + L"Характеристики", // personal stats/attributes section + L"Портрет", // the personal portrait selection + L"Голос: %d", // the voice selection + L"Готово", // done profiling + L"Начать сначала", // start over profiling + L"Да, я выбираю отмеченный ответ.", + L"Да", + L"Нет", + L"Готово", // finished answering questions + L"Назад", // previous question..abbreviated form + L"Дальше", // next question + L"ДА.", // yes, I am certain + L"НЕТ, Я ХОЧУ НАЧАТЬ СНОВА.", // no, I want to start over the profiling process + L"ДА", + L"НЕТ", + L"Назад", // back one page + L"Отменить", // cancel selection + L"Да, все верно.", + L"Нет, еще раз взгляну.", + L"Регистрация", // the IMP site registry..when name and gender is selected + L"Анализ данных", // analyzing your profile results + L"Готово", + L"Голос", +}; + +STR16 pExtraIMPStrings[] = +{ + L"Чтобы создать профиль, укажите свои личные данные.", + L"Завершив формирование личности, укажите свои способности и умения.", + L"Способности героя заданы. Теперь вы можете выбрать портрет.", + L"Чтобы завершить процесс, выберите голос, который вам подходит." +}; + +STR16 pFilesTitle[] = +{ + L"Просмотр данных", +}; + +STR16 pFilesSenderList[] = +{ + L"Отчет разведки", // the recon report sent to the player. Recon is an abbreviation for reconissance + L"В розыске #1", // first intercept file .. Intercept is the title of the organization sending the file...similar in function to INTERPOL/CIA/KGB..refer to fist record in files.txt for the translated title + L"В розыске #2", // second intercept file + L"В розыске #3", // third intercept file + L"В розыске #4", // fourth intercept file + L"В розыске #5", // fifth intercept file + L"В розыске #6", // sixth intercept file +}; + +// Text having to do with the History Log + +STR16 pHistoryTitle[] = +{ + L"Журнал событий", +}; + +STR16 pHistoryHeaders[] = +{ + L"День", // the day the history event occurred + L"Стр.", // the current page in the history report we are in + L"День", // the days the history report occurs over + L"Локация", // location (in sector) the event occurred + L"Событие", // the event label +}; + +// various history events +// THESE STRINGS ARE "HISTORY LOG" STRINGS AND THEIR LENGTH IS VERY LIMITED. +// PLEASE BE MINDFUL OF THE LENGTH OF THESE STRINGS. ONE WAY TO "TEST" THIS +// IS TO TURN "CHEAT MODE" ON AND USE CONTROL-R IN THE TACTICAL SCREEN, THEN +// GO INTO THE LAPTOP/HISTORY LOG AND CHECK OUT THE STRINGS. CONTROL-R INSERTS +// MANY (NOT ALL) OF THE STRINGS IN THE FOLLOWING LIST INTO THE GAME. +STR16 pHistoryStrings[] = +{ + L"", // leave this line blank + //1-5 + L"Нанят(а) %s из A.I.M.", // merc was hired from the aim site + L"Нанят(а) %s из M.E.R.C.", // merc was hired from the aim site + L"%s мертв(а).", // merc was killed + L"Оплачены услуги M.E.R.C.", // paid outstanding bills at MERC + L"Принято задание от Энрико Чивалдори", + //6-10 + L"Воспользовались услугами I.M.P.", + L"Оформлена страховка для %s.", // insurance contract purchased + L"%s: cтраховой контракт аннулирован.", // insurance contract canceled + L"Выплата страховки %s.", // insurance claim payout for merc + L"%s: контракт продлен на 1 день.", // Extented "mercs name"'s for a day + //11-15 + L"%s: контракт продлен на 7 дней.", // Extented "mercs name"'s for a week + L"%s: контракт продлен на 14 дней.", // Extented "mercs name"'s 2 weeks + L"Вы уволили %s.", // "merc's name" was dismissed. + L"%s уходит от вас.", // "merc's name" quit. + L"получено задание.", // a particular quest started + //16-20 + L"задание выполнено.", + L"Поговорили со старшим горняком города %s", // talked to head miner of town + L"%s освобожден(а).", + L"Включен режим чит-кодов", + L"Провизия будет доставлена в Омерту завтра.", + //21-25 + L"%s ушла, чтобы выйти замуж за Дерила Хика.", + L"Истек контракт у %s.", + L"Нанят(а) %s.", + L"Энрико сетует на отсутствие успехов в кампании.", + L"Победа в сражении!", + //26-30 + L"В шахте %s иссякает запас руды.", + L"Шахта %s истощилась.", + L"Шахта %s закрыта.", + L"Шахта %s снова работает.", + L"Получена информация о тюрьме Тикса.", + //31-35 + L"Узнали об Орте - секретном военном заводе.", + L"Ученый из Орты подарил вам ракетные винтовки.", + L"Королева Дейдрана нашла применение трупам.", + L"Фрэнк говорил что-то о боях в Сан-Моне.", + L"Пациенту кажется, что он что-то видел в шахтах.", + //36-40 + L"Встретили Дэвина - торговца взрывчаткой.", + L"Пересеклись с бывшим наемником A.I.M., Майком!", + L"Встретили Тони, торговца оружием.", + L"Получена ракетная винтовка от сержанта Кротта.", + L"Документы на магазин Энджела переданы Кайлу.", + //41-45 + L"Шиз предлагает построить робота.", //может, собрать робота? + L"Болтун может сделать варево, обманывающее жуков.", + L"Кит отошел от дел.", + L"Говард поставлял цианиды Дейдране.", + L"Встретили торговца Кита из Камбрии.", + //46-50 + L"Встретили Говарда, фармацевта из Балайма.", + L"Встретили Перко. Он держит небольшую мастерскую.", + L"Встретили Сэма из Балайма. Он торгует железками.", + L"Франц разбирается в электронике и других вещах.", + L"Арнольд держит мастерскую в Граме.", + //51-55 + L"Фредо из Грама чинит электронику.", + L"Один богатей из Балайма дал вам денег.", + L"Встретили старьевщика Джейка.", + L"Один бродяга дал нам электронную карточку.", + L"Вальтер подкуплен, он откроет дверь в подвал.", + //56-60 + L"Дэйв заправит машину бесплатно, если будет бензин.", + L"Дали взятку Пабло.", + L"Босс держит деньги в шахте Сан-Моны.", + L"%s: победа в бое без правил.", + L"%s: проигрыш в бое без правил.", + //61-65 + L"%s: дисквалификация в бое без правил.", //дисквалификация из боя? + L"В заброшенной шахте найдена куча денег.", + L"Встречен убийца, посланный Боссом.", + L"Потерян контроль над сектором", //ENEMY_INVASION_CODE + L"Отбита атака врага", + //66-70 + L"Сражение проиграно", //ENEMY_ENCOUNTER_CODE + L"Смертельная засада", //ENEMY_AMBUSH_CODE + L"Вырвались из засады", + L"Атака провалилась!", //ENTERING_ENEMY_SECTOR_CODE + L"Успешная атака!", + //71-75 + L"Атака тварей", //CREATURE_ATTACK_CODE + L"Кошки-убийцы уничтожили ваш отряд.", //BLOODCAT_AMBUSH_CODE + L"Все кошки-убийцы убиты", + L"%s был убит(а).", + L"Отдали Кармену голову террориста.", + L"Убийца ушел.", + L"%s убит(а) вашим отрядом.", +}; + +STR16 pHistoryLocations[] = +{ + L"Н/Д", // N/A is an acronym for Not Applicable +}; + +// icon text strings that appear on the laptop + +STR16 pLaptopIcons[] = +{ + L"Почта", + L"Сайты", + L"Финансы", + L"Команда", + L"Журнал", + L"Данные", + L"Выключить", + L"sir-FER 4.0", // our play on the company name (Sirtech) and web surFER +}; + +// bookmarks for different websites +// IMPORTANT make sure you move down the Cancel string as bookmarks are being added + +STR16 pBookMarkStrings[] = +{ + L"А.I.M.", + L"Бобби Рэй", + L"I.M.P.", + L"М.Е.R.С.", + L"Похороны", + L"Цветы", + L"Страховка", + L"Отмена", +}; + +STR16 pBookmarkTitle[] = +{ + L"Закладки", + L"Позже это меню можно вызвать правым щелчком мыши.", +}; + +// When loading or download a web page + +STR16 pDownloadString[] = +{ + L"Загрузка", + L"Обновление", +}; + +//This is the text used on the bank machines, here called ATMs for Automatic Teller Machine + +STR16 gsAtmSideButtonText[] = +{ + L"OK", //пр + L"Взять", // take money from merc + L"Дать", // give money to merc + L"Отмена", //пр cancel transaction + L"Очист.", //пр clear amount being displayed on the screen +}; + +STR16 gsAtmStartButtonText[] = +{ + L"Перевести $", // transfer money to merc -- short form + L"Параметры", // view stats of the merc + L"Инвентарь", // view the inventory of the merc + L"Контракт", +}; + +STR16 sATMText[ ]= +{ + L"Перевести средства?", // transfer funds to merc? + L"Уверены?", //пр are we certain? + L"Ввести сумму", // enter the amount you want to transfer to merc + L"Выбрать тип", // select the type of transfer to merc + L"Не хватает денег", // not enough money to transfer to merc + L"Сумма должна быть кратна $10", // transfer amount must be a multiple of $10 +}; + +// Web error messages. Please use German equivilant for these messages. +// DNS is the acronym for Domain Name Server +// URL is the acronym for Uniform Resource Locator + +STR16 pErrorStrings[] = +{ + L"Ошибка", + L"Сервер не зарегистрирован в DNS.", + L"Проверьте адрес и попробуйте еще раз.", + L"OK", //пр //Превышено время ожидания ответа сервера. + L"Обрыв соединения с сервером.", +}; + + +STR16 pPersonnelString[] = +{ + L"Бойцов:", // mercs we have +}; + + +STR16 pWebTitle[ ]= +{ + L"sir-FER 4.0", // our name for the version of the browser, play on company name +}; + + +// The titles for the web program title bar, for each page loaded + +STR16 pWebPagesTitles[] = +{ + L"А.I.M.", + L"A.I.M. Состав", + L"A.I.M. Портреты", // a mug shot is another name for a portrait + L"A.I.M. Сортировка", + L"A.I.M.", + L"A.I.M. Галерея", //$$ + L"A.I.M. Правила", + L"A.I.M. История", + L"A.I.M. Ссылки", + L"M.E.R.C.", + L"M.E.R.C. Счета", + L"M.E.R.C. Регистрация", + L"M.E.R.C. Оглавление", + L"Бобби Рэй", + L"Бобби Рэй - оружие", + L"Бобби Рэй - боеприпасы", + L"Бобби Рэй - броня", + L"Бобби Рэй - разное", //misc is an abbreviation for miscellaneous + L"Бобби Рэй - вещи б/у.", + L"Бобби Рэй - почтовый заказ", + L"I.M.P.", + L"I.M.P.", + L"\"Цветы по всему миру\"", + L"\"Цветы по всему миру\" - галерея", + L"\"Цветы по всему миру\" - бланк заказа", + L"\"Цветы по всему миру\" - открытки", + L"Страховые агенты: Малеус, Инкус и Стэйпс", + L"Информация", + L"Контракт", //пр + L"Комментарии", + L"Похоронная служба Макгилликатти", + L"", + L"Адрес не найден.", + L"Бобби Рэй - последние поступления",//@@@3 Translate new text + L"", + L"", +}; + +STR16 pShowBookmarkString[] = +{ + L"Подсказка", + L"Щелкните еще раз по кнопке \"Сайты\" для отображения меню сайтов.", +}; + +STR16 pLaptopTitles[] = +{ + L"Почтовый ящик", + L"Просмотр данных", + L"Персонал", //пр + L"Финансовый отчет", + L"Журнал", //пр +}; + +STR16 pPersonnelDepartedStateStrings[] = +{ + //reasons why a merc has left. + L"Погиб в бою", + L"Уволен", + L"Другое", + L"Замужем", + L"Контракт истек", + L"Выход", +}; +// personnel strings appearing in the Personnel Manager on the laptop + +STR16 pPersonelTeamStrings[] = +{ + L"В команде", + L"Выбывшие", + L"Гонорар за день:", + L"Высший гонорар:", + L"Низший гонорар:", + L"Погибло в боях:", + L"Уволено:", + L"Другое:", +}; + + +STR16 pPersonnelCurrentTeamStatsStrings[] = +{ + L"Худший", + L"Среднее", + L"Лучший", +}; + + +STR16 pPersonnelTeamStatsStrings[] = +{ + L"ЗДР", + L"ПРВ", + L"ЛОВ", + L"СИЛ", + L"ЛИД", + L"ИНТ", + L"ОПТ", + L"МЕТ", + L"МЕХ", + L"ВЗР", + L"МЕД", +}; + + +// horizontal and vertical indices on the map screen + +STR16 pMapVertIndex[] = +{ + L"X", + L"A", + L"B", + L"C", + L"D", + L"E", + L"F", + L"G", + L"H", + L"I", + L"J", + L"K", + L"L", + L"M", + L"N", + L"O", + L"P", +}; + +STR16 pMapHortIndex[] = +{ + L"X", + L"1", + L"2", + L"3", + L"4", + L"5", + L"6", + L"7", + L"8", + L"9", + L"10", + L"11", + L"12", + L"13", + L"14", + L"15", + L"16", +}; + +STR16 pMapDepthIndex[] = +{ + L"", + L"-1", + L"-2", + L"-3", +}; + +// text that appears on the contract button + +STR16 pContractButtonString[] = +{ + L"Контракт", +}; + +// text that appears on the update panel buttons + +STR16 pUpdatePanelButtons[] = +{ + L"Далее", + L"Стоп", +}; + +// Text which appears when everyone on your team is incapacitated and incapable of battle + +CHAR16 LargeTacticalStr[][ LARGE_STRING_LENGTH ] = +{ + L"Вы потерпели поражение в этом секторе!", + L"Рептионы, не испытывая угрызений совести, пожрут всех до единого!", //пр + L"Ваши бойцы захвачены в плен (некоторые без сознания)!", + L"Ваши бойцы захвачены в плен.", +}; + + +//Insurance Contract.c +//The text on the buttons at the bottom of the screen. + +STR16 InsContractText[] = +{ + L"Назад", + L"Дальше", + L"Да", //пр + L"Очистить", //пр +}; + + + +//Insurance Info +// Text on the buttons on the bottom of the screen + +STR16 InsInfoText[] = +{ + L"Назад", + L"Дальше" +}; + + + +//For use at the M.E.R.C. web site. Text relating to the player's account with MERC + +STR16 MercAccountText[] = +{ + // Text on the buttons on the bottom of the screen + L"Внести сумму", + L"В начало", + L"Номер счета:", + L"Наемник", + L"Дней", + L"Ставка", //5 + L"Стоимость", + L"Всего:", + L"Вы подтверждаете платеж в размере %s?", //the %s is a string that contains the dollar amount ( ex. "$150" ) +}; + +// Merc Account Page buttons +STR16 MercAccountPageText[] = +{ + // Text on the buttons on the bottom of the screen + L"Назад", + L"Дальше", +}; + +//For use at the M.E.R.C. web site. Text relating a MERC mercenary + + +STR16 MercInfo[] = +{ + L"Здоровье", + L"Проворность", + L"Ловкость", + L"Сила", + L"Лидерство", + L"Интеллект", + L"Уровень опыта", + L"Меткость", + L"Механика", + L"Взрывчатка", + L"Медицина", + + L"Назад", + L"Нанять", + L"Дальше", + L"Дополнительная информация", + L"В начало", + L"Нанят", + L"Oплaтa", + L"в день", + L"Погиб", + + L"Похоже, вы пытаетесь нанять более 18 наемников, а это недопустимо.", + L"Недоступно", +}; + + + +// For use at the M.E.R.C. web site. Text relating to opening an account with MERC + +STR16 MercNoAccountText[] = +{ + //Text on the buttons at the bottom of the screen + L"Открыть счет", + L"Отмена", + L"Вы еще не зарегистрировались. Желаете открыть счет?" +}; + + + +// For use at the M.E.R.C. web site. MERC Homepage + +STR16 MercHomePageText[] = +{ + //Description of various parts on the MERC page + L"Спек Т. Кляйн, основатель и хозяин", + L"Открыть счет", + L"Просмотр счета", + L"Просмотр файлов", + // The version number on the video conferencing system that pops up when Speck is talking + L"Спек Ком v3.2" +}; + +// For use at MiGillicutty's Web Page. + +STR16 sFuneralString[] = +{ + L"Похоронное агентство Макгилликатти: скорбим вместе с семьями усопших с 1983.", + L"Директор по похоронам и бывший наемник А.I.М. - Мюррэй Макгилликатти \"Папаша\", специалист по части похорон.", + L"Всю жизнь Папашу сопровождали смерть и утраты, поэтому он, как никто, познал их тяжесть.", + L"Похоронное агентство Макгилликатти предлагает широкий спектр ритуальных услуг - от жилетки, в которую можно поплакать, до восстановления сильно поврежденных останков.", + L"Похоронное агентство Макгилликатти поможет вам и вашим родственникам покоиться с миром.", + + // Text for the various links available at the bottom of the page + L"ДОСТАВКА ЦВЕТОВ", + L"КОЛЛЕКЦИЯ УРН И ГРОБОВ", + L"УСЛУГИ ПО КРЕМАЦИИ", + L"ПОМОЩЬ В ПРОВЕДЕНИИ ПОХОРОН", + L"ПОХОРОННЫЕ РИТУАЛЫ", + + // The text that comes up when you click on any of the links ( except for send flowers ). + L"К сожалению, наш сайт не закончен, в связи с утратой в семье. Мы постараемся продолжить работу после прочтения завещания и выплат долгов умершего. Сайт вскоре откроется.", + L"Мы искренне сочувствуем вам в это трудное время. Заходите еще." +}; + +// Text for the florist Home page + +STR16 sFloristText[] = +{ + //Text on the button on the bottom of the page + + L"Галерея", + + //Address of United Florist + + L"\"Мы сбросим ваш букет где угодно!\"", + L"1-555-SCENT-ME", + L"333 NoseGay Dr,Seedy City, CA USA 90210", + L"http://www.scent-me.com", + + // detail of the florist page + + L"Мы работаем быстро и эффективно!", + L"Гарантируем доставку на следующий день практически в любой уголок мира. Есть некоторые ограничения.", + L"Гарантируем самые низкие цены в мире!", + L"Покажите нам рекламу более дешевого сервиса и получите 10 бесплатных роз.", + L"\"Крылатая Флора\", занимаемся фауной и цветами с 1981 г.", + L"Наши летчики, бывшие пилоты бомбардировщиков, сбросят ваш букет в радиусе 10 миль от заданного района. Когда угодно и сколько угодно!", + L"Позвольте нам удовлетворить ваши цветочные фантазии.", + L"Пусть Брюс, известный во всем мире садовник, сам соберет вам отличный букет в нашем саду.", + L"И запомните, если у нас нет таких цветов, мы быстро вырастим то, что вам надо!" +}; + + + +//Florist OrderForm + +STR16 sOrderFormText[] = +{ + //Text on the buttons + + L"Назад", + L"Послать", + L"Отмена", + L"Галерея", + + L"Название букета:", + L"Цена:", //5 + L"Номер заказа:", + L"Доставить", + L"Завтра", + L"Как будете в тех краях", + L"Место доставки", //10 + L"Дополнительно", + L"Сломать цветы ($10)", + L"Черные розы ($20)", + L"Увядший букет ($10)", + L"Фруктовый пирог (если есть) ($10)", //15 + L"Текст поздравления:", + L"Ввиду небольшого размера открытки, постарайтесь уложиться в 75 символов.", + L"...или выберите одну из", + + L"СТАНДАРТНЫХ ОТКРЫТОК", + L"Информация о счете",//20 + + //The text that goes beside the area where the user can enter their name + + L"Название:", +}; + + + + +//Florist Gallery.c + +STR16 sFloristGalleryText[] = +{ + //text on the buttons + + L"Назад", //abbreviation for previous + L"Дальше", //abbreviation for next + + L"Выберите букет, которые хотите послать.", + L"Примечание: Если Вам нужно послать увядший или сломанный букет - заплатите еще $10.", + + //text on the button + + L"В начало", +}; + +//Florist Cards + +STR16 sFloristCards[] = +{ + L"Выберите текст, который будет напечатан на открытке.", + L"Назад" +}; + + + +// Text for Bobby Ray's Mail Order Site + +STR16 BobbyROrderFormText[] = +{ + L"Бланк заказа", //Title of the page + L"Штк", // The number of items ordered + L"Вес (%s)", // The weight of the item + L"Название", // The name of the item + L"цена 1 вещи", // the item's weight + L"Итого", //5 // The total price of all of items of the same type + L"Стоимость", // The sub total of all the item totals added + L"ДиУ (см. Место Доставки)", // S&H is an acronym for Shipping and Handling + L"Всего", // The grand total of all item totals + the shipping and handling + L"Место доставки", + L"Скорость доставки", //10 // See below + L"Цена (за %s.)", // The cost to ship the items + L"Экспресс-доставка", // Gets deliverd the next day + L"2 рабочих дня", // Gets delivered in 2 days + L"Обычная доставка", // Gets delivered in 3 days + L"ОЧИСТИТЬ",//15 // Clears the order page + L"ЗАКАЗАТЬ", // Accept the order + L"Назад", // text on the button that returns to the previous page + L"В начало", // Text on the button that returns to the home page + L"* - вещи, бывшие в употреблении", // Disclaimer stating that the item is used + L"Вы не можете это оплатить.", //20 // A popup message that to warn of not enough money + L"<НЕ ВЫБРАНО>", // Gets displayed when there is no valid city selected + L"Вы действительно хотите отправить груз в %s?", // A popup that asks if the city selected is the correct one + L"Вес груза**", // Displays the weight of the package + L"** Мин. вес", // Disclaimer states that there is a minimum weight for the package + L"Заказы", +}; + + +STR16 BobbyRFilter[] = +{ + // Guns + L"Тяжелое", + L"Пистолеты", + L"Авт.пистол.", + L"ПП", + L"Винтовки", + L"Сн.винтовки", + L"Шт.винтовки", + L"Пулеметы", + L"Ружья", + + // Ammo + //L"Heavy W.", + L"Пистолеты", + L"Авт.пистол.", + L"ПП", + L"Винтовки", + L"Сн.винтовки", + L"Шт.винтовки", + L"Пулеметы", + L"Ружья", + + // Used + L"Оружие", + L"Броня", + L"Разгр.с-мы", + L"Разное", + + // Armour + L"Каски", + L"Жилеты", + L"Брюки", + L"Пластины", + + // Misc + L"Режущие", + L"Метательн.", + L"Дробящие", + L"Гранаты", + L"Бомбы", + L"Аптечки", + L"Наборы", + L"Головные", + L"Разгр.с-мы", + L"Разное", +}; + + +// This text is used when on the various Bobby Ray Web site pages that sell items + +STR16 BobbyRText[] = +{ + L"Заказать", // Title + // instructions on how to order + L"Нажмите на товар. Левая кнопка - добавить, правая кнопка - уменьшить. После того как выберете товар, оформите заказ.", + + //Text on the buttons to go the various links + + L"Назад", // + L"Оружие", //3 + L"Патроны", //4 + L"Броня", //5 + L"Разное", //6 //misc is an abbreviation for miscellaneous + L"Б/У", //7 + L"Далее", + L"БЛАНК ЗАКАЗА", + L"В начало", //10 + + //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 + + L"У вашей команды есть",//11 + L"оруж., использующее этот тип боеприпасов", //12 + + //The following lines provide information on the items + + L"Вес:", // Weight of all the items of the same type + L"Кал.:", // the caliber of the gun + L"Маг:", // number of rounds of ammo the Magazine can hold + L"Дист:", // The range of the gun + L"Урон:", // Damage of the weapon + L"Скор:", // Weapon's Rate Of Fire, acronym ROF + L"Цена:", // Cost of the item + L"Склад:", // The number of items still in the store's inventory + L"Штук в заказе:", // The number of items on order + L"Урон:", // If the item is damaged + L"Вес:", // the Weight of the item + L"Итого:", // The total cost of all items on order + L"* %% до износа", // 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"Черт! Эта форма поддерживает не более 10 предметов в одном заказе. Если вы хотите заказать больше (а мы надеемся, вы хотите), то заполните еще один заказ и примите наши извинения за неудобства.", + + // A popup that tells the user that they are trying to order more items then the store has in stock + + L"Извините, но данного товара нет на складе. Попробуйте заглянуть позже.", + + //A popup that tells the user that the store is temporarily sold out + + L"Извините, но данного товара пока нет на складе.", + +}; + + +// Text for Bobby Ray's Home Page + +STR16 BobbyRaysFrontText[] = +{ + //Details on the web site + + L"Здесь вы найдете лучшие и новейшие образцы оружия", + L"Мы снабдим вас всем, что нужно для победы над противником", + L"ВЕЩИ Б/У", + + //Text for the various links to the sub pages + + L"РАЗНОЕ", + L"ОРУЖИЕ", + L"БОЕПРИПАСЫ", //5 + L"БРОНЯ", + + //Details on the web site + + L"Если у нас чего-то нет, то этого нет нигде!", + L"В разработке", +}; + + + +// Text for the AIM page. +// This is the text used when the user selects the way to sort the aim mercanaries on the AIM mug shot page + +STR16 AimSortText[] = +{ + L"А.I.M. Состав", // Title + // Title for the way to sort + L"Сортировка:", + + // sort by... + + L"Цена", + L"Опыт", + L"Меткость", + L"Медицина", + L"Взрывчатка", + L"Механика", + + //Text of the links to other AIM pages + + L"Показать фотографии наемников", + L"Просмотреть информацию о наемниках", + L"Просмотреть архивную галерею A.I.M.", + + // text to display how the entries will be sorted + + L"По возрастанию", + L"По убыванию" +}; + + +//Aim Policies.c +//The page in which the AIM policies and regulations are displayed + +STR16 AimPolicyText[] = +{ + // The text on the buttons at the bottom of the page + + L"Назад", + L"В начало", + L"Оглавление", + L"Дальше", + L"Не согласен", + L"Согласен" +}; + + + +//Aim Member.c +//The page in which the players hires AIM mercenaries + +// Instructions to the user to either start video conferencing with the merc, or to go the mug shot index + +STR16 AimMemberText[] = +{ + L"Левая кнопка мыши", + L"чтобы связаться с бойцом.", + L"Правая кнопка мыши", + L"экран с фотографиями.", +}; + +//Aim Member.c +//The page in which the players hires AIM mercenaries + +STR16 CharacterInfo[] = +{ + // The various attributes of the merc + + L"Здоровье", + L"Проворность", + L"Ловкость", + L"Сила", + L"Лидерство", + L"Интеллект", + L"Уровень опыта", + L"Меткость", + L"Механика", + L"Взрывчатка", + L"Медицина", //10 + + // the contract expenses' area + + L"Гонорар", + L"Срок", + L"1 день", + L"7 дней", + L"14 дней", + + // text for the buttons that either go to the previous merc, + // start talking to the merc, or go to the next merc + + L"<<", + L"Связаться", + L">>", + + L"Дополнительная информация", // Title for the additional info for the merc's bio + L"Действующий состав", //20 // Title of the page + L"Снаряжение:", // Displays the optional gear cost + L"Стоимость Мед. депозита", // If the merc required a medical deposit, this is displayed +}; + + +//Aim Member.c +//The page in which the player's hires AIM mercenaries + +//The following text is used with the video conference popup + +STR16 VideoConfercingText[] = +{ + L"Сумма контракта:", //Title beside the cost of hiring the merc + + //Text on the buttons to select the length of time the merc can be hired + + L"1 день", + L"7 дней", + L"14 дней", + + //Text on the buttons to determine if you want the merc to come with the equipment + + L"Без снаряжения", + L"Со снаряжением", + + // Text on the Buttons + + L"ОПЛАТИТЬ", // to actually hire the merc + L"ОТМЕНА", // go back to the previous menu + L"НАНЯТЬ", // go to menu in which you can hire the merc + L"ОТБОЙ", // stops talking with the merc + L"ЗАКРЫТЬ", + L"СООБЩЕНИЕ", // if the merc is not there, you can leave a message + + //Text on the top of the video conference popup + + L"Видеоконференция с", + L"Подключение. . .", + + L"+ страховка" // Displays if you are hiring the merc with the medical deposit +}; + + + +//Aim Member.c +//The page in which the player hires AIM mercenaries + +// The text that pops up when you select the TRANSFER FUNDS button + +STR16 AimPopUpText[] = +{ + L"ПРОИЗВЕДЕН ЭЛЕКТРОННЫЙ ПЛАТЕЖ", // You hired the merc + L"НЕЛЬЗЯ ПЕРЕВЕСТИ СРЕДСТВА", // Player doesn't have enough money, message 1 + L"НЕ ХВАТАЕТ СРЕДСТВ", // Player doesn't have enough money, message 2 + + // if the merc is not available, one of the following is displayed over the merc's face + + L"На задании", + L"Пожалуйста, оставьте сообщение", + L"Скончался", + + //If you try to hire more mercs than game can support + + L"У вас уже полная команда из наемников.", + + L"Автоответчик", + L"Сообщение оставлено на автоответчике", +}; + + +//AIM Link.c + +STR16 AimLinkText[] = +{ + L"A.I.M. Ссылки", //The title of the AIM links page +}; + + + +//Aim History + +// This page displays the history of AIM + +STR16 AimHistoryText[] = +{ + L"A.I.M. История", //Title + + // Text on the buttons at the bottom of the page + + L"Назад", + L"В начало", + L"A.I.M. Галерея", //$$ + L"Дальше" +}; + + +//Aim Mug Shot Index + +//The page in which all the AIM members' portraits are displayed in the order selected by the AIM sort page. + +STR16 AimFiText[] = +{ + // displays the way in which the mercs were sorted + + L"Цена", + L"Опыт", + L"Меткость", + L"Медицина", + L"Взрывчатка", + L"Механика", + + // The title of the page, the above text gets added at the end of this text + + L"Сортировка состава A.I.M. По возрастанию, критерий - %s", + L"Сортировка состава A.I.M. По убыванию, критерий - %s", + + // Instructions to the players on what to do + + L"Левый щелчок", + L"Выбрать наемника", //10 + L"Правый щелчок", + L"Критерий сортировки", + + // Gets displayed on top of the merc's portrait if they are... + + L"Выбыл", + L"Скончался", //14 + L"На задании", +}; + + + +//AimArchives. +// The page that displays information about the older AIM alumni merc... mercs who are no longer with AIM + +STR16 AimAlumniText[] = +{ + // Text of the buttons + + L"СТР. 1", + L"СТР. 2", + L"СТР. 3", + + L"A.I.M. Галерея", // Title of the page //$$ + + L"ОК" // Stops displaying information on selected merc +}; + + + + + + +//AIM Home Page + +STR16 AimScreenText[] = +{ + // AIM disclaimers + + L"A.I.M. и логотип A.I.M. - зарегистрированные во многих странах торговые марки.", + L"Так что и не думай подражать нам.", + L"(с) 1998-1999 A.I.M., Ltd. Все права защищены.", + + //Text for an advertisement that gets displayed on the AIM page + + L"\"Цветы по всему миру\"", + L"\"Мы сбросим ваш букет где угодно!\"", //10 + L"Сделай как надо", + L"...в первый раз", + L"Если у нас нет такого ствола, то он вам и не нужен.", +}; + + +//Aim Home Page + +STR16 AimBottomMenuText[] = +{ + //Text for the links at the bottom of all AIM pages + L"В начало", + L"Наемники", + L"Архив", //$$ + L"Правила", + L"Информация", + L"Ссылки" +}; + + + +//ShopKeeper Interface +// The shopkeeper interface is displayed when the merc wants to interact with +// the various store clerks scattered through out the game. + +STR16 SKI_Text[ ] = +{ + L"ИМЕЮЩИЕСЯ ТОВАРЫ", //Header for the merchandise available + L"СТР.", //The current store inventory page being displayed + L"ОБЩАЯ ЦЕНА", //The total cost of the the items in the Dealer inventory area + L"ОБЩАЯ ЦЕННОСТЬ", //The total value of items player wishes to sell + L"ОЦЕНКА", //Button text for dealer to evaluate items the player wants to sell + L"ПЕРЕВОД", //Button text which completes the deal. Makes the transaction. + L"УЙТИ", //Text for the button which will leave the shopkeeper interface. + L"ЦЕНА РЕМОНТА", //The amount the dealer will charge to repair the merc's goods + L"1 ЧАС", // SINGULAR! The text underneath the inventory slot when an item is given to the dealer to be repaired + L"%d ЧАСОВ", // PLURAL! The text underneath the inventory slot when an item is given to the dealer to be repaired + L"ИСПРАВНО", // Text appearing over an item that has just been repaired by a NPC repairman dealer + L"Вам уже некуда класть вещи.", //Message box that tells the user there is no more room to put there stuff + L"%d МИНУТ", // The text underneath the inventory slot when an item is given to the dealer to be repaired + L"Выбросить предмет на землю.", +}; + +//ShopKeeper Interface +//for the bank machine panels. Referenced here is the acronym ATM, which means Automatic Teller Machine + +STR16 SkiAtmText[] = +{ + //Text on buttons on the banking machine, displayed at the bottom of the page + L"0", + L"1", + L"2", + L"3", + L"4", + L"5", + L"6", + L"7", + L"8", + L"9", + L"OK", //пр Transfer the money + L"Взять", //пр Take money from the player + L"Дать", //пр Give money to the player + L"Отмена", //пр Cancel the transfer + L"Очистить", //пр Clear the money display +}; + + +//Shopkeeper Interface +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 + L"Введите сумму", //пр Enter the amount to transfer + L"Перевести деньги бойцу", //пр Giving money to the merc + L"Забрать деньги у бойца", //пр Taking money from the merc + L"Недостаточно средств", //пр Not enough money to transfer + L"Баланс", //пр Display the amount of money the player currently has +}; + + +STR16 SkiMessageBoxText[] = +{ + L"Желаете снять со счета %s, чтобы покрыть разницу?", + L"Недостаточно средств. Не хватает %s", + L"Желаете снять со счета %s, чтобы оплатить полную стоимость?", + L"Попросить торговца сделать перевод", + L"Попросить торговца починить выбранные предметы", + L"Закончить беседу", //вспл. подсказка по нажатии кнопки кэнсэл при торговле\ремонте + L"Текущий баланс", +}; + + +//OptionScreen.c + +STR16 zOptionsText[] = +{ + //button Text + L"Сохранить игру", + L"Загрузить игру", + L"Выход", + L"Готово", + + //Text above the slider bars + L"Звуки", + L"Речь", + L"Музыка", + + //Confirmation pop when the user selects.. + L"Выйти из игры и вернуться в главное меню?", + + L"Необходимо выбрать или \"Речь\", или \"Субтитры\"", +}; + + +//SaveLoadScreen +STR16 zSaveLoadText[] = +{ + L"Сохранить", + L"Загрузить", + L"Отмена", + L"Сохранение выбрано", + L"Загрузка выбрана", + + L"Игра успешно сохранена", + L"ОШИБКА сохранения игры!", + L"Игра успешно загружена", + L"ОШИБКА загрузки игры!", + + L"Это сохранение было сделано иной версией игры. Скорее всего, вы не сможете загрузить его. Все равно продолжить?", + L"Версия файла сохранения отличается от текущей версии игры.", + + //Translators, the next two strings are for the same thing. The first one is for beta version releases and the second one + //is used for the final version. Please don't modify the "#ifdef JA2BETAVERSION" or the "#else" or the "#endif" as they are + //used by the compiler and will cause program errors if modified/removed. It's okay to translate the strings though. +#ifdef JA2BETAVERSION + L"Скорее всего, вы не сможете нормально продолжить игру. Все равно продолжить?", +#else + L"Версия файла сохранения отличается от текущей версии игры.", +#endif + + //Translators, the next two strings are for the same thing. The first one is for beta version releases and the second one + //is used for the final version. Please don't modify the "#ifdef JA2BETAVERSION" or the "#else" or the "#endif" as they are + //used by the compiler and will cause program errors if modified/removed. It's okay to translate the strings though. +#ifdef JA2BETAVERSION + L"Вероятно, файлы сохранения повреждены. Желаете удалить их?", +#else + L"Пытаюсь загрузить старую версию файла сохранения. Автоматически обновить и загрузить файл?", +#endif + + L"Вы решили записать игру на существующее сохранение #%d?", + L"Хотите загрузить игру из сохранения #", + + + //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"У вас заканчивается свободное место на жестком диске. Сейчас свободно %d Мб, а требуется %d Мб свободного места для JA.", + + L"Сохраняю...", //When saving a game, a message box with this string appears on the screen + + L"Нормальный", + L"Расширенный", + L"Реалистичный", + L"Фантастический", + + L"Стиль игры", //пр + L"Золотая серия", //Placeholder English + L"Бобби Рей", + L"Нормальный", + L"Большой", + L"Огромный", + L"Все, включая эксклюзив", + + L"Новый инвентарь, используемый в этом релизе, не работает при разрешении экрана 640х480. Измените разрешение и запустит игру заново.", + L"Новый инвентарь не работает, если выбрана по умолчанию игровая папка 'Data'.", +}; + + + +//MapScreen +STR16 zMarksMapScreenText[] = +{ + L"Уровень карты", + L"У вас нет ополченцев. Чтобы они появились, вам нужно склонить на свою сторону горожан.", + L"Доход в сутки", + L"Наемник застрахован", + L"%s не нуждается в отдыхе.", + L"%s на марше и не может лечь спать.", + L"%s валится с ног от усталости, погоди немного.", + L"%s ведет машину.", + L"Отряд не может двигаться, когда один из наемников спит.", + + // stuff for contracts + L"Хотя у вас и есть деньги на подписание контракта, но их не хватит, чтобы оплатить страховку наемника.", + L"%s: продление страховки составит %s за %d дополнительных дней. Желаете заплатить?", + L"Предметы в секторе", + L"Жизнь наемника застрахована.", + + // other items + L"Медики", // people acting a field medics and bandaging wounded mercs + L"Раненые", // people who are being bandaged by a medic + L"Готово", // Continue on with the game after autobandage is complete + L"Стоп", // Stop autobandaging of patients by medics now + L"Извините, этот пункт недоступен в демонстрационной версии.", // informs player this option/button has been disabled in the demo + L"%s: нет инструментов.", + L"%s: нет аптечки.", + L"Здесь недостаточно добровольцев для тренировки.", + L"В %s максимальное количество ополченцев.", + L"У наемника ограниченный контракт.", + L"Контракт наемника не застрахован", + L"Карта Арулько", // 24 +}; + + +STR16 pLandMarkInSectorString[] = +{ + L"Отряд %d заметил кого-то в секторе %s.", +}; + +// confirm the player wants to pay X dollars to build a militia force in town +STR16 pMilitiaConfirmStrings[] = +{ + L"Тренировка отряда ополченцев будет стоить $", // telling player how much it will cost + L"Подтвердить платеж?", // asking player if they wish to pay the amount requested + L"Вы не можете себе этого позволить.", // telling the player they can't afford to train this town + L"Продолжить тренировку в %s (%s %d)?", // continue training this town? + L"Цена $", // the cost in dollars to train militia + L"( Д/Н )", // abbreviated yes/no + L"", // unused + L"Тренировка ополчения в секторе %d будет стоить $%d. %s", // cost to train sveral sectors at once + L"У вас нет $%d, чтобы приступить к тренировке ополчения.", + L"%s: Требуется не менее %d процентов лояльности, чтобы продолжить тренировку ополчения.", + L"Больше вы не можете тренировать ополчение в %s.", +}; + +//Strings used in the popup box when withdrawing, or depositing money from the $ sign at the bottom of the single merc panel +STR16 gzMoneyWithdrawMessageText[] = +{ + L"За один раз вы можете снять со счета не более $20.000.", + L"Вы решили положить %s на свой счет?", +}; + +STR16 gzCopyrightText[] = +{ + L"Aвтopcкиe пpaвa (C) 1999 Sir-Tech Canada Ltd. Bce пpaвa зaщищeны.", +}; + +//option Text +STR16 zOptionsToggleText[] = +{ + L"Речь", + L"Молчаливые герои", //$$ + L"Субтитры", + L"Пауза в диалогах", + L"Анимированный дым", + L"Кровь и жестокость", + L"Не трогать мышь!", + L"Старый метод выбора", + L"Показывать путь движения", + L"Показывать промахи", + L"Игра в реальном времени", + L"Подтверждение сна/подъема", + L"Метрическая система", + L"Движущаяся подсветка бойца", + L"Курсор на бойцов", + L"Курсор на дверь", + L"Мерцание вещей", + L"Показать кроны деревьев", + L"Показывать каркасы", + L"Трехмерный курсор", + L"Показывать шанс попадания", + L"Курсор очереди для гранат", + L"Выпадение всего из врагов", //Весь трофей врага + L"Стрельба гранатой навесом", + L"Классическое прицеливание", + L"Выбор пробелом след. отряда", + L"Тени предметов в инвентаре", + L"Дальность оружия в тайлах", + L"Одиночный трассер", + L"Шум дождя", + L"Вороны", + L"Случайный I.M.P персонаж", + L"Автосохранение каждый ход", + L"Молчаливый пилот вертолета", + L"Низкое использование CPU", +}; + +//This is the help text associated with the above toggles. +STR16 zOptionsScreenHelpText[] = +{ + //speech + L"Включить или выключить\nголос во время диалогов.", + + //Mute Confirmation + L"Включить или выключить речевое\nподтверждение выполнения приказов.", + + //Subtitles + L"Включить или выключить отображение\nсубтитров во время диалогов.", //$$ + + //Key to advance speech + L"Если субтитры включены, выберите этот пункт,\nчтобы успеть прочитать диалоги персонажей.", + + //Toggle smoke animation + L"Отключите анимацию дыма,\nесли он замедляет игру.", + + //Blood n Gore + L"Отключите этот пункт, если боитесь крови.", + + //Never move my mouse + L"Если выключено, то курсор автоматически перемещается\nна кнопку всплывающего окна диалога.", + + //Old selection method + L"Если включено, то будет использоваться старый метод выбора наемников\n(для тех, кто привык к управлению предыдущих частей Jagged Alliance).", + + //Show movement path + L"Если включено, то в режиме реального времени будет отображаться путь передвижения\n(если выключено, нажмите SHIFT, чтобы увидеть путь).", + + //show misses + L"Если включено, то камера будет отслеживать\nтраекторию пуль, прошедших мимо цели.", + + //Real Time Confirmation + L"Если включено, то для приказа на передвижение будет требоваться\nдополнительный, подтверждающий щелчок мыши на месте назначения.", + + //Display the enemy indicator + L"Если включено, то вы получите предупреждение,\nкогда наемники лягут спать или проснутся.", + + //Use the metric system + L"Если включено, то используется метрическая система мер,\nиначе будет британская.", + + //Merc Lighted movement + L"При ходьбе карта подсвечивается вокруг бойца.\nВыключите опцию для повышения производительности системы.", + + //Smart cursor + L"Если включено, то перемещение курсора возле наемника\nавтоматически выбирает его.", + + //snap cursor to the door + L"Если включено, то перемещение курсора возле двери\nавтоматически помещает его на дверь.", + + //glow items + L"Если включено, то все предметы подсвечиваются. (|I)", + + //toggle tree tops + L"Если включено, то отображаются кроны деревьев. (|T)", + + //toggle wireframe + L"Если включено, то у препятствий\nдополнительно показывается каркас. (|W)", //$$ + + L"Если включено, то курсор передвижения\nотображается в 3D. (|Home )", + + // Options for 1.13 + L"Если включено, шанс попадания\nпоказывается над курсором.", + L"Если включено, очередь из гранатомета\nиспользует курсор стрельбы очередями.", + L"Если включено, из убитых врагов\nвыпадает все их снаряжение.", + L"Если включено, гранатометы выстреливают заряд под большим углом к горизонту (|Q).", + L"Если включено, из винтовок нельзя целится\nдольше 4 очков действия.", + L"Если включено, |П|р|о|б|е|л выделяет следующий отряд автоматически.", + L"Если включено, показываются тени предметов в инвентаре.", + L"Если включено, дальность оружия показывается в тайлах.", + L"Если включено, трассирующий эффект\nсоздается одиночным выстрелом.", + L"Если включено, вы услышите шум дождя во время непогоды.", + L"Если включено, вороны присутствуют в игре.", + L"Если включено, персонаж I.M.P будет получать\nслучайную внешность и характеристики.", + L"Если включено, игра будет автоматически сохраняться\nпосле каждого хода игрока.", + L"Если включено, Небесный Всадник\nне будет вас раздражать болтливостью.", + L"Если включено, игра будет использовать\nменьше процессорного времени.", +}; + + +STR16 gzGIOScreenText[] = +{ + L"УСТАНОВКА НАЧАЛА ИГРЫ", + L"Стиль игры", + L"Реалистичный", + L"Фантастический", + L"Золотая серия", //Placeholder English + L"Выбор оружия", + L"Расширенный", + L"Нормальный", + L"Уровень сложности", + L"Легкий", + L"Нормальный", + L"Трудный", + L"БЕЗУМИЕ", + L"Начать игру", + L"Главное меню", + L"Дополнительная сложность", + L"Сохранение в любое время", + L"СТАЛЬНАЯ ВОЛЯ", + L"Отключено в демо-версии", + L"Ассортимент Бобби Рэя", + L"Нормальный", + L"Большой", + L"Огромный", + L"Все, включая эксклюзив", + L"Режим инвентаря", + L"Классический", + L"Новый вариант", + + L"Timed Turns",//hayden + L"Not Timed", + L"Timed Player Turns", + L"Load MP Game", +}; + +STR16 pDeliveryLocationStrings[] = +{ + L"Остин", //Austin, Texas, USA + L"Багдад", //Baghdad, Iraq (Suddam Hussein's home) + L"Драссен", //The main place in JA2 that you can receive items. The other towns are dummy names... + L"Гонконг", //Hong Kong, Hong Kong + L"Бейрут", //Beirut, Lebanon (Middle East) + L"Лондон", //London, England + L"Лос-Анджелес", //Los Angeles, California, USA (SW corner of USA) + L"Медуна", //Meduna -- the other airport in JA2 that you can receive items. + L"Метавира", //The island of Metavira was the fictional location used by JA1 + L"Майами", //Miami, Florida, USA (SE corner of USA) + L"Москва", //Moscow, USSR + L"Нью-Йорк", //New York, New York, USA + L"Оттава", //Ottawa, Ontario, Canada -- where JA2 was made! + L"Париж", //Paris, France + L"Триполи", //Tripoli, Libya (eastern Mediterranean) + L"Токио", //Tokyo, Japan + L"Ванкувер", //Vancouver, British Columbia, Canada (west coast near US border) +}; + +STR16 pSkillAtZeroWarning[] = +{ //This string is used in the IMP character generation. It is possible to select 0 ability + //in a skill meaning you can't use it. This text is confirmation to the player. + L"Вы уверены? Значение 0 означает отсутствие этого навыка вообще." +}; + +STR16 pIMPBeginScreenStrings[] = +{ + L"( до 8 символов )", +}; + +STR16 pIMPFinishButtonText[ 1 ]= +{ + L"Анализ", //пр +}; + +STR16 pIMPFinishStrings[ ]= +{ + L"Спасибо, %s", //%s is the name of the merc +}; + +// the strings for imp voices screen +STR16 pIMPVoicesStrings[] = +{ + L"Голос", +}; + +STR16 pDepartedMercPortraitStrings[ ]= +{ + L"Погиб в бою", + L"Уволен", + L"Другое", +}; + +// title for program +STR16 pPersTitleText[] = +{ + L"Досье", //пр +}; + +// paused game strings +STR16 pPausedGameText[] = +{ + L"Пауза в игре", + L"Продолжить (|P|a|u|s|e)", + L"Пауза (|P|a|u|s|e)", +}; + + +STR16 pMessageStrings[] = +{ + L"Выйти из игры?", + L"Да", + L"ДА", + L"НЕТ", + L"ОТМЕНА", + L"НАНЯТЬ", + L"СОЛГАТЬ", + L"Нет описания.", //Save slots that don't have a description. + L"Игра сохранена.", + L"Игра сохранена.", + L"QuickSave", //The name of the quicksave file (filename, text reference) + L"SaveGame", //The name of the normal savegame file, such as SaveGame01, SaveGame02, etc. + L"sav", //The 3 character dos extension (represents sav) + L"..\\SavedGames", //The name of the directory where games are saved. + L"День", //пр + L"Наемн", //пр + L"Свободное место", //An empty save game slot + L"Демо", //Demo of JA2 + L"Ловля Багов", //State of development of a project (JA2) that is a debug build + L"Release", //Release build for JA2 + L"пвм", //пр //Abbreviation for Rounds per minute -- the potential # of bullets fired in a minute. + L"мин", //Abbreviation for minute. + L"м", //One character abbreviation for meter (metric distance measurement unit). + L"пуль", //пр //Abbreviation for rounds (# of bullets) + L"кг", //Abbreviation for kilogram (metric weight measurement unit) + L"фунт", //Abbreviation for pounds (Imperial weight measurement unit) + L"В начало", //пр //Home as in homepage on the internet. + L"USD", //Abbreviation to US dollars + L"н/д", //Lowercase acronym for not applicable. + L"Посмотрим что происходит тем временем в другом месте", //Meanwhile + L"%s: прибыл в сектор %s%s", //Name/Squad has arrived in sector A9. Order must not change without notifying + //SirTech + L"Версия", + L"Пустая ячейка быстрого сохр", + L"Эта ячейка зарезервирована для Быстрого Сохранения, которое можно провести с тактической карты или с глобальной карты, нажав клавиши ALT+S.", + L"Открытая", //возможно это про дверь, проверить + L"Закрытая", //возможно это про дверь, проверить + L"У вас заканчивается свободное дисковое пространство. На диске есть всего %sMб свободного места, а для Jagged Alliance 2 требуется %sMб.", + L"Из A.I.M. нанят боец %s.", + L"%s ловит %s.", //'Merc name' has caught 'item' -- let SirTech know if name comes after item. + L"%s принимает препарат.", //'Merc name' has taken the drug + L"%s: отсутствуют навыки в медицине.",//'Merc name' has no medical skill. + + //CDRom errors (such as ejecting CD while attempting to read the CD) + L"Нарушена целостность программы.", + L"ОШИБКА: CD-ROM открыт.", + + //When firing heavier weapons in close quarters, you may not have enough room to do so. + L"Нет места, чтобы вести отсюда огонь.", + + //Can't change stance due to objects in the way... + L"Сейчас нельзя изменить положение тела.", + + //Simple text indications that appear in the game, when the merc can do one of these things. + L"Выкинуть", + L"Бросить", + L"Передать", + + L"%s передан %s.", //"Item" passed to "merc". Please try to keep the item %s before the merc %s, otherwise, + //must notify SirTech. + L"Не хватает места, чтобы передать %s %s.", //pass "item" to "merc". Same instructions as above. + + //A list of attachments appear after the items. Ex: Kevlar vest ( Ceramic Plate 'Attached )' + L" присоединен )", + + //Cheat modes + L"Достигнут чит-уровень один.", + L"Достигнут чит-уровень два.", + + //Toggling various stealth modes + L"Отряд перешел в режим скрытности.", + L"Отряд перешел в обычный режим.", + L"%s теперь в режиме скрытности.", + L"%s теперь в обычном режиме.", + + //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"Каркас зданий ВКЛ.",//$$ + L"Каркас зданий ВЫКЛ.",//$$ + + //These are used in the cheat modes for changing levels in the game. Going from a basement level to + //an upper level, etc. + L"Нельзя подняться с этого уровня...", + L"Нет нижних этажей...", + L"Входим в подвал. Уровень %d...", + L"Покидаем подвал...", + + L".", // used in the shop keeper inteface to mark the ownership of the item eg Red's gun + L"Режим следования ВЫКЛ.", + L"Режим следования ВКЛ.", + L"3D курсор ВЫКЛ.", + L"3D курсор ВКЛ.", + L"Выбран %dй отряд.", + L"Не хватает денег, чтобы заплатить %s ежедневный гонорар %s", //first %s is the mercs name, the seconds is a string containing the salary + L"Нет", + L"%s не может уйти в одиночку.", + L"Файл сохранения был записан под названием SaveGame99.sav. Если необходимо, переименуйте его в SaveGame01 - SaveGame10 и тогда, он станет доступен в экране сохранений.", + L"%s: выпил(а) немного %s.", + L"Посылка прибыла в Драссен.", + L"%s прибудет в точку назначения (сектор %s) в %dй день, примерно в %s.", //first %s is mercs name, next is the sector location and name where they will be arriving in, lastely is the day an the time of arrival + L"В журнал добавлена запись!", + L"Очереди из гранат используют курсор стрельбы очередями (стрельба по площадям возможна)", + L"Очереди из гранат используют курсор метания (стрельба по площадям не возможна)", + L"Выпадение всего снаряжения ВКЛ", + L"Выпадение всего снаряжения ВЫКЛ", + L"Гранатометы стреляют под обычным углом", + L"Гранатометы стреляют навесом", +#ifdef JA2BETAVERSION + L"Игра сохранена в ячейку авто-сохранения.", +#endif + L"..\\SavedGames\\MP_SavedGames", //The name of the directory where games are saved. + L"Client", +}; + + +CHAR16 ItemPickupHelpPopup[][40] = +{ + L"Взять", + L"Вверх", + L"Выбрать все", + L"Вниз", + L"Отмена" +}; + +STR16 pDoctorWarningString[] = +{ + L"%s слишком далеко, чтобы подлечиться.", + L"Ваши медики не могут оказать первую помощь всем раненым.", +}; + +STR16 pMilitiaButtonsHelpText[] = +{ + L"Уменьшить (правя кнопка)\nУвеличить (левая кнопка)\nчисло новобранцев", // button help text informing player they can pick up or drop militia with this button + L"Уменьшить (правая кнопка)\nУвеличить (левая кнопка)\nчисло рядовых", + L"Уменьшить (правая кнопка)\nУвеличить (левая кнопка)\nчисло элитных солдат", + L"Равномерно распределить\nополченцев по всем секторам.", +}; + +STR16 pMapScreenJustStartedHelpText[] = +{ + L"Отправляйтесь в A.I.M. и наймите бойцов (*Подсказка* - это в ноутбуке).", // to inform the player to hired some mercs to get things going + L"Когда будете готовы отправиться в Арулько, включите сжатие времени в правом нижнем углу экрана.", // to inform the player to hit time compression to get the game underway +}; + +STR16 pAntiHackerString[] = +{ + L"Ошибка. Пропущен или испорчен файл(ы). Игра прекращает работу.", +}; + + +STR16 gzLaptopHelpText[] = +{ + //Buttons: + L"Просмотреть почту", + L"Посетить Интернет сайты", + L"Просмотреть полученные данные", + L"Просмотреть журнал последних событий", + L"Показать информацию о команде", + L"Просмотреть финансовые отчеты", + L"Закрыть ноутбук", + + //Bottom task bar icons (if they exist): + L"Получена новая почта", + L"Получены новые данные", + + //Bookmarks: + L"Международная Ассоциация Наемников A.I.M.", + L"Бобби Рэй - заказ оружия через Интернет", + L"Институт Изучения Личности Наемника I.M.P.", + L"Центр рекрутов M.E.R.C.", + L"Похоронная служба Макгилликатти", + L"'Цветы по всему миру'", + L"Страховые агенты по контрактам A.I.M.", +}; + + +STR16 gzHelpScreenText[] = +{ + L"Закрыть экран помощи", +}; + +STR16 gzNonPersistantPBIText[] = +{ + L"Идет бой. Вы можете отступить только через тактический экран.", + L"Войти в сектор, чтобы продолжить бой. (|E)", + L"Провести бой автоматически (|A).", + L"Во время атаки врага автоматическую битву включить нельзя.", + L"После того как вы попали в засаду, автоматическую битву включить нельзя.", + L"Рядом рептионы - автоматическую битву включить нельзя.", + L"Рядом враждебные гражданские - автоматическую битву включить нельзя.", + L"Рядом кошки-убийцы - автоматическую битву включить нельзя.", + L"ИДЕТ БОЙ", + L"Сейчас вы не можете отступить.", +}; + +STR16 gzMiscString[] = +{ + L"Ваши ополченцы продолжают бой без помощи наемников...", + L"Сейчас машине топливо не требуется.", + L"Топливный бак полон на %d%%.", + L"%s полностью под контролем Дейдраны.", + L"Вы потеряли заправочную станцию.", +}; + +STR16 gzIntroScreen[] = +{ + L"Не удается найти вступительный видеоролик", +}; + +// 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 +// report a noise. +// e.g. "Sidney hears a loud sound of MOVEMENT coming from the SOUTH." +STR16 pNewNoiseStr[] = +{ + L"%s слышит %s звук %s.", + L"%s слышит %s звук движения %s.", + L"%s слышит %s скрип, идущий %s.", + L"%s слышит %s звук всплеска %s.", + L"%s слышит %s звук удара %s.", //$$ + L"%s слышит %s звук взрыва %s.", + L"%s слышит %s крик %s.", + L"%s слышит %s звук удара %s.", + L"%s слышит %s звук удара %s.", + L"%s слышит %s звон %s.", + L"%s слышит %s грохот %s.", +}; + +STR16 wMapScreenSortButtonHelpText[] = +{ + L"Сортировка по имени (|F|1)", + L"Сортировка по роду деятельности (|F|2)", + L"Сортировка по состоянию сна (|F|3)", + L"Сортировка по месту пребывания (|F|4)", + L"Сортировка по месту назначения (|F|5)", + L"Сортировка по времени контракта (|F|6)", +}; + + + +STR16 BrokenLinkText[] = +{ + L"Ошибка 404", + L"Сайт не найден.", +}; + + +STR16 gzBobbyRShipmentText[] = +{ + L"Последние поступления", + L"Заказ #", + L"Количество", + L"Заказано", +}; + + +STR16 gzCreditNames[]= +{ + L"Chris Camfield", + L"Shaun Lyng", + L"Kris Mornes", + L"Ian Currie", + L"Linda Currie", + L"Eric \"WTF\" Cheng", + L"Lynn Holowka", + L"Norman \"NRG\" Olsen", + L"George Brooks", + L"Andrew Stacey", + L"Scot Loving", + L"Andrew \"Big Cheese\" Emmons", + L"Dave \"The Feral\" French", + L"Alex Meduna", + L"Joey \"Joeker\" Whelan", +}; + + +STR16 gzCreditNameTitle[]= +{ + L"Ведущий программист игры", // Chris Camfield !!! + L"Дизайнер/Сценарист", // Shaun Lyng + L"Программист стратегической части и редактора", //Kris Marnes + L"Продюсер/Дизайнер", // Ian Currie + L"Дизайнер/Дизайн карт", // Linda Currie + L"Художник", // Eric \"WTF\" Cheng + L"Тестирование, поддержка", // Lynn Holowka + L"Главный художник", // Norman \"NRG\" Olsen + L"Мастер по звуку", // George Brooks + L"Дизайнер экранов/художник", // Andrew Stacey + L"Ведущий художник/аниматор", // Scot Loving + L"Ведущий программист", // Andrew \"Big Cheese Doddle\" Emmons + L"Программист", // Dave French + L"Программист стратегии и баланса игры", // Alex Meduna + L"Художник-портретист", // Joey \"Joeker\" Whelan", +}; + +STR16 gzCreditNameFunny[]= +{ + L"", // Chris Camfield + L"(Все еще зубрит правила пунктуации)", // Shaun Lyng + L"(\"Я просто вносил исправления.\")", //Kris \"The Cow Rape Man\" Marnes + L"(уже слишком стар для всего этого)", // Ian Currie + L"(также работает над Wizardry 8)", // Linda Currie + L"(тестировал проект под дулом пистолета)", // Eric \"WTF\" Cheng + L"(ушла от нас в CFSA - скатертью дорожка...)", // Lynn Holowka + L"", // Norman \"NRG\" Olsen + L"", // George Brooks + L"(поклонник Мертвой Головы и джаза)", // Andrew Stacey + L"(его настоящее имя Роберт)", // Scot Loving + L"(единственный ответственный человек)", // Andrew \"Big Cheese Doddle\" Emmons + L"(может опять заняться мотогонками)", // Dave French + L"(украден из Wizardry 8!)", // Alex Meduna + L"(еще делал предметы и загрузочные экраны!)", // Joey \"Joeker\" Whelan", +}; + +STR16 sRepairsDoneString[] = +{ + L"%s: завершен ремонт личных вещей.", + L"%s: завершен ремонт всего оружия и брони.", + L"%s: завершен ремонт всей экипировки отряда.", + L"%s: завершен ремонт всех вещей, имеющихся у отряда.", + L"%s: завершен ремонт всех вещей, имеющихся у отряда.", + L"%s: завершен ремонт всех вещей, имеющихся у отряда.", +}; + +STR16 zGioDifConfirmText[]= +{ + L"Вы выбрали ЛЕГКИЙ режим. Этот режим предназначен для тех, кто не знаком с Jagged Alliance и стратегическими играми вообще. Ваш выбор определит ход всей игры, так что будьте осторожны. Вы действительно хотите начать игру в этом режиме?", + L"Вы выбрали НОРМАЛЬНЫЙ режим. Этот режим предназначен для тех, кто знаком с Jagged Alliance или другими подобными играми. Ваш выбор определит ход всей игры, так что будьте осторожны. Вы действительно хотите начать игру в этом режиме?", + L"Вы выбрали ТРУДНЫЙ режим. Предупреждаем: не сетуйте на нас, если вас быстро разгромят. Ваш выбор определит ход всей игры, так что будьте осторожны. Вы действительно хотите начать игру в этом режиме?", + L"Вы выбрали режим БЕЗУМИЕ. Если игра уже пройдена на предыдущих трех уровнях сложности, то нужно подумать о смысле жизни, о происхождении вселенной и вообще... Но если вам все равно на что тратить время и нервы, то можете играть в этом режиме. Страшно?", +}; + +STR16 gzLateLocalizedString[] = +{ + L"%S файл для загрузки экрана не найден...", + + //1-5 + L"Робот не сможет покинуть этот сектор, пока кто-нибудь не возьмет пульт управления.", + + //This message comes up if you have pending bombs waiting to explode in tactical. + L"Сейчас нельзя включить сжатие времени. Дождитесь взрыва!", + + //'Name' refuses to move. + L"%s отказывается подвинуться.", + + //%s a merc name + L"%s: недостаточно очков действия для изменения положения.", + + //A message that pops up when a vehicle runs out of gas. + L"%s: закончилось топливо. Машина осталась в %c%d.", + + //6-10 + + // the following two strings are combined with the pNewNoise[] strings above to report noises + // heard above or below the merc + L"сверху", + L"снизу", + + //The following strings are used in autoresolve for autobandaging related feedback. + L"Никто из ваших наемников не имеет медицинских навыков.", + L"Нечем бинтовать. Ни у кого из наемников нет аптечки.", + L"Чтобы перевязать всех наемников, не хватило бинтов.", + L"Никто из ваших наемников не нуждается в перевязке.", + L"Автоматически перевязывать бойцов.", + L"Все ваши наемники перевязаны.", + + //14 + L"Арулько", + + L"(на крыше)", + + L"Здоровье: %d/%d", + + //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 против %d", + + L"%s полон!", //(ex "The ice cream truck is full") + + L"%s нуждается не в первой помощи или перевязке, а в серьезном лечении и/или отдыхе.", + + //20 + //Happens when you get shot in the legs, and you fall down. + L"Из-за ранения в ногу %s падает на землю!", + //Name can't speak right now. + L"%s сейчас не может говорить", + + //22-24 plural versions @@@2 elite to veteran + L"%d новобранца из ополчения произведены в элитных солдат.", + L"%d новобранца из ополчения произведены в рядовые.", + L"%d рядовых ополченца произведены в элитных солдат.", + + //25 + L"Кнопка", + + //26 + //Name has gone psycho -- when the game forces the player into burstmode (certain unstable characters) + L"%s приступ безумия!", + + //27-28 + //Messages why a player can't time compress. + L"Сейчас небезопасно включать сжатие времени - у вас есть наемники в секторе %s.", // + L"Сейчас небезопасно включать сжатие времени - у вас есть наемники в пещерах с жуками.", // + + //29-31 singular versions @@@2 elite to veteran + L"1 новобранец из ополчения стал элитным солдатом.", + L"1 новобранец из ополчения стал рядовым ополченцем.", + L"1 рядовой ополченец стал элитным солдатом.", + + //32-34 + L"%s ничего не говорит.", + L"Выбраться на поверхность?", + L"(%dй отряд)", + + //35 + //Ex: "Red has repaired Scope's MP5K". Careful to maintain the proper order (Red before Scope, Scope before MP5K) + L"%s отремонтировал(а) у %s %s", + + //36 + L"ГЕПАРД", + + //37-38 "Name trips and falls" + L"%s спотыкается и падает.", + L"Этот предмет отсюда взять невозможно.", + + //39 + L"Оставшиеся наемники не могут сражаться. Сражение с тварями продолжат ополченцы.", + + //40-43 + //%s is the name of merc. + L"%s: закончились медикаменты!", + L"%s: недостаточно навыков для лечения.", + L"%s: закончился ремонтный набор!", + L"%s: недостаточно навыков для ремонта.", //проверить! пишет когда все предметы отремонтированы "%s lacks the necessary skill to repair anything!" + + //44-45 + L"Время ремонта", + L"%s не видит этого человека.", + + //46-48 + L"%s: отвалилась ствольная насадка!", + L"В одном секторе может быть не более %d тренеров ополчения.", + L"Вы уверены?", + + //49-50 + L"Сжатие времени.", + L"Бак машины полон.", + + //51-52 Fast help text in mapscreen. + L"Возобновить сжатие времени (|П|р|о|б|е|л)", + L"Прекратить сжатие времени (|E|s|c)", + + //53-54 "Magic has unjammed the Glock 18" or "Magic has unjammed Raven's H&K G11" + L"%s починил(а) %s", + L"%s починил(а) %s (%s)", + + //55 + L"Нельзя включить сжатие времени при просмотре предметов в секторе.", + + L"CD Агония Власти не найден. Программа выходит в ОС.", + + L"Предметы успешно совмещены.", + + //58 + //Displayed with the version information when cheats are enabled. + L"Прогресс игры текущий/максимально достигнутый: %d%%/%d%%", + + //59 + L"Сопроводить Джона и Мэри?", + + L"Кнопка нажата.", //пишет при нажатии кнопки, к примеру кнопка в шкафу шиза + + L"%s чувствует что в бронежилете что-то треснуло!", + L"%s выпустил на %d больше пуль!", + L"%s выпустил на %d пулю больше!", +}; + +STR16 gzCWStrings[] = +{ + L"Нужна ли поддержка ополчения из соседних секторов?", +}; + +// WANNE: Tooltips +STR16 gzTooltipStrings[] = +{ + // Debug info + L"%s|Место: %d\n", + L"%s|Яркость: %d / %d\n", + L"%s|Дистанция до |Цели: %d\n", + L"%s|I|D: %d\n", + L"%s|Приказы: %d\n", + L"%s|Настрой: %d\n", + L"%s|Текущие |A|Ps: %d\n", + L"%s|Текущее |Здоровье: %d\n", + // Full info + L"%s|Каска: %s\n", + L"%s|Жилет: %s\n", + L"%s|Брюки: %s\n", + // Limited, Basic + L"|Броня: ", + L"Каска ", + L"Жилет ", + L"Брюки", + L"Одет", + L"нет брони", + L"%s|П|Н|В: %s\n", + L"нет ПНВ", + L"%s|Противогаз: %s\n", + L"нет противогаза", + L"%s|Голова,|Слот |1: %s\n", + L"%s|Голова,|Слот |2: %s\n", + L"\n(в рюкзаке) ", + L"%s|Оружие: %s ", + L"без оружия", + L"Пистолет", + L"Пистолет-пулемет", + L"Винтовка", + L"Ручной пулемет", + L"Ружье", + L"Нож", + L"Тяжелое оружие", + L"без каски", + L"без бронежилета", + L"без поножей", + L"|Броня: %s\n", +}; + +STR16 New113Message[] = +{ + L"Началась буря.", + L"Буря закончилась.", + L"Начался дождь.", + L"Дождь закончился.", + L"Опасайтесь снайперов...", + L"Огонь на подавление!", //suppression fire! + L"*", //BRST - всегда стабильна по количеству выпущеных пуль + L"***", //AUTO - регулируемая очередь (три звездочки - это потому что она можеть быть намного длиннее очереди с отсечкой) + L"ГР", //гранатомет + L"ГР *", // + L"ГР ***", // + L"Снайпер!", + L"Невозможно разделить деньги из-за предмета на курсоре.", + L"Точка высадки новых наемников перенесена в %s, так как предыдущая точка высадки %s захвачена противником.", + L"Выброшена вещь.", + L"Выброшены все вещи выбранной группы.", + L"Вещь продана голодающему населению Арулько.", + L"Проданы все вещи выбранной группы.", +}; + +// WANNE: This are the email texts, when one of the 4 new 1.13 MERC mercs have levelled up, that Speck sends +// INFO: Do not replace the ± characters. They indicate the (-> Newline) from the edt files +STR16 New113MERCMercMailTexts[] = +{ + // Gaston: Text from Line 39 in Email.edt + L"Пожалуйста, примите к сведению, что с настоящего момента гонорар Гастона увеличивается вследствие повышения его профессионального уровня. ± ± Спек Т. Кляйн ± ", + // Stogie: Text from Line 43 in Email.edt + L"Пожалуйста, примите к сведению, что повышение боевых навыков лейтенанта Хорга 'Сигары' влечет за собой повышение его гонорара. ± ± Спек Т. Кляйн ± ", + // Tex: Text from Line 45 in Email.edt + L"Прошу принять к сведению, что заслуги Текса позволяют ему требовать более достойной оплаты. Поэтому его гонорар был увеличен, чтобы соответствовать его умениям. ± ± Спек Т. Кляйн ± ", + // Biggens: Text from Line 49 in Email.edt + L"Ставим в известность, что отличная работа полковника Фредерика Биггенса заслуживает поощрения в виде повышения гонорара. Постановление считать действительным с текущего момента. ± ± Спек Т. Кляйн ± ", +}; + +// WANNE: These are the missing skills from the impass.edt file +// INFO: Do not replace the ± characters. They indicate the (-> Newline) from the edt files +STR16 MissingIMPSkillsDescriptions[] = +{ + // Sniper + L"Снайпер: У вас глаза ястреба. В свободное время вы развлекаетесь отстреливая крылышки у мух с расстояния 100 метров! ± ", + // Camouflage + L"Маскировка: На вашем фоне кусты выглядят синтетическими! ± ", +}; + +STR16 NewInvMessage[] = +{ + L"В данный момент поднять рюкзак нельзя.", + L"Вы не можете одновременно носить 2 рюкзака.", + L"Вы потеряли свой рюкзак...", + L"Замок рюкзака работает лишь во время битвы.", + L"Вы не можете передвигаться с открытым рюкзаком.", + L"Вы уверены что находитесь в здравом уме и отвечаете за свои действия? И вы в самом деле хотите продать весь хлам этого сектора голодающему населению Арулько?", + L"Вы уверены что находитесь в здравом уме и отвечаете за свои действия? И вы в самом деле хотите выбросить весь хлам, валяющийся в этом секторе?", +}; + +// WANNE - MP: Multiplayer messages +STR16 MPServerMessage[] = +{ + // 0 + L"Initiating RakNet server...", + L"Server started, waiting for connections...", + L"You must now connect with your client to the server by pressing '2'.", + L"Server is already running.", + L"Server failed to start. Terminating.", + // 5 + L"%d/%d clients are ready for realtime-mode.", + L"Server disconnected and shutdown.", + L"Server is not running.", + L"Clients are still loading, please wait...", + L"You cannot change dropzone after the server has started.", +}; + +STR16 MPClientMessage[] = +{ + // 0 + L"Initiating RakNet client...", + L"Connecting to IP: %S ...", + L"Received game settings:", + L"You are already connected.", + L"You are already connecting...", + // 5 + L"Client #%d - '%S' has hired '%s'.", + L"Client #%d - '%S' has hired another merc.", + L"You are ready - Total ready = %d/%d.", + L"You are no longer ready - Total ready = %d/%d.", + L"Starting battle...", + // 10 + L"Client #%d - '%S' is ready - Total ready = %d/%d.", + L"Client #%d - '%S' is no longer ready - Total ready = %d/%d", + L"You are ready. Awaiting other clients... Press 'OK' if you are not ready anymore.", + L"Let us the battle begin!", + L"A client must be running for starting the game.", + // 15 + L"Game cannot start. No mercs are hired...", + L"Awaiting 'OK' from server to unlock the laptop...", + L"Interrupted", + L"Finish from interrupt", + L"Mouse Grid Coordinates:", + // 20 + 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"Sector=%s, Max Clients=%d, Max Mercs=%d, Game_Mode=%d, Same Merc=%d, Damage Multiplier=%f, Enemies=%d, Creatures=%d, Militias=%d, Civilians=%d, Timed Turns=%d, Secs/Tic=%d, Starting Cash=$%d, Tons of Guns=%d, Sci-Fi=%d, Difficulty=%d, Iron-Man=%d, BobbyRays Range=%d, Dis BobbyRay=%d, Dis Aim/Merc Equip=%d, Dis Morale=%d, Testing=%d", + L"Sector=%s, Max Clients=%d, Max Mercs=%d, Game_Mode=%d, Same Merc=%d, Damage Multiplier=%f, Timed Turns=%d, Secs/Tic=%d, Dis BobbyRay=%d, Dis Aim/Merc Equip=%d, Dis Morale=%d, Testing=%d", + // 25 + L"Testing and cheat function '9' is enabled.", + L"New connection: Client #%d - '%S', Edge: %d, Team: %d.", + L"Team: %d.",//not used any more + L"'%s' (client %d - '%S') was killed by '%s' (client %d - '%S')", + L"Kicked client #%d - '%S'", + // 30 + L"Start turn for client number:", + L"Starting turn for client #%d", + L"Requesting for realtime...", + L"Switched back to realtime.", + L"Error: Something went wrong switching back.", + // 35 + L"Unlock laptop for hiring? (Are all clients connected?)", + L"The server has unlocked the laptop. Begin hiring!", + L"Interruptor.", + L"You cannot change dropzone if you are only the client and not the server.", + L"You declined the offer to surrender, because you are in a multiplayer game.", + // 40 + L"All your mercs are wiped dead!", + L"Spectator mode enabled.", + L"You have been defeated!", + L"Sorry, climbing is disable in MP", + L"You Hired '%s'", +}; + +STR16 MPHelp[] = +{ + // 0 + L"Welcome to JAGGED ALLIANCE 2 v1.13 Multiplayer", + L"Press 'F1' for help", + L"Multiplayer controls (from strategy screen)", + L"* first set up ja2_mp.ini *", + L"'1' - Start server", + // 5 + L"'2' - Connect to server", + L"'3' - If server unlock laptop, set client ready for battle", + L"'4' - Quit server and client", + L"'5' - Display mouse coords (from tactical screen)", + L"'7' - Popup dialog for server override panel", + // 10 + L"'F2' - Display secondary help", + L"See readme_mp.html for further details", + L"Tips: (assuming ja2_mp.ini is set up)", + L"* Make sure all clients have unique CLIENT_NUM *", + L"* Game save doesn't record bobby rays order *", + // 15 + L"* Avoid placing opposed mercs in immediate sight *", + L"'F1' - Display primary help", +}; + +#endif //RUSSIAN diff --git a/Utils/_TaiwaneseText.cpp b/Utils/_TaiwaneseText.cpp index 45b07a34..e20cb286 100644 --- a/Utils/_TaiwaneseText.cpp +++ b/Utils/_TaiwaneseText.cpp @@ -207,7 +207,11 @@ CHAR16 TeamTurnString[][STRING_LENGTH] = L"Creatures' Turn", L"Militia's Turn", L"Civilians' Turn", - // planning turn + L"Player_Plan",// planning turn + L"Client #1",//hayden + L"Client #2",//hayden + L"Client #3",//hayden + L"Client #4",//hayden }; CHAR16 Message[][STRING_LENGTH] = @@ -3112,7 +3116,7 @@ STR16 AimPopUpText[] = //If you try to hire more mercs than game can support - L"You have a full team of 18 mercs already.", + L"You have a full team of mercs already.", L"Pre-recorded message", L"Message recorded", @@ -3615,6 +3619,11 @@ STR16 gzGIOScreenText[] = L"Inventory System", L"Old", L"New", + + L"Timed Turns",//hayden + L"Not Timed", + L"Timed Player Turns", + L"Load MP Game", }; STR16 pDeliveryLocationStrings[] = @@ -3799,6 +3808,8 @@ STR16 pMessageStrings[] = #ifdef JA2BETAVERSION L"Successfully Saved the Game into the End Turn Auto Save slot.", #endif + L"..\\SavedGames\\MP_SavedGames", //The name of the directory where games are saved. + L"Client", }; @@ -4271,4 +4282,105 @@ STR16 NewInvMessage[] = L"Are you sure you want to delete all sector items?", }; +// WANNE - MP: Multiplayer messages +STR16 MPServerMessage[] = +{ + // 0 + L"Initiating RakNet server...", + L"Server started, waiting for connections...", + L"You must now connect with your client to the server by pressing '2'.", + L"Server is already running.", + L"Server failed to start. Terminating.", + // 5 + L"%d/%d clients are ready for realtime-mode.", + L"Server disconnected and shutdown.", + L"Server is not running.", + L"Clients are still loading, please wait...", + L"You cannot change dropzone after the server has started.", +}; + +STR16 MPClientMessage[] = +{ + // 0 + L"Initiating RakNet client...", + L"Connecting to IP: %S ...", + L"Received game settings:", + L"You are already connected.", + L"You are already connecting...", + // 5 + L"Client #%d - '%S' has hired '%s'.", + L"Client #%d - '%S' has hired another merc.", + L"You are ready - Total ready = %d/%d.", + L"You are no longer ready - Total ready = %d/%d.", + L"Starting battle...", + // 10 + L"Client #%d - '%S' is ready - Total ready = %d/%d.", + L"Client #%d - '%S' is no longer ready - Total ready = %d/%d", + L"You are ready. Awaiting other clients... Press 'OK' if you are not ready anymore.", + L"Let us the battle begin!", + L"A client must be running for starting the game.", + // 15 + L"Game cannot start. No mercs are hired...", + L"Awaiting 'OK' from server to unlock the laptop...", + L"Interrupted", + L"Finish from interrupt", + L"Mouse Grid Coordinates:", + // 20 + 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"Sector=%s, Max Clients=%d, Max Mercs=%d, Game_Mode=%d, Same Merc=%d, Damage Multiplier=%f, Enemies=%d, Creatures=%d, Militias=%d, Civilians=%d, Timed Turns=%d, Secs/Tic=%d, Starting Cash=$%d, Tons of Guns=%d, Sci-Fi=%d, Difficulty=%d, Iron-Man=%d, BobbyRays Range=%d, Dis BobbyRay=%d, Dis Aim/Merc Equip=%d, Dis Morale=%d, Testing=%d", + L"Sector=%s, Max Clients=%d, Max Mercs=%d, Game_Mode=%d, Same Merc=%d, Damage Multiplier=%f, Timed Turns=%d, Secs/Tic=%d, Dis BobbyRay=%d, Dis Aim/Merc Equip=%d, Dis Morale=%d, Testing=%d", + // 25 + L"Testing and cheat function '9' is enabled.", + L"New connection: Client #%d - '%S', Edge: %d, Team: %d.", + L"Team: %d.",//not used any more + L"'%s' (client %d - '%S') was killed by '%s' (client %d - '%S')", + L"Kicked client #%d - '%S'", + // 30 + L"Start turn for client number:", + L"Starting turn for client #%d", + L"Requesting for realtime...", + L"Switched back to realtime.", + L"Error: Something went wrong switching back.", + // 35 + L"Unlock laptop for hiring? (Are all clients connected?)", + L"The server has unlocked the laptop. Begin hiring!", + L"Interruptor.", + L"You cannot change dropzone if you are only the client and not the server.", + L"You declined the offer to surrender, because you are in a multiplayer game.", + // 40 + L"All your mercs are wiped dead!", + L"Spectator mode enabled.", + L"You have been defeated!", + L"Sorry, climbing is disable in MP", + L"You Hired '%s'", +}; + +STR16 MPHelp[] = +{ + // 0 + L"Welcome to JAGGED ALLIANCE 2 v1.13 Multiplayer", + L"Press 'F1' for help", + L"Multiplayer controls (from strategy screen)", + L"* first set up ja2_mp.ini *", + L"'1' - Start server", + // 5 + L"'2' - Connect to server", + L"'3' - If server unlock laptop, set client ready for battle", + L"'4' - Quit server and client", + L"'5' - Display mouse coords (from tactical screen)", + L"'7' - Popup dialog for server override panel", + // 10 + L"'F2' - Display secondary help", + L"See readme_mp.html for further details", + L"Tips: (assuming ja2_mp.ini is set up)", + L"* Make sure all clients have unique CLIENT_NUM *", + L"* Game save doesn't record bobby rays order *", + // 15 + L"* Avoid placing opposed mercs in immediate sight *", + L"'F1' - Display primary help", +}; + #endif //TAIWANESE diff --git a/gameloop.cpp b/gameloop.cpp index a1b6b403..1e8f1e15 100644 --- a/gameloop.cpp +++ b/gameloop.cpp @@ -37,6 +37,8 @@ #include "Rain.h" // end rain +//network headers +#include "connect.h" UINT32 guiCurrentScreen; UINT32 guiPendingScreen = NO_PENDING_SCREEN; @@ -93,6 +95,9 @@ BOOLEAN InitializeGame(void) giStartingMemValue = MemGetFree( ); //InitializeLua(); + is_networked = FALSE; + is_client = FALSE; + is_server = FALSE; ClearAllDebugTopics(); RegisterJA2DebugTopic( TOPIC_JA2OPPLIST, "Reg" ); @@ -136,7 +141,10 @@ BOOLEAN InitializeGame(void) LoadGameSettings(); //Initialize the Game options ( Gun nut, scifi and dif. levels - InitGameOptions(); + + // WANNE - MP: Moved InitGameOptions() to MainMenuScreen::MenuButtonCallback() + // because in this function "is_networked" is not set, so it is too early! + //InitGameOptions(); // preload mapscreen graphics HandlePreloadOfMapGraphics( ); @@ -371,7 +379,11 @@ void GameLoop(void) Sleep(sleeptime); } #endif - +if ( is_networked ) + { + client_packet(); + server_packet(); + } //DebugMsg (TOPIC_JA2,DBG_LEVEL_3,"GameLoop done"); } diff --git a/gamescreen.cpp b/gamescreen.cpp index aecb808c..1327ae07 100644 --- a/gamescreen.cpp +++ b/gamescreen.cpp @@ -88,6 +88,7 @@ #include "Scheduling.h" #endif +#include "connect.h" #define ARE_IN_FADE_IN( ) ( gfFadeIn || gfFadeInitialized ) @@ -554,7 +555,7 @@ UINT32 MainGameScreenHandle(void) { if ( gTacticalStatus.fEnemySightingOnTheirTurn ) { - if ( ( GetJA2Clock( ) - gTacticalStatus.uiTimeSinceDemoOn ) > 3000 ) + if ( (( GetJA2Clock( ) - gTacticalStatus.uiTimeSinceDemoOn ) > 3000) || is_client)//unpause straight away if in MP { if ( gTacticalStatus.ubCurrentTeam != gbPlayerNum ) { @@ -1115,7 +1116,7 @@ void InitHelicopterEntranceByMercs( void ) // WANNE: fix HOT DAY in night at arrival by night. // Explanation: If game starting time + first arrival delay < 07:00 (111600) -> we arrive before the sun rises or // if game starting time + first arrival delay >= 21:00 (162000) -> we arrive after the sun goes down - if( (gGameExternalOptions.iGameStartingTime + gGameExternalOptions.iFirstArrivalDelay) < 111600 || + if( (gGameExternalOptions.iGameStartingTime + gGameExternalOptions. iFirstArrivalDelay) < 111600 || (gGameExternalOptions.iGameStartingTime + gGameExternalOptions.iFirstArrivalDelay >= 162000)) { gubEnvLightValue = 12; diff --git a/ja2_2005Express.vcproj b/ja2_2005Express.vcproj index fafea66c..c588b2da 100644 --- a/ja2_2005Express.vcproj +++ b/ja2_2005Express.vcproj @@ -1,7 +1,7 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/lua/lua.vcproj b/lua/lua.vcproj index f8e3a64e..68f8dada 100644 --- a/lua/lua.vcproj +++ b/lua/lua.vcproj @@ -19,7 +19,7 @@